static KMETHOD TypeCheck_Bracket(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, expr, gma, reqty); // [0] currentToken, [1] NULL, [2] .... size_t i; KonohaClass *requestClass = CT_(reqty); KonohaClass *paramType = (requestClass->baseTypeId == TY_Array) ? CT_(requestClass->p0) : CT_INFER; for(i = 2; i < kArray_size(expr->cons); i++) { kExpr *typedExpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, i, gma, paramType, 0); if(typedExpr == K_NULLEXPR) { KReturn(typedExpr); } if(paramType->typeId == TY_var) { paramType = CT_(typedExpr->attrTypeId); } } if(requestClass->baseTypeId != TY_Array) { requestClass = (paramType->typeId == TY_var) ? CT_Array : CT_p0(kctx, CT_Array, paramType->typeId); } kMethod *mtd = KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, Stmt_ns(stmt), CT_Array, MN_("[]"), -1, MethodMatch_NoOption); DBG_ASSERT(mtd != NULL); KFieldSet(expr, expr->cons->MethodItems[0], mtd); KFieldSet(expr, expr->cons->ExprItems[1], SUGAR kExpr_SetVariable(kctx, NULL, gma, TEXPR_NEW, requestClass->typeId, kArray_size(expr->cons) - 2)); KReturn(Expr_typed(expr, TEXPR_CALL, requestClass->typeId)); }
static KMETHOD TypeCheck_as(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, expr, gma, reqty); kExpr *targetExpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, 2, gma, TY_var, 0); kExpr *selfExpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, 1, gma, targetExpr->ty, TypeCheckPolicy_NOCHECK); if(selfExpr != K_NULLEXPR && targetExpr != K_NULLEXPR) { KonohaClass *selfClass = CT_(selfExpr->ty), *targetClass = CT_(targetExpr->ty); if(selfExpr->ty == targetExpr->ty || selfClass->isSubType(kctx, selfClass, targetClass)) { KReturn(selfExpr); } if(selfClass->isSubType(kctx, targetClass, selfClass)) { kNameSpace *ns = Stmt_ns(stmt); kMethod *mtd = KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, ns, TY_Object, MN_("as"), 0); DBG_ASSERT(mtd != NULL); KReturn(SUGAR kStmtkExpr_TypeCheckCallParam(kctx, stmt, expr, mtd, gma, targetClass->typeId)); } KReturn(kStmtExpr_Message(kctx, stmt, selfExpr, ErrTag, "unable to downcast: %s as %s", TY_t(selfExpr->ty), TY_t(targetExpr->ty))); } }
static KMETHOD TypeCheck_InstanceOf(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, expr, gma, reqty); kExpr *selfExpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, 1, gma, TY_var, 0); kExpr *targetExpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, 2, gma, TY_var, 0); if(selfExpr != K_NULLEXPR && targetExpr != K_NULLEXPR) { KonohaClass *selfClass = CT_(selfExpr->ty), *targetClass = CT_(targetExpr->ty); if(CT_is(Final, selfClass)) { kbool_t staticSubType = (selfClass == targetClass || selfClass->isSubType(kctx, selfClass, targetClass)); KReturn(SUGAR kExpr_SetUnboxConstValue(kctx, expr, TY_boolean, staticSubType)); } kNameSpace *ns = Stmt_ns(stmt); kMethod *mtd = KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, ns, TY_Object, MN_("<:"), 1); DBG_ASSERT(mtd != NULL); KFieldSet(expr->cons, expr->cons->MethodItems[0], mtd); kExpr *classValue = SUGAR kExpr_SetConstValue(kctx, expr->cons->ExprItems[2], targetExpr->ty, KLIB Knull(kctx, targetClass)); KFieldSet(expr->cons, expr->cons->ExprItems[2], classValue); KReturn(SUGAR kStmtkExpr_TypeCheckCallParam(kctx, stmt, expr, mtd, gma, TY_boolean)); } }
static KMETHOD TypeCheck_to(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, expr, gma, reqty); kExpr *targetExpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, 2, gma, TY_var, 0); kExpr *selfExpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, 1, gma, targetExpr->ty, TypeCheckPolicy_NOCHECK); if(selfExpr != K_NULLEXPR && targetExpr != K_NULLEXPR) { KonohaClass *selfClass = CT_(selfExpr->ty), *targetClass = CT_(targetExpr->ty); if(selfExpr->ty == targetExpr->ty || selfClass->isSubType(kctx, selfClass, targetClass)) { kStmtExpr_Message(kctx, stmt, selfExpr, InfoTag, "no need: %s to %s", TY_t(selfExpr->ty), TY_t(targetExpr->ty)); KReturn(selfExpr); } kNameSpace *ns = Stmt_ns(stmt); kMethod *mtd = KLIB kNameSpace_GetCoercionMethodNULL(kctx, ns, selfExpr->ty, targetExpr->ty); if(mtd == NULL) { mtd = KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, ns, selfExpr->ty, MN_("to"), 0); DBG_ASSERT(mtd != NULL); // because Object.to is found. if(mtd->typeId != selfExpr->ty) { KReturn(kStmtExpr_Message(kctx, stmt, selfExpr, ErrTag, "undefined coercion: %s to %s", TY_t(selfExpr->ty), TY_t(targetExpr->ty))); } } KReturn(SUGAR kStmtkExpr_TypeCheckCallParam(kctx, stmt, expr, mtd, gma, targetClass->typeId)); } }
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 KMETHOD TypeCheck_Defined(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, expr, gma, reqty); size_t i; kbool_t isDefined = true; SugarContext *sugarContext = GetSugarContext(kctx); int popIsBlockingErrorMessage = sugarContext->isBlockedErrorMessage; sugarContext->isBlockedErrorMessage = true; for(i = 1; i < kArray_size(expr->cons); i++) { kExpr *typedExpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, i, gma, TY_var, TypeCheckPolicy_ALLOWVOID); if(typedExpr == K_NULLEXPR) { isDefined = false; break; } } sugarContext->isBlockedErrorMessage = popIsBlockingErrorMessage; KReturn(SUGAR kExpr_SetUnboxConstValue(kctx, expr, TY_boolean, isDefined)); }
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; }