static KMETHOD TypeCheck_Float(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck2(stmt, expr, ns, reqc); kToken *tk = expr->TermToken; sfp[4].floatValue = strtod(kString_text(tk->text), NULL); // just using tramsformation float KReturn(SUGAR kNode_SetUnboxConst(kctx, expr, KType_float, sfp[4].unboxValue)); }
static KMETHOD TypeCheck_Getter(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck2(stmt, expr, ns, reqc); kToken *fieldToken = expr->NodeList->TokenItems[0]; ksymbol_t fn = fieldToken->symbol; kNode *self = KLIB TypeCheckNodeAt(kctx, expr, 1, ns, KClass_INFER, 0); if(self != K_NULLNODE) { kMethod *mtd = KLIB kNameSpace_GetGetterMethodNULL(kctx, ns, KClass_(self->typeAttr), fn); if(mtd != NULL) { KFieldSet(expr->NodeList, expr->NodeList->MethodItems[0], mtd); KReturn(KLIB TypeCheckMethodParam(kctx, mtd, expr, ns, reqc)); } else { // dynamic field o.name => o.get(name) kparamtype_t p[1] = {{KType_Symbol}}; kparamId_t paramdom = KLIB Kparamdom(kctx, 1, p); mtd = KLIB kNameSpace_GetMethodBySignatureNULL(kctx, ns, KClass_(self->typeAttr), KMethodNameAttr_Getter, paramdom, 1, p); if(mtd != NULL) { KFieldSet(expr->NodeList, expr->NodeList->MethodItems[0], mtd); KLIB kArray_Add(kctx, expr->NodeList, new_UnboxConstNode(kctx, ns, KType_Symbol, KSymbol_Unmask(fn))); KReturn(KLIB TypeCheckMethodParam(kctx, mtd, expr, ns, reqc)); } } KLIB MessageNode(kctx, stmt, fieldToken, ns, ErrTag, "undefined field: %s", kString_text(fieldToken->text)); } }
static KMETHOD TypeCheck_UntypedAssign(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck2(stmt, expr, ns, reqc); kNodeVar *leftHandNode = (kNodeVar *)kNode_At(expr, 1); if(kNode_isSymbolTerm(leftHandNode)) { kNode *texpr = KLIB TypeVariableNULL(kctx, leftHandNode, ns, KClass_INFER); if(texpr == NULL) { kNode *rightHandNode = KLIB TypeCheckNodeAt(kctx, expr, 2, ns, KClass_INFER, 0); if(rightHandNode != K_NULLNODE) { DeclVariable(kctx, stmt, ns, rightHandNode->typeAttr, leftHandNode); } } else { KFieldSet(expr->NodeList, expr->NodeList->NodeItems[1], texpr); } } }
static KMETHOD TypeCheck_Defined(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck2(stmt, expr, ns, reqc); size_t i; kbool_t isDefined = true; KParserContext *sugarContext = KGetParserContext(kctx); int popIsBlockingErrorMessage = sugarContext->isBlockedErrorMessage; sugarContext->isBlockedErrorMessage = true; for(i = 1; i < kArray_size(expr->NodeList); i++) { kNode *typedNode = SUGAR TypeCheckNodeAt(kctx, expr, i, ns, KClass_INFER, TypeCheckPolicy_AllowVoid); if(kNode_IsError(typedNode)) { isDefined = false; break; } } sugarContext->isBlockedErrorMessage = popIsBlockingErrorMessage; KReturn(SUGAR kNode_SetUnboxConst(kctx, expr, KType_Boolean, isDefined)); }
static KMETHOD TypeCheck_as(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck2(stmt, expr, ns, reqc); kNode *targetNode = SUGAR TypeCheckNodeAt(kctx, expr, 2, ns, KClass_INFER, 0); kNode *selfNode = SUGAR TypeCheckNodeAt(kctx, expr, 1, ns, KClass_(targetNode->attrTypeId), TypeCheckPolicy_NoCheck); if(selfNode != K_NULLNODE && targetNode != K_NULLNODE) { KClass *selfClass = KClass_(selfNode->attrTypeId), *targetClass = KClass_(targetNode->attrTypeId); if(selfClass->typeId == targetClass->typeId || selfClass->isSubType(kctx, selfClass, targetClass)) { KReturn(selfNode); } if(selfClass->isSubType(kctx, targetClass, selfClass)) { kNameSpace *ns = kNode_ns(stmt); kMethod *mtd = KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, ns, KClass_Object, KMethodName_("as"), 0, KMethodMatch_CamelStyle); DBG_ASSERT(mtd != NULL); KReturn(SUGAR TypeCheckMethodParam(kctx, mtd, expr, ns, targetClass)); } KReturn(SUGAR MessageNode(kctx, selfNode, NULL, ns, ErrTag, "unable to downcast: %s as %s", KType_text(selfNode->attrTypeId), KType_text(targetNode->attrTypeId))); } }
static KMETHOD TypeCheck_InstanceOf(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck2(stmt, expr, ns, reqc); /* selfNode and targetNode allow void type * e.g. "'a' instanceof void" */ kNode *selfNode = SUGAR TypeCheckNodeAt(kctx, expr, 1, ns, KClass_INFER, TypeCheckPolicy_AllowVoid); kNode *targetNode = SUGAR TypeCheckNodeAt(kctx, expr, 2, ns, KClass_INFER, TypeCheckPolicy_AllowVoid); if(selfNode != K_NULLNODE && targetNode != K_NULLNODE) { KClass *selfClass = KClass_(selfNode->attrTypeId), *targetClass = KClass_(targetNode->attrTypeId); if(KClass_Is(Final, selfClass)) { kbool_t staticSubType = (selfClass == targetClass || selfClass->isSubType(kctx, selfClass, targetClass)); KReturn(SUGAR kNode_SetUnboxConst(kctx, expr, KType_Boolean, staticSubType)); } kNameSpace *ns = kNode_ns(stmt); kMethod *mtd = KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, ns, KClass_Object, KMethodName_("instanceof"), 1, KMethodMatch_NoOption); DBG_ASSERT(mtd != NULL); kNode *classValue = SUGAR kNode_SetConst(kctx, expr->NodeList->NodeVarItems[2], NULL, KLIB Knull(kctx, targetClass)); KFieldSet(expr->NodeList, expr->NodeList->NodeItems[2], classValue); KReturn(SUGAR TypeCheckMethodParam(kctx, mtd, expr, ns, KClass_Boolean)); } }
static KMETHOD TypeCheck_to(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck2(stmt, expr, ns, reqc); kNode *targetNode = SUGAR TypeCheckNodeAt(kctx, expr, 2, ns, KClass_INFER, 0); kNode *selfNode = SUGAR TypeCheckNodeAt(kctx, expr, 1, ns, KClass_(targetNode->attrTypeId), TypeCheckPolicy_NoCheck); if(selfNode != K_NULLNODE && targetNode != K_NULLNODE) { KClass *selfClass = KClass_(selfNode->attrTypeId), *targetClass = KClass_(targetNode->attrTypeId); if(selfNode->attrTypeId == targetNode->attrTypeId || selfClass->isSubType(kctx, selfClass, targetClass)) { SUGAR MessageNode(kctx, selfNode, NULL, ns, InfoTag, "no need: %s to %s", KType_text(selfNode->attrTypeId), KType_text(targetNode->attrTypeId)); KReturn(selfNode); } kNameSpace *ns = kNode_ns(stmt); kMethod *mtd = KLIB kNameSpace_GetCoercionMethodNULL(kctx, ns, selfClass, targetClass); if(mtd == NULL) { mtd = KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, ns, selfClass, KMethodName_("to"), 0, KMethodMatch_CamelStyle); DBG_ASSERT(mtd != NULL); // because Object.to is found. if(mtd->typeId != selfClass->typeId) { KReturn(SUGAR MessageNode(kctx, selfNode, NULL, ns, ErrTag, "undefined coercion: %s to %s", KClass_text(selfClass), KClass_text(targetClass))); } } KReturn(SUGAR TypeCheckMethodParam(kctx, mtd, expr, ns, targetClass)); } }
static KMETHOD TypeCheck_null(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck2(stmt, expr, ns, reqc); if(reqc->typeId == KType_var) reqc = KClass_Object; KReturn(SUGAR kNode_SetVariable(kctx, expr, KNode_Null, reqc->typeId, 0)); }