static kMethod *CompileClosure(KonohaContext *kctx, kNameSpace *ns, kNode *expr, KClass *envCt, kToken *typeTk, kNode **texprRef) { INIT_GCSTACK(); kParam *pa = kNode_GetParamNULL(kctx, expr, typeTk, ns); kMethodVar *mtd = (kMethodVar *) KLIB new_kMethod(kctx, _GcStack, 0, envCt->typeId, 0/*mn*/, NULL); KLIB kMethod_SetParam(kctx, mtd, pa->rtype, pa->psize, (kparamtype_t *)pa->paramtypeItems); int errorCount = KGetParserContext(kctx)->errorMessageCount; KGammaStackDecl lvarItems[32] = {}; struct KGammaLocalData newgma = {}; newgma.flag = 0; newgma.currentWorkingMethod = mtd; newgma.thisClass = envCt; newgma.localScope.varItems = lvarItems; newgma.localScope.capacity = 32; newgma.localScope.varsize = 0; newgma.localScope.allocsize = 0; kNameSpace_InitParam(kctx, ns, &newgma, pa, envCt); KPushGammaStack(ns, &newgma); *texprRef = SUGAR TypeCheckNodeByName(kctx, expr, KSymbol_BlockPattern, ns, KClass_var, TypeCheckPolicy_AllowVoid); kNode *block = SUGAR kNode_GetNode(kctx, expr, KSymbol_BlockPattern, NULL); KLIB kMethod_GenCode(kctx, mtd, block, HatedLazyCompile); KPopGammaStack(ns, &newgma); kMethod_Set(StaticError, mtd, KGetParserContext(kctx)->errorMessageCount > errorCount); RESET_GCSTACK(); return mtd; }
static kbool_t FuelVM_VisitJumpNode(KonohaContext *kctx, KBuilder *builder, kNode *stmt, void *thunk, ksymbol_t label) { kNode *jump = kNode_GetNode(kctx, stmt, label); DBG_ASSERT(jump != NULL && IS_Node(jump)); Block *target = kNode_GetTargetBlock(kctx, jump, label); IRBuilder_JumpTo(BLD(builder), target); return true; }
static kbool_t FuelVM_VisitReturnNode(KonohaContext *kctx, KBuilder *builder, kNode *stmt, void *thunk) { kNode *expr = SUGAR kNode_GetNode(kctx, stmt, KSymbol_ExprPattern, NULL); if(expr != NULL && IS_Node(expr) && expr->attrTypeId != KType_void) { SUGAR VisitNode(kctx, builder, expr, thunk); INode *Ret = FuelVM_getExpression(builder); INode *Inst = CreateReturn(BLD(builder), Ret); INode_setType(Inst, ConvertToTypeId(kctx, expr->attrTypeId)); } else { CreateReturn(BLD(builder), 0); } return true; }
static kbool_t SetParamType(KonohaContext *kctx, kNode *stmt, int n, kparamtype_t *p) { kToken *typeToken = SUGAR kNode_GetToken(kctx, stmt, KSymbol_TypePattern, NULL); kNode *expr = SUGAR kNode_GetNode(kctx, stmt, KSymbol_ExprPattern, NULL); DBG_ASSERT(typeToken != NULL); DBG_ASSERT(expr != NULL); if(kNode_isSymbolTerm(expr)) { kToken *tkN = expr->TermToken; p[n].name = tkN->symbol; p[n].attrTypeId = Token_typeLiteral(typeToken); return true; } return false; }
static kbool_t kNode_declClassField(KonohaContext *kctx, kNode *bk, kNameSpace *ns, KClassVar *ct) { size_t i; kbool_t failedOnce = false; for(i = 0; i < kNode_GetNodeListSize(kctx, bk); i++) { kNode *stmt = bk->NodeList->NodeItems[i]; if(stmt->syn->keyword == KSymbol_TypeDeclPattern) { kToken *tk = SUGAR kNode_GetToken(kctx, stmt, KSymbol_TypePattern, NULL); kNode *expr = SUGAR kNode_GetNode(kctx, stmt, KSymbol_ExprPattern, NULL); if(!kNode_AddClassField(kctx, stmt, ns, ct, Token_typeLiteral(tk), expr)) { failedOnce = true; } } } return !(failedOnce); }
static size_t kNode_countFieldSize(KonohaContext *kctx, kNode *bk) { size_t i, c = 0; if(bk != NULL) { for(i = 0; i < kNode_GetNodeListSize(kctx, bk); i++) { kNode *stmt = bk->NodeList->NodeItems[i]; DBG_P("stmt->keyword=%s%s", KSymbol_Fmt2(stmt->syn->keyword)); if(stmt->syn->keyword == KSymbol_TypeDeclPattern) { kNode *expr = SUGAR kNode_GetNode(kctx, stmt, KSymbol_ExprPattern, NULL); if(expr->syn->keyword == KSymbol_COMMA) { c += (kNode_GetNodeListSize(kctx, expr) - 1); } else if(expr->syn->keyword == KSymbol_LET || kNode_IsTerm(expr)) { c++; } } } } return c; }
static kNode *kNode_GetNode(KonohaContext *kctx, kNode *stmt, ksymbol_t kw) { return SUGAR kNode_GetNode(kctx, stmt, kw, NULL); }
static kNode* kNode_getFirstNode(KonohaContext *kctx, kNode *stmt) { return SUGAR kNode_GetNode(kctx, stmt, KSymbol_ExprPattern, NULL); }
static kNode* kNode_getElseBlock(KonohaContext *kctx, kNode *stmt) { return SUGAR kNode_GetNode(kctx, stmt, KSymbol_else, K_NULLBLOCK); }
static kbool_t FuelVM_VisitLoopNode(KonohaContext *kctx, KBuilder *builder, kNode *stmt, void *thunk, enum LoopType Loop) { Block *HeadBB = CreateBlock(BLD(builder)); Block *BodyBB = CreateBlock(BLD(builder)); Block *ItrBB = CreateBlock(BLD(builder)); Block *MergeBB = CreateBlock(BLD(builder)); kNode_SetLabelBlock(kctx, stmt, KSymbol_("continue"), ItrBB); kNode_SetLabelBlock(kctx, stmt, KSymbol_("break"), MergeBB); kNode *itrBlock = SUGAR kNode_GetNode(kctx, stmt, KSymbol_("Iterator"), NULL); if(itrBlock != NULL) { assert(Loop == ForLoop); IRBuilder_JumpTo(BLD(builder), HeadBB); } else if(Loop == WhileLoop) { /* [WhileStmt] * "Head" is Join Node * Head : if(COND) { goto Body } else {goto Merge } * Body : Body * ... * goto Itr * Itr : Body3 * goto Head * Merge : ... */ IRBuilder_JumpTo(BLD(builder), HeadBB); } else { /* [LoopStmt] (e.g. do-while loop) * "Body" is Join Node * Body : Body * ... * goto Itr * Itr : Body3 * goto Head * Head : if(COND) { goto Body } else {goto Merge } * Merge : ... */ IRBuilder_JumpTo(BLD(builder), BodyBB); } { /* Head */ IRBuilder_setBlock(BLD(builder), HeadBB); SUGAR VisitNode(kctx, builder, kNode_getFirstNode(kctx, stmt), thunk); CreateBranch(BLD(builder), FuelVM_getExpression(builder), BodyBB, MergeBB); } { /* Body */ IRBuilder_setBlock(BLD(builder), BodyBB); SUGAR VisitNode(kctx, builder, kNode_getFirstBlock(kctx, stmt), thunk); IRBuilder_JumpTo(BLD(builder), ItrBB); /* Itr */ IRBuilder_setBlock(BLD(builder), ItrBB); if(itrBlock != NULL) { SUGAR VisitNode(kctx, builder, itrBlock, thunk); } IRBuilder_JumpTo(BLD(builder), HeadBB); } IRBuilder_setBlock(BLD(builder), MergeBB); return true; }
/* Konoha AST API */ static kNode* kNode_getFirstBlock(KonohaContext *kctx, kNode *stmt) { return SUGAR kNode_GetNode(kctx, stmt, KSymbol_BlockPattern, K_NULLBLOCK); }