Refactored Array, Code to be Objects. Removed Object tagging.
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() && expression->type()->isArray())
124 expression->setType(expression->type()->contained());
125 return expression->type();
129 SemanticAnalysis::visitForRef(Expression *expression)
131 expression->accept(this);
132 return expression->type();
136 TypeCheck(Type *left, Type *right)
141 if (left->isPrimitive()) {
142 if (!right->isPrimitive())
144 return left->primitive() == right->primitive();
151 SemanticAnalysis::visit(Assignment *node)
153 visitForLoad(node->expression());
155 if (node->lvalue()->isIndexExpression()) {
156 node->lvalue()->accept(this);
157 node->setType(node->lvalue()->type()->contained());
159 NameProxy *proxy = node->lvalue()->toNameProxy();
160 if (!proxy->binding()->kind() == BoundName::VARIABLE) {
161 fprintf(stderr, "error\n");
165 Variable *var = proxy->binding()->toVariable();
166 node->setType(var->type());
169 assert(TypeCheck(node->type(), node->expression()->type()));
174 SemanticAnalysis::visit(BinaryExpression *node)
176 Type *left = visitForLoad(node->left());
177 Type *right = visitForLoad(node->right());
179 if (node->token() >= TOK_PLUS && node->token() <= TOK_SLASH) {
180 // Both sides must be primitive.
184 // If either side is a float, the other side must be a float or int.
185 if (left->isFloat() || right->isFloat()) {
186 assert(left->isFloat() || left->isInt());
187 assert(right->isFloat() || right->isInt());
188 node->setType(left->isFloat() ? left : right);
193 // For now, assert everything else is integer and untagged.
194 assert(left->isInt() && right->isInt());
195 assert(!left->tag() && !right->tag());
200 SemanticAnalysis::visit(ReturnStatement *node)
202 visitForLoad(node->expression());
208 SemanticAnalysis::visit(ForStatement *node)
212 scope_ = node->scope();
213 if (node->declaration())
214 node->declaration()->accept(this);
215 if (node->condition())
216 visitForLoad(node->condition());
218 node->update()->accept(this);
219 node->body()->accept(this);
221 scope_ = scope_->enclosing();
226 SemanticAnalysis::visit(WhileStatement *node)
229 node->condition()->accept(this);
230 node->body()->accept(this);
235 SemanticAnalysis::visit(BlockStatement *node)
238 scope_ = node->scope();
239 for (size_t i = 0; i < node->statements()->length(); i++) {
240 Statement *statement = node->statements()->at(i);
241 statement->accept(this);
244 scope_ = scope_->enclosing();
248 SemanticAnalysis::visit(VariableDeclaration *node)
250 Type *type = ZONE()->types()->getPrimitiveForTag(node->tag());
254 if (node->postDimensions()) {
255 if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
260 for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
261 Expression *expr = node->postDimensions()->at(i);
264 if (!IsPrimitiveType(expr->type(), PrimitiveType_Int32)) {
265 typeError(expr, "integer");
270 if (expr->isIntegerLiteral()) {
271 size = expr->toIntegerLiteral()->value();
276 if (size >= INT_MAX / sizeof(int)) {
282 type = ZONE()->types()->unsafeArray(type, size);
285 // Right now, any array is allowed on the LIFO heap. In case the
286 // runtime actually decides to use the LIFO heap, we must reserve
287 // a slot so we can unwind the heap when the current scope leaves.
288 scope_->setUsesLifoHeap();
290 if (node->initialization()) {
291 Type *right = visitForLoad(node->initialization());
292 assert(TypeCheck(type, right));
296 node->variable()->setType(type);
300 SemanticAnalysis::visit(IntegerLiteral *node)
302 node->setType(ZONE()->types()->getPrimitive(PrimitiveType_Int32));
306 SemanticAnalysis::visit(ExpressionStatement *node)
308 node->expression()->accept(this);
312 SemanticAnalysis::visit(FunctionStatement *node)
314 scope_ = node->scope();
315 node->body()->accept(this);
320 SemanticAnalysis::visit(CallExpression *node)
325 SemanticAnalysis::visit(IfStatement *node)
327 visitForLoad(node->condition());
328 node->ifTrue()->accept(this);
330 node->ifFalse()->accept(this);
334 SemanticAnalysis::visit(IndexExpression *node)
336 Type *left = visitForRef(node->left());
337 Type *right = visitForLoad(node->right());
339 if (!right || !right->isInt()) {
340 typeError(node->right(), "integer");
343 if (!left || !left->isArray() || !left->contained()->isPrimitive()) {
344 typeError(node->left(), "array");
351 SemanticAnalysis::visit(EnumStatement *node)
353 // :TODO: test "enum Float { ..."
354 Name *tag = node->name();
356 Type *type = ZONE()->types()->getPrimitiveForTag(tag);
361 for (size_t i = 0; i < node->entries()->size(); i++) {
362 EnumStatement::Entry &entry = node->entries()->at(i);
364 BoxedPrimitive box = BoxedPrimitive::Int(value);
366 entry.expr->accept(this);
367 if (!EvaluateForConstant(entry.expr, &box))
368 fprintf(stderr, "expected constant integer expression\n");
370 assert(box.type() == PrimitiveType_Int32);
374 entry.name->set(type, box);
380 SemanticAnalysis::visit(FloatLiteral *node)
382 Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Float);
390 SemanticAnalysis::visit(BreakStatement *node)
392 assert(loopDepth_ > 0);
396 SemanticAnalysis::visit(ContinueStatement *node)
398 assert(loopDepth_ > 0);