예제 #1
0
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));
	}
}
예제 #2
0
//## Node Node.TypeCheckNodeAt(int pos, Object type, int policy);
static KMETHOD Node_TypeCheckNodeAt(KonohaContext *kctx, KonohaStack *sfp)
{
	kNode *node = sfp[0].asNode;
	size_t pos = sfp[1].intValue;
	KClass *type = kObject_class(sfp[2].asObject);
	int policy = sfp[3].intValue;
	KReturn(SUGAR TypeCheckNodeAt(kctx, node, pos, kNode_ns(node), type, policy));
}
예제 #3
0
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)));
	}
}
예제 #4
0
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));
	}
}
예제 #5
0
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));
	}
}
예제 #6
0
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);
		}
	}
}
예제 #7
0
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));
}
예제 #8
0
static kbool_t kNode_AddClassField(KonohaContext *kctx, kNode *stmt, kNameSpace *ns, KClassVar *definedClass, ktypeattr_t ty, kNode *expr)
{
	if(expr->syn->keyword == KSymbol_LET) {  // String name = "naruto";
		kNode *lexpr = kNode_At(expr, 1);
		if(kNode_IsTerm(lexpr)) {
			kString *name = lexpr->TermToken->text;
			ksymbol_t symbol = KAsciiSymbol(kString_text(name), kString_size(name), KSymbol_NewId);
			kNode *vexpr =  SUGAR TypeCheckNodeAt(kctx, expr, 2, ns, KClass_(ty), 0);
			if(vexpr == K_NULLNODE) return false;
			if(vexpr->node == KNode_Const) {
				KLIB KClass_AddField(kctx, definedClass, ty, symbol);
				KClass_SetClassFieldObjectValue(kctx, definedClass, symbol, vexpr->ObjectConstValue);
			}
			else if(vexpr->node == KNode_UnboxConst) {
				KLIB KClass_AddField(kctx, definedClass, ty, symbol);
				KClass_SetClassFieldUnboxValue(kctx, definedClass, symbol, vexpr->unboxConstValue);
			}
			else if(vexpr->node == KNode_Null) {
				KLIB KClass_AddField(kctx, definedClass, ty, symbol);
			}
			else {
				SUGAR MessageNode(kctx, stmt, lexpr->TermToken, ns, ErrTag, "field initial value must be const: %s", kString_text(name));
				return false;
			}
			return true;
		}
	} else if(expr->syn->keyword == KSymbol_COMMA) {   // String (firstName = naruto, lastName)
		size_t i;
		for(i = 1; i < kNode_GetNodeListSize(kctx, expr); i++) {
			if(!kNode_AddClassField(kctx, stmt, ns, definedClass, ty, kNode_At(expr, i))) return false;
		}
		return true;
	}
	else if(kNode_IsTerm(expr)) {  // String name
		kString *name = expr->TermToken->text;
		ksymbol_t symbol = KAsciiSymbol(kString_text(name), kString_size(name), KSymbol_NewId);
		KLIB KClass_AddField(kctx, definedClass, ty, symbol);
		return true;
	}
	SUGAR MessageNode(kctx, stmt, NULL, ns, ErrTag, "field name is expected");
	return false;
}