Implement ++ and -- operators.
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())
127 Type *type = expression->type();
128 if (type->isReference()) {
129 expression->setType(type->contained());
130 } else if (expression->isIndexExpression()) {
132 expression->setType(type->contained());
134 return expression->type();
138 SemanticAnalysis::visitForRef(Expression *expression)
140 expression->accept(this);
141 return expression->type();
145 TypeCheck(Type *left, Type *right)
150 if (left->isPrimitive()) {
151 if (!right->isPrimitive())
153 return left->primitive() == right->primitive();
160 TypeCheckAssignment(Type *left, Type *right)
165 if (left->isPrimitive()) {
166 if (!right->isPrimitive())
168 return left->primitive() == right->primitive();
171 if (left->isArray() != right->isArray())
174 if (left->levels() != 1 || right->levels() != 1)
177 if (left->elements() == -1 || right->elements() == -1)
180 if (!TypeCheckAssignment(left->contained(), right->contained()))
183 if (left->elements() != right->elements()) {
184 if (left->isCharArray() && (left->elements() >= right->elements()))
193 TypeCheckBinary(TokenKind token, Type *left, Type *right)
198 if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
199 (token >= TOK_ASSIGN_ADD && token <= TOK_ASSIGN_DIV))
201 // If either side is a float, the other side must be a float or int.
202 if (left->isFloat() || right->isFloat()) {
203 assert(left->isFloat() || left->isInt32());
204 assert(right->isFloat() || right->isInt32());
205 return left->isFloat() ? left : right;
209 assert(left->isInt32() && right->isInt32());
210 assert(!left->tag() && !right->tag());
215 SemanticAnalysis::visitForLValue(Expression *expression)
217 if (expression->isIndexExpression()) {
218 expression->accept(this);
219 if (!expression->type())
221 return expression->type()->contained();
224 if (!expression->isNameProxy()) {
229 NameProxy *proxy = expression->toNameProxy();
230 if (!proxy->binding()->kind() == BoundName::VARIABLE) {
231 fprintf(stderr, "error\n");
235 Variable *var = proxy->binding()->toVariable();
239 if (var->type()->isReference())
240 return var->type()->contained();
245 SemanticAnalysis::visit(Assignment *node)
247 visitForLoad(node->expression());
250 Type *type = visitForLValue(node->lvalue());
255 if (node->token() != TOK_ASSIGN)
256 assert(TypeCheckBinary(node->token(), node->type(), node->expression()->type()));
258 assert(TypeCheckAssignment(node->type(), node->expression()->type()));
262 SemanticAnalysis::visit(IncDecExpression *node)
265 Type *type = visitForLValue(node->expression());
269 assert(!type->isReference());
270 if (type->isArray()) {
276 assert((type->isInt32() && !type->tag()) || type->isFloat());
281 SemanticAnalysis::visit(BinaryExpression *node)
284 Type *left = visitForLoad(node->left());
285 Type *right = visitForLoad(node->right());
287 Type *result = TypeCheckBinary(node->token(), left, right);
288 node->setType(result);
292 SemanticAnalysis::visit(ReturnStatement *node)
294 visitForLoad(node->expression());
300 SemanticAnalysis::visit(ForStatement *node)
304 scope_ = node->scope();
305 if (node->initialization())
306 node->initialization()->accept(this);
307 if (node->condition())
308 visitForLoad(node->condition());
310 node->update()->accept(this);
311 node->body()->accept(this);
313 scope_ = scope_->enclosing();
318 SemanticAnalysis::visit(WhileStatement *node)
321 node->condition()->accept(this);
322 node->body()->accept(this);
327 SemanticAnalysis::visit(BlockStatement *node)
330 scope_ = node->scope();
331 for (size_t i = 0; i < node->statements()->length(); i++) {
332 Statement *statement = node->statements()->at(i);
333 statement->accept(this);
336 scope_ = scope_->enclosing();
340 SemanticAnalysis::visit(VariableDeclaration *node)
343 Type *type = ZONE()->types()->getPrimitiveForTag(node->tag());
347 if (node->postDimensions()) {
349 if (node->initialization()) {
350 node->initialization()->accept(this);
351 if ((init = node->initialization()->type()) == NULL)
355 if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
360 // If we have an initializer, make sure it's the same type.
362 assert(init->levels() == node->postDimensions()->size());
366 for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
367 Expression *expr = node->postDimensions()->at(i);
370 if (!IsPrimitiveType(expr->type(), PrimitiveType_Int32)) {
371 typeError(expr, "integer");
376 if (expr->isIntegerLiteral()) {
377 size = expr->toIntegerLiteral()->value();
382 if (size >= INT_MAX / sizeof(int)) {
390 type = ZONE()->types()->unsafeArray(type, size);
393 assert(check->elements() != -1);
396 // If we're assigning a string, we're allowed to pad with
398 if (check->isCharArray()) {
399 assert(type->isCharArray());
400 assert(type->elements() >= check->elements());
407 check = check->contained();
410 // Right now, any array is allowed on the LIFO heap. In case the
411 // runtime actually decides to use the LIFO heap, we must reserve
412 // a slot so we can unwind the heap when the current scope leaves.
413 scope_->setUsesLifoHeap();
415 if (node->initialization()) {
416 Type *right = visitForLoad(node->initialization());
417 assert(TypeCheck(type, right));
419 if (type->primitive() == PrimitiveType_Char) {
425 node->variable()->setType(type);
429 SemanticAnalysis::visit(IntegerLiteral *node)
431 node->setType(ZONE()->types()->getPrimitive(PrimitiveType_Int32));
435 SemanticAnalysis::visit(ExpressionStatement *node)
437 node->expression()->accept(this);
441 SemanticAnalysis::preanalyze(FunctionStatement *node)
445 FixedArray *args = FixedArray::New(ZONE(), node->parameters()->size(), Heap::Tenure_Old);
449 // Apply types to arguments.
450 for (size_t i = 0; i < node->parameters()->size(); i++) {
451 Parameter *parameter = node->parameters()->at(i);
453 Type *type = ZONE()->types()->getPrimitiveForTag(parameter->tag());
457 if (parameter->reference()) {
458 type = ZONE()->types()->getReference(type);
463 args->set(ZONE(), i, type);
464 parameter->variable()->setType(type);
467 Type *returnType = ZONE()->types()->getPrimitive(PrimitiveType_Int32);
471 Type *funtype = ZONE()->types()->newFunction(returnType, args);
475 node->fun()->setType(funtype);
480 SemanticAnalysis::visit(FunctionStatement *node)
482 scope_ = node->scope();
484 // :TODO: call this ahead of time.
485 if (!preanalyze(node))
488 node->body()->accept(this);
492 // :TODO: use handles
494 TypeCheckParameter(Type *given, Type *actual)
496 if (actual->isReference()) {
497 if (given->isReference())
498 given = given->contained();
499 return TypeCheck(given, actual->contained());
502 return TypeCheck(given, actual);
506 SemanticAnalysis::visit(CallExpression *node)
508 visitForLoad(node->callee());
511 Type *type = node->callee()->type();
515 assert(type->isFunction());
516 assert(node->arguments()->size() == type->parameters()->length());
518 for (unsigned i = 0; i < node->arguments()->size(); i++) {
519 // Note: we don't compute references unless the callee needs a
521 Expression *expression = node->arguments()->at(i);
522 expression->accept(this);
524 Type *given = expression->type();
528 // If it's an IndexExpression, we special case the ability to compute
529 // a reference. Maybe we should compute actual Ref types for
531 if (expression->isIndexExpression())
532 given = given->contained();
534 Type *actual = Type::cast(type->parameters()->at(i));
535 assert(TypeCheckParameter(given, actual));
537 // If the actual is a reference, and the given is not, we'll need to
538 // compute a reference, which may be allocated on the stack.
539 if (actual->isReference() && !given->isReference())
540 scope_->setUsesLifoHeap();
545 SemanticAnalysis::visit(IfStatement *node)
547 visitForLoad(node->condition());
548 node->ifTrue()->accept(this);
550 node->ifFalse()->accept(this);
554 SemanticAnalysis::visit(IndexExpression *node)
557 Type *left = visitForRef(node->left());
558 Type *right = visitForLoad(node->right());
560 if (!right || !right->isInt32()) {
561 typeError(node->right(), "integer");
564 if (!left || !left->isArray() || !left->contained()->isPrimitive()) {
565 typeError(node->left(), "array");
572 SemanticAnalysis::visit(EnumStatement *node)
574 // :TODO: test "enum Float { ..."
575 Name *tag = node->name();
577 Type *type = ZONE()->types()->getPrimitiveForTag(tag);
582 for (size_t i = 0; i < node->entries()->size(); i++) {
583 EnumStatement::Entry &entry = node->entries()->at(i);
585 BoxedPrimitive box = BoxedPrimitive::Int(value);
587 entry.expr->accept(this);
588 if (!EvaluateForConstant(entry.expr, &box))
589 fprintf(stderr, "expected constant integer expression\n");
591 assert(box.type() == PrimitiveType_Int32);
595 entry.name->set(type, box);
601 SemanticAnalysis::visit(StringLiteral *node)
603 Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Char);
607 type = Type::NewArray(ZONE(), type, node->string()->length() + 1, true);
615 SemanticAnalysis::visit(FloatLiteral *node)
617 Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Float);
625 SemanticAnalysis::visit(BreakStatement *node)
627 assert(loopDepth_ > 0);
631 SemanticAnalysis::visit(ContinueStatement *node)
633 assert(loopDepth_ > 0);