static kbool_t CollectLocalVar_VisitReturnNode(KVISITOR_PARAM) { kUntypedNode *expr = KLIB kUntypedNode_GetNode(kctx, node, KSymbol_ExprPattern, NULL); if(expr != NULL && IS_Node(expr) && expr->typeAttr != KType_void) { KLIB VisitNode(kctx, builder, expr, thunk); } return false; }
static kbool_t FuelVM_VisitMethodCallNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk) { kMethod *mtd = CallNode_getMethod(expr); DBG_ASSERT(IS_Method(mtd)); enum TypeId Type = ConvertToTypeId(kctx, expr->attrTypeId); if(mtd->mn == KMethodName_("box")) { Type = ToBoxType(Type); } /* * [CallExpr] := this.method(arg1, arg2, ...) * expr->NodeList = [method, this, arg1, arg2, ...] **/ INode *Inst; if((Inst = CreateSpecialInstruction(kctx, builder, mtd, expr, thunk)) != 0) { INode_setType(Inst, Type); builder->Value = Inst; return true; } int i, s = kMethod_Is(Static, mtd) ? 2 : 1; int argc = CallExpr_getArgCount(expr); INode *Params[argc+2]; if(kMethod_Is(Static, mtd)) { kObject *obj = KLIB Knull(kctx, KClass_(mtd->typeId)); INode *Self = CreateObject(BLD(builder), mtd->typeId, (void *) obj); Params[1] = Self; } for (i = s; i < argc + 2; i++) { kNode *exprN = kNode_At(expr, i); DBG_ASSERT(IS_Node(exprN)); SUGAR VisitNode(kctx, builder, exprN, thunk); INode *Node = FuelVM_getExpression(builder); assert(Node->Type != TYPE_void); Params[i] = Node; } INode *MtdObj = CreateObject(BLD(builder), KType_Method, (void *) mtd); enum CallOp Op = (kMethod_Is(Virtual, mtd)) ? VirtualCall : DefaultCall; Params[0] = MtdObj; kNode *stmt = expr->Parent; assert(IS_Node(stmt)); Inst = CreateICall(BLD(builder), Type, Op, kNode_uline(stmt), Params, argc + 2); builder->Value = Inst; return true; }
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 MiniVM_VisitJumpNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk, ksymbol_t label) { bblock_t target; kUntypedNode *jump = kUntypedNode_GetNode(kctx, node, label); DBG_ASSERT(jump != NULL && IS_Node(jump)); target = kUntypedNode_GetLabelNode(kctx, jump, label); MiniVMBuilder_JumpTo(kctx, builder, target); return true; }
static kbool_t MiniVM_VisitReturnNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk) { kUntypedNode *expr = KLIB kUntypedNode_GetNode(kctx, node, KSymbol_ExprPattern, NULL); if(expr != NULL && IS_Node(expr) && expr->typeAttr != KType_void) { KLIB VisitNode(kctx, builder, expr, thunk); ASM_NMOV(kctx, builder, KClass_(expr->typeAttr), K_RTNIDX, MiniVM_getExpression(builder)); } MiniVMBuilder_JumpTo(kctx, builder, builder->bbReturnId); return false; }
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 MiniVM_VisitMethodCallNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk) { kMethod *mtd = CallNode_getMethod(node); /* * [CallExpr] := this.method(arg1, arg2, ...) * node->NodeList = [method, this, arg1, arg2, ...] **/ intptr_t stackbase, thisidx; int i, s, argc = CallNode_getArgCount(node); DBG_ASSERT(IS_Method(mtd)); s = kMethod_Is(Static, mtd) ? 2 : 1; if(kMethod_Is(Static, mtd)) { KClass *selfTy = KClass_(mtd->typeId); kObject *obj = KLIB Knull(kctx, selfTy); ASM(NSET, OC_(builder->stackbase), (uintptr_t) obj, selfTy); } stackbase = builder->stackbase; thisidx = stackbase + K_CALLDELTA; for (i = s; i < argc + 2; i++) { kUntypedNode *exprN = kUntypedNode_At(node, i); builder->stackbase = thisidx + i - 1; DBG_ASSERT(IS_Node(exprN)); KLIB VisitNode(kctx, builder, exprN, thunk); if(builder->Value != builder->stackbase) { KClass *ty = KClass_(exprN->typeAttr); ASM_NMOV(kctx, builder, ty, builder->stackbase, builder->Value); } } if(kMethod_Is(Final, mtd) || !kMethod_Is(Virtual, mtd)) { ASM(NSET, NC_(thisidx-1), (intptr_t)mtd, KClass_Method); if(kMethod_Is(Virtual, mtd)) { // set namespace to enable method lookups ASM(NSET, OC_(thisidx-2), (intptr_t)kUntypedNode_ns(node), KClass_NameSpace); } } else { ASM(NSET, OC_(thisidx-2), (intptr_t)kUntypedNode_ns(node), KClass_NameSpace); ASM(LOOKUP, SFP_(thisidx), kUntypedNode_ns(node), mtd); } ASM(CALL, kUntypedNode_uline(node), SFP_(thisidx), SFP_(thisidx + argc + 1), KLIB Knull(kctx, KClass_(node->typeAttr))); builder->stackbase = stackbase; builder->Value = builder->stackbase; return true; }
/* copied from src/parser/import/typecheck.h */ static kNode *CallTypeFunc(KonohaContext *kctx, kFunc *fo, kNode *expr, kNameSpace *ns, kObject *reqType) { INIT_GCSTACK(); BEGIN_UnusedStack(lsfp); KUnsafeFieldSet(lsfp[1].asNode, expr); KUnsafeFieldSet(lsfp[2].asNameSpace, ns); KUnsafeFieldSet(lsfp[3].asObject, reqType); CallSugarMethod(kctx, lsfp, fo, 4, UPCAST(K_NULLNODE)); END_UnusedStack(); RESET_GCSTACK(); if(kNode_IsError(expr)) return expr; if(lsfp[K_RTNIDX].asNode == K_NULLNODE) { DBG_ASSERT(expr->attrTypeId == KType_var); // untyped } DBG_ASSERT(IS_Node(lsfp[K_RTNIDX].asObject)); return (kNode *)lsfp[K_RTNIDX].asObject; }
static INode *CreateSpecialInstruction(KonohaContext *kctx, KBuilder *builder, kMethod *mtd, kNode *expr, void *thunk) { ktypeattr_t thisTy = mtd->typeId; kmethodn_t mn = mtd->mn; ktypeattr_t retTy = kMethod_GetReturnType(mtd)->typeId; kParam *params = kMethod_GetParam(mtd); kNode *stmt = expr->Parent; assert(IS_Node(stmt)); if(thisTy == KType_Boolean) { if(params->psize == 0) { /* UnaryOperator */ if(retTy == KType_Boolean) { /* booleaen booleaen.opNEG() */ enum UnaryOp Op = KMethodName_toUnaryOperator(kctx, mn); INode *Param = FetchINode(kctx, builder, expr, 1, KType_Boolean, thunk); return CreateUnaryInst(BLD(builder), Op, Param, kNode_uline(stmt)); } } else if(params->psize == 1) { /* BinaryOperator */ ktypeattr_t ptype = params->paramtypeItems[0].attrTypeId; if(retTy == KType_Boolean && ptype == KType_Boolean) { /* boolean boolean.(opEQ|opNE) (boolean x) */ enum BinaryOp Op = KMethodName_toBinaryOperator(kctx, mn); assert(Op == Eq || Op == Nq); INode *LHS = FetchINode(kctx, builder, expr, 1, KType_Boolean, thunk); INode *RHS = FetchINode(kctx, builder, expr, 2, KType_Boolean, thunk); return CreateBinaryInst(BLD(builder), Op, LHS, RHS, kNode_uline(stmt)); } } } else if(thisTy == KType_Int) { if(params->psize == 0) { /* UnaryOperator */ if(retTy == KType_Int) { /* int int.opSUB() */ enum UnaryOp Op = KMethodName_toUnaryOperator(kctx, mn); INode *Param = FetchINode(kctx, builder, expr, 1, KType_Int, thunk); return CreateUnaryInst(BLD(builder), Op, Param, kNode_uline(stmt)); } } else if(params->psize == 1) { /* BinaryOperator */ ktypeattr_t ptype = params->paramtypeItems[0].attrTypeId; if(retTy == KType_Boolean && ptype == KType_Int) { /* boolean int.(opEQ|opNE|opGT|opGE|opLT|opLE) (int x) */ enum BinaryOp Op = KMethodName_toBinaryOperator(kctx, mn); INode *LHS = FetchINode(kctx, builder, expr, 1, KType_Int, thunk); INode *RHS = FetchINode(kctx, builder, expr, 2, KType_Int, thunk); return CreateBinaryInst(BLD(builder), Op, LHS, RHS, kNode_uline(stmt)); } else if(retTy == KType_Int && ptype == KType_Int) { /* int int.(opADD|opSUB|opMUL|opDIV|opMOD|opLSHIFT|opRSHIFT|opAND|opOR|opXOR) (int x) */ enum BinaryOp Op = KMethodName_toBinaryOperator(kctx, mn); INode *LHS = FetchINode(kctx, builder, expr, 1, KType_Int, thunk); INode *RHS = FetchINode(kctx, builder, expr, 2, KType_Int, thunk); return CreateBinaryInst(BLD(builder), Op, LHS, RHS, kNode_uline(stmt)); } } } else if(FloatIsDefined() && thisTy == KType_float) { if(params->psize == 0) { /* UnaryOperator */ if(retTy == KType_float) { /* int int.opSUB() */ enum UnaryOp Op = KMethodName_toUnaryOperator(kctx, mn); INode *Param = FetchINode(kctx, builder, expr, 1, KType_float, thunk); return CreateUnaryInst(BLD(builder), Op, Param, kNode_uline(stmt)); } } else if(params->psize == 1) { /* BinaryOperator */ ktypeattr_t ptype = params->paramtypeItems[0].attrTypeId; if(retTy == KType_Boolean && ptype == KType_float) { /* boolean float.(opEQ|opNE|opGT|opGE|opLT|opLE) (float x) */ enum BinaryOp Op = KMethodName_toBinaryOperator(kctx, mn); INode *LHS = FetchINode(kctx, builder, expr, 1, KType_float, thunk); INode *RHS = FetchINode(kctx, builder, expr, 2, KType_float, thunk); return CreateBinaryInst(BLD(builder), Op, LHS, RHS, kNode_uline(stmt)); } else if(retTy == KType_float && ptype == KType_float) { /* float float.(opADD|opSUB|opMUL|opDIV) (float x) */ enum BinaryOp Op = KMethodName_toBinaryOperator(kctx, mn); INode *LHS = FetchINode(kctx, builder, expr, 1, KType_float, thunk); INode *RHS = FetchINode(kctx, builder, expr, 2, KType_float, thunk); return CreateBinaryInst(BLD(builder), Op, LHS, RHS, kNode_uline(stmt)); } } } return 0; }