示例#1
0
static kbool_t FuelVM_VisitAssignNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk)
{
	/*
	 * [LetExpr] := lhs = rhs
	 * expr->NodeList = [NULL, lhs, rhs]
	 **/

	kNode *left = kNode_At(expr, 1);
	kNode *right = kNode_At(expr, 2);
	INode *Node;
	FuelIRBuilder *flbuilder = BLD(builder);
	if(left->node == KNode_Local) {
		enum TypeId type = ConvertToTypeId(kctx, left->attrTypeId);
		if((Node = IRBuilder_FindLocalVarByHash(flbuilder, type, left->index)) == 0) {
			Node = CreateLocal(flbuilder, type);
			IField_setHash((IField *) Node, left->index);
		}
		SUGAR VisitNode(kctx, builder, right, thunk);
		INode *RHS = FuelVM_getExpression(builder);
		//if(RHS->Type != Node->Type) {
		//	INode_setType(Node, RHS->Type);
		//}
		CreateUpdate(flbuilder, Node, RHS);
	}
	//else if(left->node == TEXPR_STACKTOP) {
	//	enum TypeId type = ConvertToTypeId(kctx, left->attrTypeId);
	//	uintptr_t Hash = (uintptr_t) left;
	//	if((Node = IRBuilder_FindLocalVarByHash(flbuilder, type, Hash)) == 0) {
	//		Node = CreateLocal(flbuilder, type);
	//		IField_setHash((IField *) Node, Hash);
	//		ARRAY_add(INodePtr, &BLD(builder)->Stack, Node);
	//	}
	//	SUGAR VisitNode(kctx, builder, right, thunk);
	//	INode *RHS = FuelVM_getExpression(builder);
	//	if(RHS->Type != Node->Type)
	//		INode_setType(Node, RHS->Type);
	//	CreateUpdate(BLD(builder), Node, RHS);
	//}
	else{
		assert(left->node == KNode_Field);
		SUGAR VisitNode(kctx, builder, right, thunk);
		kshort_t index  = (kshort_t)left->index;
		kshort_t xindex = (kshort_t)(left->index >> (sizeof(kshort_t)*8));

		INode *Left;
		if((Left = IRBuilder_FindLocalVarByHash(BLD(builder), TYPE_Object, index)) == 0) {
			Left = CreateLocal(BLD(builder), TYPE_Object);
			IField_setHash((IField *) Left, index);
		}
		enum TypeId type = ConvertToTypeId(kctx, left->attrTypeId);
		Node = CreateField(BLD(builder), FieldScope, type, Left, xindex);
		SUGAR VisitNode(kctx, builder, right, thunk);
		CreateUpdate(BLD(builder), Node, FuelVM_getExpression(builder));
	}
	builder->Value = Node;
	return true;
}
示例#2
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;
}
示例#3
0
static INode *FetchINode(KonohaContext *kctx, KBuilder *builder, kNode *expr, unsigned idx, ktypeattr_t reqTy, void *thunk)
{
	kNode *exprN = kNode_At(expr, idx);
	SUGAR VisitNode(kctx, builder, exprN, thunk);
	INode *Node = FuelVM_getExpression(builder);
	assert(Node->Type != TYPE_void);
	return Node;
}
示例#4
0
static void CreateCond(KonohaContext *kctx, KBuilder *builder, kNode *expr, enum ConditionalOp Op, void *thunk)
{
	kNode *LHS = kNode_At(expr, 1);
	kNode *RHS = kNode_At(expr, 2);

	Block *HeadBB  = CreateBlock(BLD(builder));
	Block *ThenBB  = CreateBlock(BLD(builder));
	Block *MergeBB = CreateBlock(BLD(builder));

	/* [CondExpr]
	 * LogicalAnd case
	 *       | goto Head
	 * Head  | let bval = LHS
	 *       | if(bval) { goto Then } else { goto Merge }
	 * Then  | bval = RHS
	 *       | goto Merge
	 * Merge | ...
	 */

	INode *Node;
	IRBuilder_JumpTo(BLD(builder), HeadBB);
	{ /* Head */
		IRBuilder_setBlock(BLD(builder), HeadBB);
		Node = CreateLocal(BLD(builder), TYPE_boolean);
		SUGAR VisitNode(kctx, builder, LHS, thunk);
		INode *Left = FuelVM_getExpression(builder);
		CreateUpdate(BLD(builder), Node, Left);

		if(Op == LogicalAnd) {
			CreateBranch(BLD(builder), Left, ThenBB, MergeBB);
		} else {
			CreateBranch(BLD(builder), Left, MergeBB, ThenBB);
		}
	}
	{ /* Then */
		IRBuilder_setBlock(BLD(builder), ThenBB);
		SUGAR VisitNode(kctx, builder, RHS, thunk);
		INode *Right = FuelVM_getExpression(builder);
		CreateUpdate(BLD(builder), Node, Right);
		IRBuilder_JumpTo(BLD(builder), MergeBB);
	}

	IRBuilder_setBlock(BLD(builder), MergeBB);
	builder->Value = Node;
}
示例#5
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;
}
示例#6
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);
	}
}
示例#7
0
static kbool_t KBuilder_VisitAssignNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk)
{
	kNode *leftHandNode  = kNode_At(expr, 1);
	kNode *rightHandNode = kNode_At(expr, 2);
	//DBG_P("LET (%s) a=%d, shift=%d, espidx=%d", KType_text(expr->attrTypeId), a, shift, espidx);
	if(kNode_node(leftHandNode) == KNode_Local) {
		kshort_t a = AssignStack(thunk);
		SUGAR VisitNode(kctx, builder, rightHandNode, &(leftHandNode->index));
		if(expr->attrTypeId != KType_void && a != leftHandNode->index) {
			AsmMOV(kctx, builder, a, KClass_(leftHandNode->attrTypeId), leftHandNode->index);
		}
	}
	else if(kNode_node(leftHandNode) == KNode_Field) {
		intptr_t espidx = expr->stackbase;
		SUGAR VisitNode(kctx, builder, rightHandNode, &espidx);
		kshort_t index  = (kshort_t)leftHandNode->index;
		kshort_t xindex = (kshort_t)(leftHandNode->index >> (sizeof(kshort_t)*8));
		KClass *lhsClass = KClass_(leftHandNode->attrTypeId), *rhClass = KClass_(rightHandNode->attrTypeId);
		ASM(XNMOV, OC_(index), xindex, TC_(espidx, rhClass), lhsClass);
		if(expr->attrTypeId != KType_void) {
			kshort_t a = AssignStack(thunk);
			ASM(NMOVx, TC_(a, rhClass), OC_(index), xindex, lhsClass);
		}
	}
示例#8
0
static kbool_t FuelVM_VisitMethodCallNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk)
{
	kMethod *mtd = CallNode_getMethod(expr);
	DBG_ASSERT(IS_Method(mtd));
	enum TypeId Type = ConvertToTypeId(kctx, expr->attrTypeId);
	if(mtd->mn == KMethodName_("box")) {
		Type = ToBoxType(Type);
	}

	/*
	 * [CallExpr] := this.method(arg1, arg2, ...)
	 * expr->NodeList = [method, this, arg1, arg2, ...]
	 **/
	INode *Inst;
	if((Inst = CreateSpecialInstruction(kctx, builder, mtd, expr, thunk)) != 0) {
		INode_setType(Inst, Type);
		builder->Value = Inst;
		return true;
	}
	int i, s = kMethod_Is(Static, mtd) ? 2 : 1;
	int argc = CallExpr_getArgCount(expr);
	INode *Params[argc+2];

	if(kMethod_Is(Static, mtd)) {
		kObject *obj = KLIB Knull(kctx, KClass_(mtd->typeId));
		INode *Self = CreateObject(BLD(builder), mtd->typeId, (void *) obj);
		Params[1] = Self;
	}
	for (i = s; i < argc + 2; i++) {
		kNode *exprN = kNode_At(expr, i);
		DBG_ASSERT(IS_Node(exprN));
		SUGAR VisitNode(kctx, builder, exprN, thunk);
		INode *Node = FuelVM_getExpression(builder);
		assert(Node->Type != TYPE_void);
		Params[i] = Node;
	}

	INode *MtdObj = CreateObject(BLD(builder), KType_Method, (void *) mtd);
	enum CallOp Op = (kMethod_Is(Virtual, mtd)) ? VirtualCall : DefaultCall;
	Params[0] = MtdObj;
	kNode *stmt = expr->Parent;
	assert(IS_Node(stmt));
	Inst = CreateICall(BLD(builder), Type, Op, kNode_uline(stmt), Params, argc + 2);
	builder->Value = Inst;
	return true;
}
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);
		}
	}
}
示例#10
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;
}
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);
}