Added support for do/while loops.
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"
24 IsPrimitiveType(Type *type, PrimitiveType primitive)
29 if (!type->isPrimitive())
32 return primitive == type->primitive();
36 EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
41 *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
45 *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
53 EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
55 switch (expression->kind()) {
56 case AstNode::kBinaryExpression:
60 BinaryExpression *b = expression->toBinaryExpression();
61 if (!EvaluateForConstant(b->left(), &left) ||
62 !EvaluateForConstant(b->right(), &right))
66 return EvaluateBinaryOperation(b->token(), left, right, out);
69 case AstNode::kNameProxy:
71 NameProxy *proxy = expression->toNameProxy();
72 if (proxy->binding()->kind() != BoundName::CONSTANT)
75 NamedConstant *c = proxy->binding()->toNamedConstant();
76 if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
83 case AstNode::kIntegerLiteral:
84 *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
92 SemanticAnalysis::SemanticAnalysis(ParseTree *tree)
98 SemanticAnalysis::analyze()
100 for (size_t i = 0; i < tree_->statements()->length(); i++) {
101 Statement *statement = tree_->statements()->at(i);
102 statement->accept(this);
109 SemanticAnalysis::visit(NameProxy *name)
111 name->setType(name->binding()->type());
115 SemanticAnalysis::visitForLoad(Expression *expression)
117 expression->accept(this);
118 if (expression->type() && expression->type()->isArray())
119 expression->setType(expression->type()->contained());
120 return expression->type();
124 SemanticAnalysis::visitForRef(Expression *expression)
126 expression->accept(this);
127 return expression->type();
131 TypeCheck(Type *left, Type *right)
136 if (left->isPrimitive()) {
137 if (!right->isPrimitive())
139 return left->primitive() == right->primitive();
146 SemanticAnalysis::visit(Assignment *node)
148 visitForLoad(node->expression());
150 if (node->lvalue()->isIndexExpression()) {
151 node->lvalue()->accept(this);
152 node->setType(node->lvalue()->type()->contained());
154 NameProxy *proxy = node->lvalue()->toNameProxy();
155 if (!proxy->binding()->kind() == BoundName::VARIABLE) {
156 fprintf(stderr, "error\n");
160 Variable *var = proxy->binding()->toVariable();
161 node->setType(var->type());
164 assert(TypeCheck(node->type(), node->expression()->type()));
169 SemanticAnalysis::visit(BinaryExpression *node)
171 Type *left = visitForLoad(node->left());
172 Type *right = visitForLoad(node->right());
174 if (node->token() >= TOK_PLUS && node->token() <= TOK_SLASH) {
175 // Both sides must be primitive.
179 // If either side is a float, the other side must be a float or int.
180 if (left->isFloat() || right->isFloat()) {
181 assert(left->isFloat() || left->isInt());
182 assert(right->isFloat() || right->isInt());
183 node->setType(left->isFloat() ? left : right);
188 // For now, assert everything else is integer and untagged.
189 assert(left->isInt() && right->isInt());
190 assert(!left->tag() && !right->tag());
195 SemanticAnalysis::visit(ReturnStatement *node)
197 visitForLoad(node->expression());
203 SemanticAnalysis::visit(ForStatement *node)
205 if (node->declaration())
206 node->declaration()->accept(this);
207 if (node->condition())
208 visitForLoad(node->condition());
210 node->update()->accept(this);
211 node->body()->accept(this);
215 SemanticAnalysis::visit(WhileStatement *node)
217 node->condition()->accept(this);
218 node->body()->accept(this);
222 SemanticAnalysis::visit(BlockStatement *node)
224 for (size_t i = 0; i < node->statements()->length(); i++) {
225 Statement *statement = node->statements()->at(i);
226 statement->accept(this);
231 SemanticAnalysis::visit(VariableDeclaration *node)
233 Type *type = Type::NewPrimitive(node->tag());
237 if (node->postDimensions()) {
238 if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
243 for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
244 Expression *expr = node->postDimensions()->at(i);
247 if (!IsPrimitiveType(expr->type(), PrimitiveType_Int32)) {
248 typeError(expr, "integer");
253 if (expr->isIntegerLiteral()) {
254 size = expr->toIntegerLiteral()->value();
259 if (size >= INT_MAX / sizeof(int)) {
265 type = Type::NewUnsafeArray(type, size);
268 Type *right = visitForLoad(node->initialization());
269 assert(TypeCheck(type, right));
272 node->variable()->setType(type);
276 SemanticAnalysis::visit(IntegerLiteral *node)
278 Type *type = Type::NewPrimitive(NULL);
283 SemanticAnalysis::visit(ExpressionStatement *node)
285 node->expression()->accept(this);
289 SemanticAnalysis::visit(FunctionStatement *node)
291 node->body()->accept(this);
295 SemanticAnalysis::visit(CallExpression *node)
300 SemanticAnalysis::visit(IfStatement *node)
305 SemanticAnalysis::visit(IndexExpression *node)
307 Type *left = visitForRef(node->left());
308 Type *right = visitForLoad(node->right());
310 if (!right || !right->isInt()) {
311 typeError(node->right(), "integer");
314 if (!left || !left->isArray() || !left->contained()->isPrimitive()) {
315 typeError(node->left(), "array");
322 SemanticAnalysis::visit(EnumStatement *node)
324 // :TODO: test "enum Float { ..."
325 Name *tag = node->name();
327 Type *type = Type::NewPrimitive(tag);
332 for (size_t i = 0; i < node->entries()->size(); i++) {
333 EnumStatement::Entry &entry = node->entries()->at(i);
335 BoxedPrimitive box = BoxedPrimitive::Int(value);
337 entry.expr->accept(this);
338 if (!EvaluateForConstant(entry.expr, &box))
339 fprintf(stderr, "expected constant integer expression\n");
341 assert(box.type() == PrimitiveType_Int32);
345 entry.name->set(type, box);
351 SemanticAnalysis::visit(FloatLiteral *node)
353 Type *type = Type::NewPrimitive(PrimitiveType_Float);