Example #1
0
static kbool_t KBuilder_VisitMethodCallNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk)
{
	kshort_t a = AssignStack(thunk), espidx = expr->stackbase, thisidx = espidx + K_CALLDELTA;
	DBG_ASSERT(a <= espidx);
	kMethod *mtd = CallNode_getMethod(expr);
	DBG_ASSERT(IS_Method(mtd));
	int i, s = kMethod_Is(Static, mtd) ? 2 : 1;
	int argc = CallNode_getArgCount(expr);
	for (i = s; i < argc + 2; i++) {
		intptr_t a = thisidx + i - 1;
		kNode *paramNode = kNode_At(expr, i);
		if(!kNode_IsValue(paramNode) && paramNode->stackbase != a) {
			DBG_P("a=%d, stackbase=%d", a, paramNode->stackbase);
			DBG_ASSERT(paramNode->stackbase == a);
		}
		SUGAR VisitNode(kctx, builder, paramNode, &a);
	}
	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)kNode_ns(expr), KClass_NameSpace);
		}
	}
	else {
		ASM(NSET, OC_(thisidx-2), (intptr_t)kNode_ns(expr), KClass_NameSpace);
		ASM(LOOKUP, SFP_(thisidx), kNode_ns(expr), mtd);
	}
	int esp_ = SFP_(espidx + argc + K_CALLDELTA + 1);
	ASM(CALL, builder->common.uline, SFP_(thisidx), esp_, KLIB Knull(kctx, KClass_(expr->attrTypeId)));
	ReAssignNonValueNode(kctx, builder, a, expr);
	return true;
}
Example #2
0
//## Node Node.message(int error, String msg);
static KMETHOD Node_Message(KonohaContext *kctx, KonohaStack *sfp)
{
	kNode   *node  = sfp[0].asNode;
	kinfotag_t level = (kinfotag_t)sfp[1].intValue;
	kString *msg   = sfp[2].asString;
	KReturn(SUGAR MessageNode(kctx, node, NULL, kNode_ns(node), level, "%s", kString_text(msg)));
}
Example #3
0
//## Node Node.message(int error, Token tk, String msg);
static KMETHOD NodeToken_Message(KonohaContext *kctx, KonohaStack *sfp)
{
	kNode   *stmt  = sfp[0].asNode;
	kinfotag_t level = (kinfotag_t)sfp[1].intValue;
	kString *msg   = sfp[3].asString;
	KReturn(SUGAR MessageNode(kctx, stmt, sfp[2].asToken, kNode_ns(stmt), level, "%s", kString_text(msg)));
}
Example #4
0
static void kNode_AddMethodDeclNode(KonohaContext *kctx, kNode *bk, kToken *tokenClassName, kNode *classNode)
{
	if(bk == NULL) {
		return;
	}
	size_t i;

	kNameSpace *ns = kNode_ns(classNode);
	kMethod *AddMethod = KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, ns, KClass_NameSpace, KMethodName_("AddMethodDecl"), 1, KMethodMatch_NoOption);

	for(i = 0; i < kNode_GetNodeListSize(kctx, bk); i++) {
		kNode *stmt = bk->NodeList->NodeItems[i];
		if(stmt->syn->keyword == KSymbol_TypeDeclPattern)
			continue;
		if(stmt->syn->keyword == KSymbol_MethodDeclPattern) {
			KLIB kObjectProto_SetObject(kctx, stmt, KSymbol_("ClassName"), KType_Token, tokenClassName);
			kNodeVar *classParentBlock = kNode_GetParentNULL(classNode);
			if(classParentBlock == NULL) {
				classParentBlock = KNewNode(ns);
				SUGAR kNode_AddNode(kctx, classParentBlock, classNode);
				kNode_Type(kctx, classParentBlock, KNode_Block, KType_void);
			}

			/* Create 'NameSpace.AddMethodDecl(stmt)' */
			kNode *arg0 = new_ConstNode(kctx, ns, NULL, UPCAST(ns));
			kNode *arg1 = new_ConstNode(kctx, ns, NULL, UPCAST(stmt));

			kNode *callNode = SUGAR new_MethodNode(kctx, ns, KClass_NameSpace, AddMethod, 2, arg0, arg1);
			SUGAR kNode_AddNode(kctx, classParentBlock, callNode);
		}
		else {
			SUGAR MessageNode(kctx, stmt, NULL, NULL, WarnTag, "%s is not available within the class clause", KSymbol_Fmt2(stmt->syn->keyword));
		}
	}
}
Example #5
0
static struct KVirtualCode *FuelVM_GenerateVirtualCode(KonohaContext *kctx, kMethod *mtd, kNode *block, int option)
{
	if(unlikely(AbstractMethodPtr == 0)) {
		AbstractMethodPtr = mtd->invokeKMethodFunc;
	}

	kNameSpace *ns = kNode_ns(block);
	KBuilder builderbuf = {}, *builder = &builderbuf;
	FuelIRBuilder Builder = {};
	INIT_GCSTACK();
	IRBuilder_Init(&Builder, kctx, ns);
	builder->builder = &Builder;
	builder->common.api = ns->builderApi;
	Block *EntryBlock = CreateBlock(BLD(builder));
	IRBuilder_setBlock(BLD(builder), EntryBlock);
	INode *Self = SetUpArguments(kctx, &Builder, mtd);

	SUGAR VisitNode(kctx, builder, block, NULL);

	if(!Block_HasTerminatorInst(BLD(builder)->Current)) {
		if(mtd->mn == MN_new) {
			INode *Ret = CreateReturn(BLD(builder), Self);
			INode_setType(Ret, ConvertToTypeId(kctx, mtd->typeId));
		} else {
			ktypeattr_t retTy = kMethod_GetReturnType(mtd)->typeId;
			if(retTy == KType_void) {
				CreateReturn(BLD(builder), 0);
			} else {
				enum TypeId Type = ConvertToTypeId(kctx, retTy);
				INode *Ret;
				if(KType_Is(UnboxType, retTy)) {
					SValue V; V.bits = 0;
					Ret = CreateConstant(BLD(builder), Type, V);
				} else {
					kObject *obj = KLIB Knull(kctx, KClass_(retTy));
					Ret = CreateObject(BLD(builder), Type, (void *)obj);
				}
				Ret = CreateReturn(BLD(builder), Ret);
				INode_setType(Ret, Type);
				CreateReturn(BLD(builder), 0);
			}
		}
	}
	RESET_GCSTACK();
	IMethod Mtd = {kctx, mtd, EntryBlock, ns};
	BLD(builder)->Method = &Mtd;
	bool JITCompiled = false;
	union ByteCode *code = IRBuilder_Compile(BLD(builder), &Mtd, option, &JITCompiled);
	if(mtd->invokeKMethodFunc == FuelVM_RunVirtualMachine) {
		mtd->virtualCodeApi_plus1[-1]->FreeVirtualCode(kctx, mtd->vcode_start);
	}
	KLIB kMethod_SetFunc(kctx, mtd, 0);
	if(JITCompiled) {
		KLIB kMethod_SetFunc(kctx, mtd, (KMethodFunc) code);
	}
	KFieldSet(mtd, ((kMethodVar *)mtd)->CompiledNode, block);
	IRBuilder_Exit(&Builder);
	return (struct KVirtualCode *) code;
}
Example #6
0
//## Node Node.TypeCheckNode(Symbol key, Object type, int policy);
static KMETHOD Node_TypeCheckNode(KonohaContext *kctx, KonohaStack *sfp)
{
	kNode *node = sfp[0].asNode;
	ksymbol_t key = (ksymbol_t)sfp[1].intValue;
	KClass *type = kObject_class(sfp[2].asObject);
	int policy = sfp[3].intValue;
	KReturn(SUGAR TypeCheckNodeByName(kctx, node, key, kNode_ns(node), type, policy));
}
Example #7
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));
}
Example #8
0
//## Node Node.ParseNewNode(Token[] tokenList, int beginIdx, int endIdx, boolean isMetaPattern);
static KMETHOD Node_ParseNewNode(KonohaContext *kctx, KonohaStack *sfp)
{
	kNode    *stmt = sfp[0].asNode;
	kArray   *tokenList = sfp[1].asArray;
	int beginIdx = (int)sfp[2].intValue;
	int endIdx   = (int)sfp[3].intValue;
	ParseOption opt = (sfp[4].boolValue == true) ? ParseMetaPatternOption : 0;
	KReturn(SUGAR ParseNewNode(kctx, kNode_ns(stmt), tokenList, &beginIdx, endIdx, opt, NULL));
}
Example #9
0
//## Node Node.newMethodNode(Object type, Symbol keyword, Node expr1);
static KMETHOD Node_newMethodNode1(KonohaContext *kctx, KonohaStack *sfp)
{
	kNameSpace *ns = kNode_ns(sfp[0].asNode);
	KClass *type = kObject_class(sfp[1].asObject);
	ksymbol_t keyword = (ksymbol_t)sfp[2].intValue;
	kNode *expr1 = sfp[3].asNode;
	kMethod *mtd = KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, ns, type, keyword, 0, KMethodMatch_NoOption);
	if(mtd == NULL) {
		KReturn(KNULL(Node));
	}
	KReturn(SUGAR new_MethodNode(kctx, ns, type, mtd, 1, expr1));
}
Example #10
0
static kNode* kNode_ParseClassNodeNULL(KonohaContext *kctx, kNode *stmt, kToken *tokenClassName)
{
	kNode *block = NULL;
	kTokenVar *blockToken = (kTokenVar *)kNode_GetObject(kctx, stmt, KSymbol_BlockPattern, NULL);
	if(blockToken != NULL) {
		kNameSpace *ns = kNode_ns(stmt);
		SUGAR kToken_ToBraceGroup(kctx, blockToken, ns, NULL);
		KTokenSeq source = {ns, RangeGroup(blockToken->GroupTokenList)};
		block = SUGAR ParseNewNode(kctx, ns, source.tokenList, &source.beginIdx, source.endIdx, ParseMetaPatternOption, NULL);
		KLIB kObjectProto_SetObject(kctx, stmt, KSymbol_BlockPattern, KType_Node, block);
	}
	return block;
}
Example #11
0
static KMETHOD Expression_Defined(KonohaContext *kctx, KonohaStack *sfp)
{
	VAR_Expression(expr, tokenList, beginIdx, currentIdx, endIdx);
	kNameSpace *ns = kNode_ns(expr);
	if(beginIdx == currentIdx && beginIdx + 1 < endIdx) {
		kTokenVar *definedToken = tokenList->TokenVarItems[beginIdx];   // defined
		kTokenVar *pToken = tokenList->TokenVarItems[beginIdx+1];
		if(IS_Array(pToken->GroupTokenList)) {
			SUGAR kNode_Op(kctx, expr, definedToken, 0);
			FilterDefinedParam(kctx, ns, RangeGroup(pToken->GroupTokenList));
			KReturn(SUGAR AppendParsedNode(kctx, expr, RangeGroup(pToken->GroupTokenList), NULL, ParseExpressionOption, "("));
		}
	}
}
Example #12
0
static KMETHOD Expression_isNotNull(KonohaContext *kctx, KonohaStack *sfp)
{
	VAR_Expression(stmt, tokenList, beginIdx, opIdx, endIdx);
	if(opIdx + 2 == endIdx) {
		DBG_P("checking .. x != null");
		kTokenVar *tk = tokenList->TokenVarItems[opIdx+1];
		if(tk->symbol == KSymbol_("null") || tk->symbol == KSymbol_("NULL")) {
			kNameSpace *ns = kNode_ns(stmt);
			tk->symbol = KSymbol_("IsNotNull");
			tk->resolvedSyntaxInfo = tokenList->TokenVarItems[opIdx]->resolvedSyntaxInfo;
			SUGAR kNode_Op(kctx, stmt, tk, 1, SUGAR ParseNewNode(kctx, ns, tokenList, &beginIdx, opIdx, ParseExpressionOption, NULL));
			KReturnUnboxValue(opIdx + 2);
		}
	}
	DBG_P("checking parent .. != ..");
	KReturnUnboxValue(-1);
}
Example #13
0
static KMETHOD PatternMatch_ForStmt(KonohaContext *kctx, KonohaStack *sfp)
{
	VAR_PatternMatch(stmt, name, tokenList, beginIdx, endIdx);
	/* for(IniitExpr; CondExpr; IterateExpr) $Block */
	kNameSpace *ns = kNode_ns(stmt);
	int i, start = beginIdx;
	/* InitExpression Part */
	for(i = beginIdx; i < endIdx; i++) {
		kTokenVar *tk = tokenList->TokenVarItems[i];
		if(tk->symbol == KSymbol_SEMICOLON) {
			if(start < i) {
				kNode *node = SUGAR ParseNewNode(kctx, ns, tokenList, &start, i, ParseMetaPatternOption, NULL);
				SUGAR kNode_AddParsedObject(kctx, stmt, KSymbol_("init"), UPCAST(node));
			}
			start = i + 1;
			break;
		}
	}
	if(start == beginIdx) {
		KReturnUnboxValue(-1);
	}
	/* CondExpression Part */
	for(i = start; i < endIdx; i++) {
		kTokenVar *tk = tokenList->TokenVarItems[i];
		if(tk->symbol == KSymbol_SEMICOLON) {
			if(start < i) {
				kNode *node = SUGAR ParseNewNode(kctx, ns, tokenList, &start, i, ParseExpressionOption, NULL);
				KDump(node);
				SUGAR kNode_AddParsedObject(kctx, stmt, KSymbol_ExprPattern, UPCAST(node));
			}
			start = i + 1;
			break;
		}
	}
	if(i == endIdx) {
		KReturnUnboxValue(-1);
	}
	/* IterExpression Part */
	if(start < endIdx) {
		kNode *node = SUGAR ParseNewNode(kctx, ns, tokenList, &start, endIdx, ParseMetaPatternOption, NULL);
		SUGAR kNode_AddParsedObject(kctx, stmt, KSymbol_("Iterator"), UPCAST(node));
	}
	KReturnUnboxValue(endIdx);
}
Example #14
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)));
	}
}
Example #15
0
static KMETHOD Statement_namespace(KonohaContext *kctx, KonohaStack *sfp)
{
	VAR_TypeCheck(stmt, ns, reqc);
	kstatus_t result = K_CONTINUE;
	kToken *tk = SUGAR kNode_GetToken(kctx, stmt, KSymbol_BlockPattern, NULL);
	if(tk != NULL && tk->resolvedSyntaxInfo->keyword == TokenType_LazyBlock) {
		INIT_GCSTACK();
		kNameSpace *ns = new_(NameSpace, kNode_ns(stmt), _GcStack);
		KTokenSeq range = {ns, KGetParserContext(kctx)->preparedTokenList};
		KTokenSeq_Push(kctx, range);
		SUGAR Tokenize(kctx, ns, kString_text(tk->text), tk->uline, tk->indent, range.tokenList);
		KTokenSeq_End(kctx, range);
		result = SUGAR EvalTokenList(kctx, &range, NULL/*trace*/);
		KTokenSeq_Pop(kctx, range);
		RESET_GCSTACK();
		kNode_Type(kctx, stmt, KNode_Done, KType_void);
	}
	KReturnUnboxValue(result == K_CONTINUE);
}
Example #16
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));
	}
}
Example #17
0
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;
}
Example #18
0
static KMETHOD Expression_LispOperator(KonohaContext *kctx, KonohaStack *sfp)
{
	VAR_Expression(expr, tokenList, beginIdx, currentIdx, endIdx);
	kNameSpace *ns = kNode_ns(expr);
	if(beginIdx == currentIdx && beginIdx + 1 < endIdx) {
		kTokenVar *opToken = tokenList->TokenVarItems[beginIdx];
		kNode_Type(kctx, expr, KNode_Block, KType_var);
		int i = beginIdx + 1;
		SUGAR kNode_Op(kctx, expr, opToken, 0);
		while(i < endIdx) {
			int orig = i;
			kNode *node = SUGAR ParseNewNode(kctx, ns, tokenList, &i, i+1, ParseExpressionOption, "(");
			SUGAR kNode_AddNode(kctx, expr, node);
			assert(i != orig);
		}
		int size = kNode_GetNodeListSize(kctx, expr);
		if(size == 1) { /* case (+) */
			assert(0 && "(+) is not supported");
		}
		else if(size == 2) { /* case (+ 1) */
			KReturnUnboxValue(endIdx);
		}
		/* (+ 1 2 3 4) => (+ (+ (+ 1 2) 3 ) 4) */
		kNode *leftNode = kNode_At(expr, 1), *rightNode;
		for(i = 2; i < size-1; i++) {
			kNode *node = KNewNode(ns);
			rightNode = kNode_At(expr, i);
			SUGAR kNode_Op(kctx, node, opToken, 2, leftNode, rightNode);
			leftNode = node;
		}
		rightNode = kNode_At(expr, i);
		KLIB kArray_Clear(kctx, expr->NodeList, 1);
		KLIB kArray_Add(kctx, expr->NodeList, leftNode);
		KLIB kArray_Add(kctx, expr->NodeList, rightNode);
		KDump(expr);
		KReturnUnboxValue(endIdx);
	}
}
Example #19
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));
	}
}
static KMETHOD Expression_ExtendedTextLiteral(KonohaContext *kctx, KonohaStack *sfp)
{
	VAR_Expression(expr, tokenList, beginIdx, opIdx, endIdx);
	kNameSpace *ns = kNode_ns(expr);
	kToken *tk = tokenList->TokenItems[opIdx];
	INIT_GCSTACK();
	kString *text = remove_escapes(kctx, tk);
	if(beginIdx != opIdx) {
		/* FIXME */
		assert(0 && "FIXME");
		KReturnUnboxValue(-1);
	}

	if(text == NULL) {
		/* text contain unsupported escape sequences */
		RESET_GCSTACK();
		KReturnUnboxValue(-1);
	}

	const char *str = kString_text(text);
	const char *end = NULL;
	const char *start = strstr(str, "${");
	if(start == NULL) {
		/* text does not contain Interpolation expressions */
		RESET_GCSTACK();
		KReturnUnboxValue(beginIdx+1);
	}
	kSyntax *addSyntax = kSyntax_(ns, KSymbol_("+"));
	kTokenVar *opToken = tokenList->TokenVarItems[beginIdx];
	opToken->symbol = KSymbol_("+");
	opToken->text   = KLIB new_kString(kctx, OnGcStack, "+", 1, 0);
	KFieldSet(opToken, opToken->resolvedSyntaxInfo, addSyntax);
	SUGAR kNode_Op(kctx, expr, opToken, 0);

	/* [before] "aaa${bbb}ccc"
	 * [after]  "" + "aaa" + bbb + "ccc"
	 */
	SUGAR kNode_AddNode(kctx, expr, new_ConstNode(kctx, ns, NULL, UPCAST(TS_EMPTY)));
	while(true) {
		start = strstr(str, "${");
		if(start == NULL)
			break;
		if(start == strstr(str, "${}")) {
			str += 3;
			continue;
		}
		end = strchr(start, '}');
		if(end == NULL)
			break;
		kNode *newexpr = ParseSource(kctx, ns, start+2, end-(start+2));
		if(start - str > 0) {
			kNode *first = new_ConstNode(kctx, ns, NULL,
					UPCAST(KLIB new_kString(kctx, OnGcStack, str, (start - str), 0)));
			SUGAR kNode_AddNode(kctx, expr, first);
		}
		SUGAR kNode_AddNode(kctx, expr, newexpr);
		str = end + 1;
	}

	if((start == NULL) || (start != NULL && end == NULL)) {
		kNode *rest = new_ConstNode(kctx, ns, KClass_String,
				UPCAST(KLIB new_kString(kctx, OnGcStack, str, strlen(str), 0)));
		SUGAR kNode_AddNode(kctx, expr, rest);
	}

	/* (+ 1 2 3 4) => (+ (+ (+ 1 2) 3 ) 4) */
	int i, size = kNode_GetNodeListSize(kctx, expr);
	assert(size > 2);
	kNode *leftNode = kNode_At(expr, 1), *rightNode;
	for(i = 2; i < size-1; i++) {
		kNode *node = KNewNode(ns);
		rightNode = kNode_At(expr, i);
		SUGAR kNode_Op(kctx, node, opToken, 2, leftNode, rightNode);
		leftNode = node;
	}
	rightNode = kNode_At(expr, i);
	KLIB kArray_Clear(kctx, expr->NodeList, 1);
	KLIB kArray_Add(kctx, expr->NodeList, leftNode);
	KLIB kArray_Add(kctx, expr->NodeList, rightNode);
	RESET_GCSTACK();
	KReturnUnboxValue(beginIdx+1);
}
Example #21
0
//## boolean Node.getNameSpace();
static KMETHOD Node_getNameSpace(KonohaContext *kctx, KonohaStack *sfp)
{
	KReturn(kNode_ns(sfp[0].asNode));
}