Added support for non-array references.
2 * Copyright (C) 2012 David Anderson
4 * This file is part of JITCraft.
6 * JITCraft is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free
8 * Software Foundation, either version 3 of the License, or (at your option)
11 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * JITCraft. If not, see http://www.gnu.org/licenses/.
18 #include "SemanticAnalysis.h"
21 #include "TypeManager.h"
27 IsPrimitiveType(Type *type, PrimitiveType primitive)
32 if (!type->isPrimitive())
35 return primitive == type->primitive();
39 EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
44 *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
48 *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
56 EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
58 switch (expression->kind()) {
59 case AstNode::kBinaryExpression:
63 BinaryExpression *b = expression->toBinaryExpression();
64 if (!EvaluateForConstant(b->left(), &left) ||
65 !EvaluateForConstant(b->right(), &right))
69 return EvaluateBinaryOperation(b->token(), left, right, out);
72 case AstNode::kNameProxy:
74 NameProxy *proxy = expression->toNameProxy();
75 if (proxy->binding()->kind() != BoundName::CONSTANT)
78 NamedConstant *c = proxy->binding()->toNamedConstant();
79 if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
86 case AstNode::kIntegerLiteral:
87 *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
95 SemanticAnalysis::SemanticAnalysis(ParseTree *tree)
103 SemanticAnalysis::analyze()
105 for (size_t i = 0; i < tree_->statements()->length(); i++) {
106 Statement *statement = tree_->statements()->at(i);
107 statement->accept(this);
114 SemanticAnalysis::visit(NameProxy *name)
116 name->setType(name->binding()->type());
120 SemanticAnalysis::visitForLoad(Expression *expression)
122 expression->accept(this);
123 if (expression->type()) {
125 Type *type = expression->type();
126 if (type->isArray() || type->isReference())
127 expression->setType(type->contained());
129 return expression->type();
133 SemanticAnalysis::visitForRef(Expression *expression)
135 expression->accept(this);
136 return expression->type();
140 TypeCheck(Type *left, Type *right)
145 if (left->isPrimitive()) {
146 if (!right->isPrimitive())
148 return left->primitive() == right->primitive();
155 SemanticAnalysis::visit(Assignment *node)
157 visitForLoad(node->expression());
159 if (node->lvalue()->isIndexExpression()) {
160 node->lvalue()->accept(this);
161 node->setType(node->lvalue()->type()->contained());
163 NameProxy *proxy = node->lvalue()->toNameProxy();
164 if (!proxy->binding()->kind() == BoundName::VARIABLE) {
165 fprintf(stderr, "error\n");
169 Variable *var = proxy->binding()->toVariable();
170 if (var->type()->isReference())
171 node->setType(var->type()->contained());
173 node->setType(var->type());
176 assert(TypeCheck(node->type(), node->expression()->type()));
181 SemanticAnalysis::visit(BinaryExpression *node)
183 Type *left = visitForLoad(node->left());
184 Type *right = visitForLoad(node->right());
186 if (node->token() >= TOK_PLUS && node->token() <= TOK_SLASH) {
187 // Both sides must be primitive.
191 // If either side is a float, the other side must be a float or int.
192 if (left->isFloat() || right->isFloat()) {
193 assert(left->isFloat() || left->isInt());
194 assert(right->isFloat() || right->isInt());
195 node->setType(left->isFloat() ? left : right);
200 // For now, assert everything else is integer and untagged.
201 assert(left->isInt() && right->isInt());
202 assert(!left->tag() && !right->tag());
207 SemanticAnalysis::visit(ReturnStatement *node)
209 visitForLoad(node->expression());
215 SemanticAnalysis::visit(ForStatement *node)
219 scope_ = node->scope();
220 if (node->declaration())
221 node->declaration()->accept(this);
222 if (node->condition())
223 visitForLoad(node->condition());
225 node->update()->accept(this);
226 node->body()->accept(this);
228 scope_ = scope_->enclosing();
233 SemanticAnalysis::visit(WhileStatement *node)
236 node->condition()->accept(this);
237 node->body()->accept(this);
242 SemanticAnalysis::visit(BlockStatement *node)
245 scope_ = node->scope();
246 for (size_t i = 0; i < node->statements()->length(); i++) {
247 Statement *statement = node->statements()->at(i);
248 statement->accept(this);
251 scope_ = scope_->enclosing();
255 SemanticAnalysis::visit(VariableDeclaration *node)
258 Type *type = ZONE()->types()->getPrimitiveForTag(node->tag());
262 if (node->postDimensions()) {
263 if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
268 for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
269 Expression *expr = node->postDimensions()->at(i);
272 if (!IsPrimitiveType(expr->type(), PrimitiveType_Int32)) {
273 typeError(expr, "integer");
278 if (expr->isIntegerLiteral()) {
279 size = expr->toIntegerLiteral()->value();
284 if (size >= INT_MAX / sizeof(int)) {
290 type = ZONE()->types()->unsafeArray(type, size);
293 // Right now, any array is allowed on the LIFO heap. In case the
294 // runtime actually decides to use the LIFO heap, we must reserve
295 // a slot so we can unwind the heap when the current scope leaves.
296 scope_->setUsesLifoHeap();
298 if (node->initialization()) {
299 Type *right = visitForLoad(node->initialization());
300 assert(TypeCheck(type, right));
304 node->variable()->setType(type);
308 SemanticAnalysis::visit(IntegerLiteral *node)
310 node->setType(ZONE()->types()->getPrimitive(PrimitiveType_Int32));
314 SemanticAnalysis::visit(ExpressionStatement *node)
316 node->expression()->accept(this);
320 SemanticAnalysis::preanalyze(FunctionStatement *node)
324 FixedArray *args = FixedArray::New(ZONE(), node->parameters()->size(), Heap::Tenure_Old);
328 // Apply types to arguments.
329 for (size_t i = 0; i < node->parameters()->size(); i++) {
330 Parameter *parameter = node->parameters()->at(i);
332 Type *type = ZONE()->types()->getPrimitiveForTag(parameter->tag());
336 if (parameter->reference()) {
337 type = ZONE()->types()->getReference(type);
342 args->set(ZONE(), i, type);
343 parameter->variable()->setType(type);
346 Type *returnType = ZONE()->types()->getPrimitive(PrimitiveType_Int32);
350 Type *funtype = ZONE()->types()->newFunction(returnType, args);
354 node->fun()->setType(funtype);
359 SemanticAnalysis::visit(FunctionStatement *node)
361 scope_ = node->scope();
363 // :TODO: call this ahead of time.
364 if (!preanalyze(node))
367 node->body()->accept(this);
371 // :TODO: use handles
373 TypeCheckParameter(Type *given, Type *actual)
375 if (actual->isReference()) {
376 if (given->isReference())
377 given = given->contained();
378 return TypeCheck(given, actual->contained());
381 return TypeCheck(given, actual);
385 SemanticAnalysis::visit(CallExpression *node)
387 visitForLoad(node->callee());
390 Type *type = node->callee()->type();
394 assert(type->isFunction());
395 assert(node->arguments()->size() == type->parameters()->length());
397 for (unsigned i = 0; i < node->arguments()->size(); i++) {
398 Expression *expression = node->arguments()->at(i);
399 expression->accept(this);
401 Type *given = expression->type();
405 Type *actual = Type::cast(type->parameters()->at(i));
406 assert(TypeCheckParameter(given, actual));
408 // If the actual is a reference, and the given is not, we'll need to
409 // compute a reference, which may be allocated on the stack.
410 if (actual->isReference() && !given->isReference())
411 scope_->setUsesLifoHeap();
416 SemanticAnalysis::visit(IfStatement *node)
418 visitForLoad(node->condition());
419 node->ifTrue()->accept(this);
421 node->ifFalse()->accept(this);
425 SemanticAnalysis::visit(IndexExpression *node)
428 Type *left = visitForRef(node->left());
429 Type *right = visitForLoad(node->right());
431 if (!right || !right->isInt()) {
432 typeError(node->right(), "integer");
435 if (!left || !left->isArray() || !left->contained()->isPrimitive()) {
436 typeError(node->left(), "array");
443 SemanticAnalysis::visit(EnumStatement *node)
445 // :TODO: test "enum Float { ..."
446 Name *tag = node->name();
448 Type *type = ZONE()->types()->getPrimitiveForTag(tag);
453 for (size_t i = 0; i < node->entries()->size(); i++) {
454 EnumStatement::Entry &entry = node->entries()->at(i);
456 BoxedPrimitive box = BoxedPrimitive::Int(value);
458 entry.expr->accept(this);
459 if (!EvaluateForConstant(entry.expr, &box))
460 fprintf(stderr, "expected constant integer expression\n");
462 assert(box.type() == PrimitiveType_Int32);
466 entry.name->set(type, box);
472 SemanticAnalysis::visit(FloatLiteral *node)
474 Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Float);
482 SemanticAnalysis::visit(BreakStatement *node)
484 assert(loopDepth_ > 0);
488 SemanticAnalysis::visit(ContinueStatement *node)
490 assert(loopDepth_ > 0);