Exemplo n.º 1
0
VarType TypeCheckerVisitor::getOperationResultType(TokenKind tokenKind, AstNode* left, AstNode* right) {
	VarType result = VT_INVALID;
	VarType leftType = getNodeType(left);
	VarType rightType = getNodeType(right);
	switch (tokenKind) {
	case tOR: case tAND: case tEQ: case tNEQ:
	case tGT: case tGE: case tLT: case tLE:
		result = VT_INT;
		break;
	case tADD:
		if (leftType == VT_STRING || rightType == VT_STRING) {
			result = VT_STRING;
		} else if (leftType == VT_DOUBLE || rightType == VT_DOUBLE) {
			result = VT_DOUBLE;
		} else if (leftType == VT_INT && rightType == VT_INT) {
			result = VT_INT;
		}
		break;
	case tSUB: case tMUL: case tDIV: case tMOD:
		if (leftType == VT_DOUBLE || rightType == VT_DOUBLE) {
			result = VT_DOUBLE;
		} else if (leftType == VT_INT && rightType == VT_INT) {
			result = VT_INT;
		}
		break;
	case tASSIGN:
		if (!(isAssignable(leftType, rightType))) {
			setErrorMessage(right, "bad type");
		}
		result = leftType;
		break;
	case tDECRSET:
		if (!(isAssignable(leftType, rightType)) || (leftType == VT_STRING)) {
			setErrorMessage(right, "bad type");
		}
		result = leftType;
		break;
	case tINCRSET:
		if (leftType == VT_STRING) {
			result = VT_STRING;
		} else if (leftType == VT_DOUBLE) {
			result = VT_DOUBLE;
		} else if (leftType == VT_INT && rightType == VT_INT) {
			result = VT_INT;
		}
		break;
	default:
		assert(0);
	}
	if (leftType == VT_VOID) {
		setErrorMessage(left, "Should not be of type void");
	}
	if (rightType == VT_VOID) {
		setErrorMessage(right, "Should not be of type void");
	}
	return result;
}
Exemplo n.º 2
0
void TypeCheckerVisitor::visitStoreNode(StoreNode* node) {
	AstNode* value = node->value();
	value->visit(this);
	const AstVar* var = node->var();
	if (isAssignable(var->type(), getNodeType(value))) {
		setNodeType(node, var->type());
	} else {
		setErrorMessage(node, "Bad type");
	}
}
Exemplo n.º 3
0
static void typeAssign(Output& output, Ast::Assign* n, TypeConstraints* constraints)
{
	type(output, n->left, constraints);
	type(output, n->right, constraints);

	typeMustEqual(n->right, astType(n->left), constraints, output);

	if (!isAssignable(n->left) && !constraints)
		output.error(n->location, "Expression is not assignable");

	if (!n->type)
		n->type = UNION_NEW(Ty, Void, {});
}
Exemplo n.º 4
0
static bool isAssignable(Ast* node)
{
	if (UNION_CASE(Ident, n, node))
		return n->targets.size == 1 && n->targets[0]->kind == Variable::KindVariable;
	else if (UNION_CASE(Member, n, node))
		return isAssignable(n->expr);
	else if (UNION_CASE(Index, n, node))
		return true;
	else if (UNION_CASE(Unary, n, node))
		return n->op == UnaryOpDeref;
	else
		return false;
}
Exemplo n.º 5
0
void TypeCheckerVisitor::visitCallNode(CallNode* node) {
	uint32_t params_count = node->parametersNumber();
	AstFunction* refFunc = _current_scope->lookupFunction(node->name(), true);
	bool matchesRefedFunction = (refFunc!= NULL) && (refFunc->parametersNumber() == params_count);
	for (uint32_t i = 0; i < params_count; i++) {
		AstNode* param = node->parameterAt(i);
		param->visit(this);
		if (matchesRefedFunction && !isAssignable(refFunc->parameterType(i), getNodeType(param))) {
			setErrorMessage(param, "Wrong type parameter");
		}
	}
	if (matchesRefedFunction) {
		setNodeType(node, refFunc->returnType());
	} else {
		setNodeType(node, VT_INVALID);
	}
}
Exemplo n.º 6
0
void TypeCheckerVisitor::visitFunctionNode(FunctionNode* node) {
	node->body()->visit(this);
	if (!isAssignable(node->returnType(), getNodeType(node->body()))) {
		setNodeType(node, VT_INVALID);
	}
}