static KMETHOD Statement_class(KonohaContext *kctx, KonohaStack *sfp) { VAR_Statement(stmt, gma); kToken *tokenClassName = SUGAR kStmt_GetToken(kctx, stmt, SYM_("$ClassName"), NULL); kNameSpace *ns = Stmt_ns(stmt); int isNewlyDefinedClass = false; KonohaClassVar *definedClass = (KonohaClassVar *)KLIB kNameSpace_GetClassByFullName(kctx, ns, S_text(tokenClassName->text), S_size(tokenClassName->text), NULL); if(definedClass == NULL) { // Already defined kshortflag_t cflag = kStmt_ParseClassFlag(kctx, stmt, kClass_Virtual); KMakeTraceUL(trace, sfp, stmt->uline); definedClass = kNameSpace_DefineClassName(kctx, ns, cflag, tokenClassName->text, trace); isNewlyDefinedClass = true; } kBlock *bk = kStmt_ParseClassBlockNULL(kctx, stmt, tokenClassName); size_t declsize = kBlock_countFieldSize(kctx, bk); if(isNewlyDefinedClass) { // Already defined KonohaClass *superClass = CT_Object; kToken *tokenSuperClass= SUGAR kStmt_GetToken(kctx, stmt, SYM_("extends"), NULL); if(tokenSuperClass != NULL) { DBG_ASSERT(Token_isVirtualTypeLiteral(tokenSuperClass)); superClass = CT_(Token_typeLiteral(tokenSuperClass)); if(CT_is(Final, superClass)) { SUGAR kStmt_Message2(kctx, stmt, NULL, ErrTag, "%s is final", CT_t(superClass)); KReturnUnboxValue(false); } if(CT_is(Virtual, superClass)) { SUGAR kStmt_Message2(kctx, stmt, NULL, ErrTag, "%s is still virtual", CT_t(superClass)); KReturnUnboxValue(false); } } size_t initsize = (bk != NULL) ? declsize : initFieldSizeOfVirtualClass(superClass); KonohaClass_InitField(kctx, definedClass, superClass, initsize); } else { if(declsize > 0 && !CT_is(Virtual, definedClass)) { SUGAR kStmt_Message2(kctx, stmt, NULL, ErrTag, "%s has already defined", CT_t(definedClass)); KReturnUnboxValue(false); } } if(bk != NULL) { if(!kBlock_declClassField(kctx, bk, gma, definedClass)) { KReturnUnboxValue(false); } CT_set(Virtual, definedClass, false); } kToken_setTypeId(kctx, tokenClassName, ns, definedClass->typeId); kBlock_AddMethodDeclStmt(kctx, bk, tokenClassName, stmt); kStmt_done(kctx, stmt); KReturnUnboxValue(true); }
//## Expr Stmt.printError(String msg); static KMETHOD Stmt_Message2rintError(KonohaContext *kctx, KonohaStack *sfp) { kStmt *stmt = sfp[0].asStmt; kString *msg = sfp[1].asString; SUGAR kStmt_Message2(kctx, stmt, NULL, ErrTag, "%s", S_text(msg)); KReturn(K_NULLEXPR); }
//## Expr Stmt.message(int error, Expr expr, String msg); static KMETHOD StmtExpr_Message(KonohaContext *kctx, KonohaStack *sfp) { kStmt *stmt = sfp[0].asStmt; kinfotag_t level = (kinfotag_t)sfp[1].intValue; kString *msg = sfp[3].asString; KReturn(SUGAR kStmt_Message2(kctx, stmt, sfp[2].asToken, level, "%s", S_text(msg))); }
static kbool_t kStmt_AddClassField(KonohaContext *kctx, kStmt *stmt, kGamma *gma, KonohaClassVar *definedClass, kshortflag_t flag, ktype_t ty, kExpr *expr) { if(Expr_isTerm(expr)) { // String name kString *name = expr->termToken->text; ksymbol_t symbol = ksymbolA(S_text(name), S_size(name), SYM_NEWID); KLIB KonohaClass_AddField(kctx, definedClass, flag, ty, symbol); return true; } else if(expr->syn->keyword == KW_LET) { // String name = "naruto"; kExpr *lexpr = kExpr_at(expr, 1); if(Expr_isTerm(lexpr)) { kString *name = lexpr->termToken->text; ksymbol_t symbol = ksymbolA(S_text(name), S_size(name), SYM_NEWID); kExpr *vexpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, 2, gma, ty, 0); if(vexpr == K_NULLEXPR) return false; if(vexpr->build == TEXPR_CONST) { KLIB KonohaClass_AddField(kctx, definedClass, flag, ty, symbol); KonohaClass_setClassFieldObjectValue(kctx, definedClass, symbol, vexpr->objectConstValue); } else if(vexpr->build == TEXPR_NCONST) { KLIB KonohaClass_AddField(kctx, definedClass, flag, ty, symbol); KonohaClass_setClassFieldUnboxValue(kctx, definedClass, symbol, vexpr->unboxConstValue); } else if(vexpr->build == TEXPR_NULL) { KLIB KonohaClass_AddField(kctx, definedClass, flag, ty, symbol); } else { SUGAR kStmt_Message2(kctx, stmt, lexpr->termToken, ErrTag, "field initial value must be const: %s", S_text(name)); return false; } return true; } } else if(expr->syn->keyword == KW_COMMA) { // String (firstName = naruto, lastName) size_t i; for(i = 1; i < kArray_size(expr->cons); i++) { if(!kStmt_AddClassField(kctx, stmt, gma, definedClass, flag, ty, kExpr_at(expr, i))) return false; } return true; } SUGAR kStmt_Message2(kctx, stmt, NULL, ErrTag, "field name is expected"); return false; }
static KMETHOD Statement_syntax(KonohaContext *kctx, KonohaStack *sfp) { kbool_t r = 0; VAR_Statement(stmt, gma); kTokenArray *tokenList = (kTokenArray *)kStmt_GetObject(kctx, stmt, KW_TokenPattern, NULL); if(tokenList == NULL) { SUGAR kStmt_Message2(kctx, stmt, NULL, ErrTag, "empty syntax"); } if(tokenList != NULL) { if(!IS_Array(tokenList)) { // create tokenList from a Token kTokenArray *a = new_(TokenArray, 0, OnGcStack); KLIB kArray_Add(kctx, a, tokenList); tokenList = a; } DBG_ASSERT(IS_Array(tokenList)); kNameSpace *ns = Stmt_ns(stmt); SugarSyntaxVar *syn = kNameSpace_guessSyntaxFromTokenList(kctx, ns, tokenList); if(syn != NULL) { if(syn->syntaxPatternListNULL_OnList != NULL) { SUGAR kStmt_Message2(kctx, stmt, NULL, InfoTag, "oveloading syntax: %s%s", PSYM_t(syn->keyword)); } else { syn->syntaxPatternListNULL_OnList = new_(TokenArray, 0, ns->NameSpaceConstList); } TokenSeq tokens = {ns, tokenList, 0, kArray_size(tokenList)}; // Referred to kNameSpace_ParseSyntaxPattern in ast.h. kArray *patternList = syn->syntaxPatternListNULL_OnList; size_t firstPatternIdx = kArray_size(patternList); SUGAR kArray_AddSyntaxRule(kctx, patternList, &tokens); if(firstPatternIdx < kArray_size(patternList)) { kToken *firstPattern = patternList->TokenItems[firstPatternIdx]; if(kToken_isFirstPattern(firstPattern)) { kNameSpace_AppendArrayRef(kctx, ns, &((kNameSpaceVar *)ns)->stmtPatternListNULL_OnList, UPCAST(firstPattern)); } } r = 1; } kStmt_done(kctx, stmt); } KReturnUnboxValue(r); }
static kMethod *Object_newProtoSetterNULL(KonohaContext *kctx, kStmt *stmt, kObject *o, ktype_t ty, ksymbol_t symbol) { ktype_t cid = O_typeId(o); kNameSpace *ns = Stmt_ns(stmt); kMethod *mtd = KLIB kNameSpace_GetSetterMethodNULL(kctx, ns, cid, symbol, TY_var); if(mtd != NULL) { SUGAR kStmt_Message2(kctx, stmt, NULL, ErrTag, "already defined name: %s", SYM_t(symbol)); return NULL; } mtd = KLIB kNameSpace_GetGetterMethodNULL(kctx, ns, cid, symbol, TY_var); if(mtd != NULL && Method_returnType(mtd) != ty) { SUGAR kStmt_Message2(kctx, stmt, NULL, ErrTag, "differently defined name: %s", SYM_t(symbol)); return NULL; } int flag = kField_Setter; if(mtd == NULL) { // no getter flag |= kField_Getter; } KLIB KonohaClass_AddField(kctx, O_ct(o), flag, ty, symbol); return KLIB kNameSpace_GetSetterMethodNULL(kctx, ns, cid, symbol, ty); }
static KMETHOD TypeCheck_Getter(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, expr, gma, reqty); kToken *tkN = expr->cons->TokenItems[0]; ksymbol_t fn = tkN->resolvedSymbol; kExpr *self = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, 1, gma, TY_var, 0); kNameSpace *ns = Stmt_ns(stmt); if(self != K_NULLEXPR) { kMethod *mtd = KLIB kNameSpace_GetGetterMethodNULL(kctx, ns, self->ty, fn, TY_var); if(mtd != NULL) { KFieldSet(expr->cons, expr->cons->MethodItems[0], mtd); KReturn(SUGAR kStmtkExpr_TypeCheckCallParam(kctx, stmt, expr, mtd, gma, reqty)); } SUGAR kStmt_Message2(kctx, stmt, tkN, ErrTag, "undefined field: %s", S_text(tkN->text)); } }
static void kBlock_AddMethodDeclStmt(KonohaContext *kctx, kBlock *bk, kToken *tokenClassName, kStmt *classStmt) { if(bk != NULL) { size_t i; for(i = 0; i < kArray_size(bk->StmtList); i++) { kStmt *stmt = bk->StmtList->StmtItems[i]; if(stmt->syn->keyword == KW_TypeDeclPattern) continue; if(stmt->syn->keyword == KW_MethodDeclPattern) { kStmt *lastStmt = classStmt; KLIB kObject_setObject(kctx, stmt, SYM_("ClassName"), TY_Token, tokenClassName); SUGAR kBlock_InsertAfter(kctx, lastStmt->parentBlockNULL, lastStmt, stmt); lastStmt = stmt; } else { SUGAR kStmt_Message2(kctx, stmt, NULL, WarnTag, "%s is not available within the class clause", PSYM_t(stmt->syn->keyword)); } } } }