Added initial String: support.
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 SemanticAnalysis::visit(Assignment *node)
195 visitForLoad(node->expression());
197 if (node->lvalue()->isIndexExpression()) {
198 node->lvalue()->accept(this);
199 node->setType(node->lvalue()->type()->contained());
201 NameProxy *proxy = node->lvalue()->toNameProxy();
202 if (!proxy->binding()->kind() == BoundName::VARIABLE) {
203 fprintf(stderr, "error\n");
207 Variable *var = proxy->binding()->toVariable();
211 if (var->type()->isReference())
212 node->setType(var->type()->contained());
214 node->setType(var->type());
217 assert(TypeCheckAssignment(node->type(), node->expression()->type()));
222 SemanticAnalysis::visit(BinaryExpression *node)
224 Type *left = visitForLoad(node->left());
225 Type *right = visitForLoad(node->right());
227 if (node->token() >= TOK_PLUS && node->token() <= TOK_SLASH) {
228 // Both sides must be primitive.
232 // If either side is a float, the other side must be a float or int.
233 if (left->isFloat() || right->isFloat()) {
234 assert(left->isFloat() || left->isInt32());
235 assert(right->isFloat() || right->isInt32());
236 node->setType(left->isFloat() ? left : right);
241 // For now, assert everything else is integer and untagged.
242 assert(left->isInt32() && right->isInt32());
243 assert(!left->tag() && !right->tag());
248 SemanticAnalysis::visit(ReturnStatement *node)
250 visitForLoad(node->expression());
256 SemanticAnalysis::visit(ForStatement *node)
260 scope_ = node->scope();
261 if (node->declaration())
262 node->declaration()->accept(this);
263 if (node->condition())
264 visitForLoad(node->condition());
266 node->update()->accept(this);
267 node->body()->accept(this);
269 scope_ = scope_->enclosing();
274 SemanticAnalysis::visit(WhileStatement *node)
277 node->condition()->accept(this);
278 node->body()->accept(this);
283 SemanticAnalysis::visit(BlockStatement *node)
286 scope_ = node->scope();
287 for (size_t i = 0; i < node->statements()->length(); i++) {
288 Statement *statement = node->statements()->at(i);
289 statement->accept(this);
292 scope_ = scope_->enclosing();
296 SemanticAnalysis::visit(VariableDeclaration *node)
299 Type *type = ZONE()->types()->getPrimitiveForTag(node->tag());
303 if (node->postDimensions()) {
305 if (node->initialization()) {
306 node->initialization()->accept(this);
307 if ((init = node->initialization()->type()) == NULL)
311 if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
316 // If we have an initializer, make sure it's the same type.
318 assert(init->levels() == node->postDimensions()->size());
322 for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
323 Expression *expr = node->postDimensions()->at(i);
326 if (!IsPrimitiveType(expr->type(), PrimitiveType_Int32)) {
327 typeError(expr, "integer");
332 if (expr->isIntegerLiteral()) {
333 size = expr->toIntegerLiteral()->value();
338 if (size >= INT_MAX / sizeof(int)) {
346 type = ZONE()->types()->unsafeArray(type, size);
349 assert(check->elements() != -1);
352 // If we're assigning a string, we're allowed to pad with
354 if (check->isCharArray()) {
355 assert(type->isCharArray());
356 assert(type->elements() >= check->elements());
363 check = check->contained();
366 // Right now, any array is allowed on the LIFO heap. In case the
367 // runtime actually decides to use the LIFO heap, we must reserve
368 // a slot so we can unwind the heap when the current scope leaves.
369 scope_->setUsesLifoHeap();
371 if (node->initialization()) {
372 Type *right = visitForLoad(node->initialization());
373 assert(TypeCheck(type, right));
375 if (type->primitive() == PrimitiveType_Char) {
381 node->variable()->setType(type);
385 SemanticAnalysis::visit(IntegerLiteral *node)
387 node->setType(ZONE()->types()->getPrimitive(PrimitiveType_Int32));
391 SemanticAnalysis::visit(ExpressionStatement *node)
393 node->expression()->accept(this);
397 SemanticAnalysis::preanalyze(FunctionStatement *node)
401 FixedArray *args = FixedArray::New(ZONE(), node->parameters()->size(), Heap::Tenure_Old);
405 // Apply types to arguments.
406 for (size_t i = 0; i < node->parameters()->size(); i++) {
407 Parameter *parameter = node->parameters()->at(i);
409 Type *type = ZONE()->types()->getPrimitiveForTag(parameter->tag());
413 if (parameter->reference()) {
414 type = ZONE()->types()->getReference(type);
419 args->set(ZONE(), i, type);
420 parameter->variable()->setType(type);
423 Type *returnType = ZONE()->types()->getPrimitive(PrimitiveType_Int32);
427 Type *funtype = ZONE()->types()->newFunction(returnType, args);
431 node->fun()->setType(funtype);
436 SemanticAnalysis::visit(FunctionStatement *node)
438 scope_ = node->scope();
440 // :TODO: call this ahead of time.
441 if (!preanalyze(node))
444 node->body()->accept(this);
448 // :TODO: use handles
450 TypeCheckParameter(Type *given, Type *actual)
452 if (actual->isReference()) {
453 if (given->isReference())
454 given = given->contained();
455 return TypeCheck(given, actual->contained());
458 return TypeCheck(given, actual);
462 SemanticAnalysis::visit(CallExpression *node)
464 visitForLoad(node->callee());
467 Type *type = node->callee()->type();
471 assert(type->isFunction());
472 assert(node->arguments()->size() == type->parameters()->length());
474 for (unsigned i = 0; i < node->arguments()->size(); i++) {
475 // Note: we don't compute references unless the callee needs a
477 Expression *expression = node->arguments()->at(i);
478 expression->accept(this);
480 Type *given = expression->type();
484 // If it's an IndexExpression, we special case the ability to compute
485 // a reference. Maybe we should compute actual Ref types for
487 if (expression->isIndexExpression())
488 given = given->contained();
490 Type *actual = Type::cast(type->parameters()->at(i));
491 assert(TypeCheckParameter(given, actual));
493 // If the actual is a reference, and the given is not, we'll need to
494 // compute a reference, which may be allocated on the stack.
495 if (actual->isReference() && !given->isReference())
496 scope_->setUsesLifoHeap();
501 SemanticAnalysis::visit(IfStatement *node)
503 visitForLoad(node->condition());
504 node->ifTrue()->accept(this);
506 node->ifFalse()->accept(this);
510 SemanticAnalysis::visit(IndexExpression *node)
513 Type *left = visitForRef(node->left());
514 Type *right = visitForLoad(node->right());
516 if (!right || !right->isInt32()) {
517 typeError(node->right(), "integer");
520 if (!left || !left->isArray() || !left->contained()->isPrimitive()) {
521 typeError(node->left(), "array");
528 SemanticAnalysis::visit(EnumStatement *node)
530 // :TODO: test "enum Float { ..."
531 Name *tag = node->name();
533 Type *type = ZONE()->types()->getPrimitiveForTag(tag);
538 for (size_t i = 0; i < node->entries()->size(); i++) {
539 EnumStatement::Entry &entry = node->entries()->at(i);
541 BoxedPrimitive box = BoxedPrimitive::Int(value);
543 entry.expr->accept(this);
544 if (!EvaluateForConstant(entry.expr, &box))
545 fprintf(stderr, "expected constant integer expression\n");
547 assert(box.type() == PrimitiveType_Int32);
551 entry.name->set(type, box);
557 SemanticAnalysis::visit(StringLiteral *node)
559 Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Char);
563 type = Type::NewArray(ZONE(), type, node->string()->length() + 1, true);
571 SemanticAnalysis::visit(FloatLiteral *node)
573 Type *type = ZONE()->types()->getPrimitive(PrimitiveType_Float);
581 SemanticAnalysis::visit(BreakStatement *node)
583 assert(loopDepth_ > 0);
587 SemanticAnalysis::visit(ContinueStatement *node)
589 assert(loopDepth_ > 0);