static kbool_t FuelVM_VisitFunctionNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk) { /* * [FunctionExpr] := new Function(method, env1, env2, ...) * expr->NodeList = [method, defObj, env1, env2, ...] **/ enum TypeId Type; kMethod *mtd = CallNode_getMethod(expr); kObject *obj = expr->NodeList->ObjectItems[1]; INode *MtdObj = CreateObject(BLD(builder), KType_Method, (void *) mtd); Type = ConvertToTypeId(kctx, kObject_class(obj)->typeId); INode *NewEnv = CreateNew(BLD(builder), 0, Type); size_t i, ParamSize = kArray_size(expr->NodeList)-2; for(i = 0; i < ParamSize; i++) { kNode *envN = kNode_At(expr, i+2); enum TypeId FieldType = ConvertToTypeId(kctx, envN->attrTypeId); INode *Node = CreateField(BLD(builder), FieldScope, FieldType, NewEnv, i); SUGAR VisitNode(kctx, builder, envN, thunk); CreateUpdate(BLD(builder), Node, FuelVM_getExpression(builder)); } Type = ConvertToTypeId(kctx, expr->attrTypeId); INode *NewFunc = CreateNew(BLD(builder), 0, Type); kNameSpace *ns = kNode_ns(expr); mtd = KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, ns, KClass_Func, KMethodName_("_Create"), 2, KMethodMatch_NoOption); INode *CallMtd = CreateObject(BLD(builder), KType_Method, (void *) mtd); INode *Params[4]; Params[0] = CallMtd; Params[1] = NewFunc; Params[2] = NewEnv; Params[3] = MtdObj; builder->Value = CreateICall(BLD(builder), Type, DefaultCall, kNode_uline(expr), Params, 4); return true; }
static kbool_t KBuilder_VisitErrorNode(KonohaContext *kctx, KBuilder *builder, kNode *stmt, void *thunk) { ASM(ERROR, kNode_uline(stmt), stmt->ErrorMessage); return false; }
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; }