src/SemanticAnalysis.cpp
author David Anderson <dvander@alliedmods.net>
Mon Jul 30 22:30:38 2012 -0700 (2012-07-30)
changeset 144 a8735148dcf0
parent 143 393f1b8ac8c3
child 145 e9d804821c48
permissions -rw-r--r--
Support -x as a constant expression.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of JITCraft.
     6  *
     7  * JITCraft is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * JITCraft. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #include <string.h>
    20 #include "SemanticAnalysis.h"
    21 #include "Types.h"
    22 #include "Zone.h"
    23 #include "TypeManager.h"
    24 #include "Scopes.h"
    25 #include "NameBinding.h"
    26 #include "Heap-inl.h"
    27 #include "Strings.h"
    28 
    29 using namespace ke;
    30 
    31 static inline bool
    32 IsPrimitiveType(Type *type, PrimitiveType primitive)
    33 {
    34     if (!type)
    35         return false;
    36 
    37     if (!type->isPrimitive())
    38         return false;
    39 
    40     return primitive == type->primitive();
    41 }
    42 
    43 static inline bool
    44 EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
    45                         BoxedPrimitive *out)
    46 {
    47     switch (kind) {
    48       case TOK_PLUS:
    49         *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
    50         return true;
    51 
    52       case TOK_SHL:
    53         *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
    54         return true;
    55 
    56       default:
    57         return false;
    58     }
    59 }
    60 
    61 static inline bool
    62 EvaluateUnaryOperation(TokenKind kind, const BoxedPrimitive &inner, BoxedPrimitive *out)
    63 {
    64   switch (kind) {
    65     case TOK_MINUS:
    66       *out = BoxedPrimitive::Int(-inner.toInt());
    67       return true;
    68 
    69     default:
    70       return false;
    71   }
    72 }
    73 
    74 static bool
    75 EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
    76 {
    77     switch (expression->kind()) {
    78       case AstNode::kBinaryExpression:
    79       {
    80         BoxedPrimitive left;
    81         BoxedPrimitive right;
    82         BinaryExpression *b = expression->toBinaryExpression();
    83         if (!EvaluateForConstant(b->left(), &left) ||
    84             !EvaluateForConstant(b->right(), &right))
    85         {
    86             return false;
    87         }
    88         return EvaluateBinaryOperation(b->token(), left, right, out);
    89       }
    90 
    91       case AstNode::kUnaryExpression:
    92       {
    93         BoxedPrimitive inner;
    94         UnaryExpression *u = expression->toUnaryExpression();
    95         if (!EvaluateForConstant(u->expression(), &inner))
    96             return false;
    97         return EvaluateUnaryOperation(u->token(), inner, out);
    98       }
    99 
   100       case AstNode::kNameProxy:
   101       {
   102         NameProxy *proxy = expression->toNameProxy();
   103         if (proxy->binding()->kind() != BoundName::CONSTANT)
   104             return false;
   105 
   106         NamedConstant *c = proxy->binding()->toNamedConstant();
   107         if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
   108             return false;
   109 
   110         *out = c->value();
   111         return true;
   112       }
   113 
   114       case AstNode::kIntegerLiteral:
   115         *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
   116         return true;
   117 
   118       default:
   119         return false;
   120     }
   121 }
   122 
   123 SemanticAnalysis::SemanticAnalysis(Zone *zone, CompileContext &cc, ParseTree *tree)
   124   : zone_(zone),
   125     cc_(cc),
   126     tree_(tree),
   127     scope_(NULL),
   128     loop_(NULL)
   129 {
   130 }
   131 
   132 bool
   133 SemanticAnalysis::analyze()
   134 {
   135     if (cc_.failures())
   136         return false;
   137 
   138     scope_ = tree_->scope();
   139 
   140     for (size_t i = 0; i < tree_->statements()->length(); i++) {
   141         Statement *statement = tree_->statements()->at(i);
   142         if (statement->isFunctionStatement()) {
   143             FunctionStatement *funstmt = statement->toFunctionStatement();
   144             if (!preanalyze(funstmt))
   145                 return false;
   146         }
   147     }
   148 
   149     for (size_t i = 0; i < tree_->statements()->length(); i++) {
   150         Statement *statement = tree_->statements()->at(i);
   151         statement->accept(this);
   152     }
   153 
   154     if (!determineLiveFunctions())
   155         return false;
   156 
   157     return !cc_.failures();
   158 }
   159 
   160 bool
   161 SemanticAnalysis::determineLiveFunctions()
   162 {
   163     Vector<NamedFunction *> worklist;
   164 
   165     // Add the root set.
   166     for (size_t i = 0; i < tree_->statements()->length(); i++) {
   167         Statement *statement = tree_->statements()->at(i);
   168         if (!statement->isFunctionStatement())
   169             continue;
   170 
   171         FunctionStatement *stmt = statement->toFunctionStatement();
   172         NamedFunction  *fun = stmt->fun();
   173         if (!fun->used())
   174             continue;
   175 
   176         for (size_t i = 0; i < fun->usedGlobals()->length(); i++) {
   177             NamedFunction *name = fun->usedGlobals()->at(i)->toNamedFunction();
   178 
   179             // Names in these lists are always unused, however, we mark them
   180             // as used while inserting into the work queue, to avoid double-
   181             // insertion.
   182             if (name->used())
   183                 continue;
   184 
   185             if (!worklist.append(name))
   186                 return false;
   187 
   188             name->setUsed();
   189         }
   190     }
   191 
   192     while (!worklist.empty()) {
   193         NamedFunction *fun = worklist.popCopy();
   194 
   195         for (size_t i = 0; i < fun->usedGlobals()->length(); i++) {
   196             NamedFunction *name = fun->usedGlobals()->at(i)->toNamedFunction();
   197             if (name->used())
   198                 continue;
   199             if (!worklist.append(name))
   200                 return false;
   201             name->setUsed();
   202         }
   203     }
   204 
   205     return true;
   206 }
   207 
   208 
   209 Type *
   210 SemanticAnalysis::visitAndApplyType(Expression *expression)
   211 {
   212     expression->accept(this);
   213     return expression->type();
   214 }
   215 
   216 Type *
   217 SemanticAnalysis::visitForLoad(Expression *expression)
   218 {
   219     Local<Type> type(zone_, visitAndApplyType(expression));
   220     if (!type)
   221         return NULL;
   222 
   223     if (type->isReference()) {
   224         expression->setType(type->contained());
   225     } else if (expression->isIndexExpression()) {
   226         if (type->isArray())
   227             expression->setType(type->contained());
   228     } else if (expression->isCallExpression()) {
   229         if (type->isVoid()) {
   230             CallExpression *call = expression->toCallExpression();
   231             cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
   232             return NULL;
   233         }
   234     }
   235 
   236     return expression->type();
   237 }
   238 
   239 // :TODO: this leaks an interior pointer.
   240 static inline const char *
   241 GetTypeName(Type *type)
   242 {
   243     if (type->isArray())
   244         return "array";
   245     if (type->isFunction())
   246         return "function";
   247     if (type->isVoid())
   248         return "void";
   249     if (type->isReference())
   250         type = type->contained();
   251     if (type->tag())
   252         return type->tag()->chars();
   253     return "int";
   254 }
   255 
   256 void
   257 SemanticAnalysis::unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type)
   258 {
   259     const char *op = TokenNames[token];
   260     const char *name = GetTypeName(type);
   261 
   262     cc_.reportError(node->pos(), Message_UnaryTypeError, op, name);
   263 }
   264 
   265 void
   266 SemanticAnalysis::binaryTypeError(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
   267 {
   268     const char *op = TokenNames[token];
   269     const char *leftName = GetTypeName(left);
   270     const char *rightName = GetTypeName(right);
   271 
   272     cc_.reportError(node->pos(), Message_BinaryTypeError, op, leftName, rightName);
   273 }
   274 
   275 Type *
   276 SemanticAnalysis::typeCheckBinary(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
   277 {
   278     if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
   279         (token >= TOK_ASSIGN_ADD && token <= TOK_ASSIGN_DIV))
   280     {
   281         // If either side is a float, the other side must be a float or int.
   282         if (left->isFloat() || right->isFloat()) {
   283             Type *floatType = left->isFloat() ? left : right;
   284             Type *other = left->isFloat() ? right : left;
   285             if (other->isFloat() || (other->isInt32() && !other->tag()))
   286                 return floatType;
   287         }
   288     }
   289 
   290     if (token == TOK_OR || token == TOK_AND) {
   291         if (!canTest(node, left) || !canTest(node, right))
   292             return NULL;
   293         return zone_->types()->getPrimitive(PrimitiveType_Int32);
   294     }
   295 
   296     if (token >= TOK_EQUALS && token <= TOK_GE) {
   297         if ((left->isFloat() || (left->isInt32() && !left->tag())) &&
   298             (right->isFloat() || (right->isInt32() && !right->tag())))
   299         {
   300             return zone_->types()->getPrimitive(PrimitiveType_Int32);
   301         }
   302         binaryTypeError(node, token, left, right);
   303         return NULL;
   304     }
   305 
   306     if ((!left->isInt32() || left->tag()) ||
   307         (!right->isInt32() || right->tag()))
   308     {
   309         binaryTypeError(node, token, left, right);
   310         return NULL;
   311     }
   312 
   313     return left;
   314 }
   315 
   316 bool
   317 SemanticAnalysis::canTest(AstNode *node, Handle<Type> type)
   318 {
   319     if (type->isArray() || (type->isInt32() && type->tag())) {
   320         cc_.reportError(node->pos(), Message_ArrayIsNotBoolean);
   321         return false;
   322     }
   323     return true;
   324 }
   325 
   326 Type *
   327 SemanticAnalysis::visitForLValue(Expression *expression)
   328 {
   329     if (expression->isIndexExpression()) {
   330         Type *type = visitAndApplyType(expression);
   331         if (!type)
   332             return NULL;
   333 
   334         if (type->isConst()) {
   335             cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
   336             return NULL;
   337         }
   338 
   339         return type->contained();
   340     }
   341 
   342     if (!expression->isNameProxy()) {
   343         cc_.reportError(expression->pos(), Message_ExpectedLValue);
   344         return NULL;
   345     }
   346 
   347     NameProxy *proxy = expression->toNameProxy();
   348     if (!proxy->binding()->kind() == BoundName::VARIABLE) {
   349         cc_.reportError(expression->pos(), Message_ExpectedLValue);
   350         return NULL;
   351     }
   352 
   353     Variable *var = proxy->binding()->toVariable();
   354     if (!var->type())
   355         return NULL;
   356 
   357     if  (var->type()->isReference()) {
   358         if (var->type()->isConst()) {
   359             cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
   360             return NULL;
   361         }
   362         return var->type()->contained();
   363     }
   364     return var->type();
   365 }
   366 
   367 SemanticAnalysis::ControlStatus
   368 SemanticAnalysis::visitForControl(Statement *statement)
   369 {
   370     ControlScope scope(&control_);
   371     statement->accept(this);
   372     return scope.status();
   373 }
   374 
   375 void
   376 SemanticAnalysis::visit(NameProxy *name)
   377 {
   378     BoundName *binding = name->binding();
   379 
   380     if (binding->scope()->kind() == Scope::GLOBAL) {
   381         if (!function_ || function_->isPublic()) {
   382             // Whatever we're referencing must be kept alive no matter what.
   383             // As such, we simply mark it used, and don't do anything special.
   384             binding->setUsed();
   385         } else if (!binding->used() && binding->kind() == BoundName::FUNCTION) {
   386             // Otherwise, we're inside a normal stock or function. Since we
   387             // don't really know if we've been used yet, we shouldn't
   388             // prematurely references as alive. Instead, we keep a list of
   389             // which names have been used, so we can mark them later if needed.
   390             //
   391             // Note that we skip this step if the binding is already in the
   392             // root set.
   393             if (!function_->addUsedGlobal(binding))
   394                 return;
   395         }
   396     }
   397 
   398     name->setType(binding->type());
   399 }
   400 
   401 void
   402 SemanticAnalysis::visit(Assignment *node)
   403 {
   404     Local<Type> exprType(zone_, visitForLoad(node->expression()));
   405     if (!exprType)
   406         return ;
   407 
   408     Local<Type> type(zone_, visitForLValue(node->lvalue()));
   409     if (!type)
   410         return;
   411 
   412     if (node->token() != TOK_ASSIGN) {
   413         if (!typeCheckBinary(node, node->token(), type, exprType))
   414             return;
   415     }
   416 
   417     if (!typeCheckAssignment(node, exprType, type, true))
   418         return;
   419 
   420     node->setType(type);
   421 }
   422 
   423 void
   424 SemanticAnalysis::visit(IncDecExpression *node)
   425 {
   426     Local<Type> type(zone_, visitForLValue(node->expression()));
   427     if (!type)
   428         return;
   429 
   430     assert(!type->isReference());
   431 
   432     if ((!type->isInt32() || (type->isInt32() && type->tag())) && !type->isFloat()) {
   433         unaryTypeError(node, node->token(), type);
   434         return;
   435     }
   436 
   437     node->setType(type);
   438 }
   439 
   440 void
   441 SemanticAnalysis::visit(UnaryExpression *node)
   442 {
   443     Local<Type> type(zone_, visitForLoad(node->expression()));
   444     if (!type)
   445         return;
   446 
   447     switch (node->token())
   448     {
   449       case TOK_NOT:
   450         if (!canTest(node->expression(), type))
   451             return;
   452         type = zone_->types()->getPrimitive(PrimitiveType_Int32);
   453         if (!type)
   454             return;
   455         node->setType(type);
   456         break;
   457 
   458       case TOK_MINUS:
   459         if (!type->isFloat() && (!type->isInt32() || type->tag())) {
   460             unaryTypeError(node, node->token(), type);
   461             return;
   462         }
   463         node->setType(type);
   464         break;
   465 
   466       case TOK_LABEL:
   467       {
   468         Local<String> tag(zone_, node->tag());
   469         Local<Type> to(zone_, zone_->types()->getPrimitiveForTag(tag));
   470         if (!to)
   471             return;
   472 
   473         if ((!type->isFloat() && !type->isInt32()) ||
   474             (!to->isFloat() && !to->isInt32()))
   475         {
   476             unaryTypeError(node, node->token(), type);
   477             return;
   478         }
   479 
   480         node->setType(to);
   481         break;
   482       }
   483 
   484       default:
   485         assert(node->token() == TOK_TILDE);
   486         if (!type->isInt32() || type->tag()) {
   487             unaryTypeError(node, node->token(), type);
   488             return;
   489         }
   490         node->setType(type);
   491         break;
   492     }
   493 }
   494 
   495 void
   496 SemanticAnalysis::visit(TernaryExpression *node)
   497 {
   498     Local<Type> type(zone_, visitForLoad(node->condition()));
   499     if (!type)
   500         return;
   501 
   502     if (!canTest(node->condition(), type))
   503         return;
   504 
   505     Local<Type> left(zone_, visitForLoad(node->left()));
   506     Local<Type> right(zone_, visitForLoad(node->right()));
   507     if (!left || !right)
   508         return;
   509 
   510     if (left != right) {
   511         binaryTypeError(node, TOK_QMARK, left, right);
   512         return;
   513     }
   514 }
   515 
   516 void
   517 SemanticAnalysis::visit(BinaryExpression *node)
   518 {
   519     Local<Type> left(zone_, visitForLoad(node->left()));
   520     Local<Type> right(zone_, visitForLoad(node->right()));
   521     if (!left || !right)
   522         return;
   523 
   524     Local<Type> result(zone_, typeCheckBinary(node, node->token(), left, right));
   525     if (!result)
   526         return;
   527 
   528     node->setType(result);
   529 }
   530 
   531 void
   532 SemanticAnalysis::visit(ReturnStatement *node)
   533 {
   534     // Set this early, so if we error we don't get more errors.
   535     control_->returns(Returns_Always);
   536 
   537     if (!node->expression()) {
   538         if (!function_->type()->returnType()->isVoid())
   539             cc_.reportError(node->pos(), Message_NotAllPathsReturnValue);
   540         return;
   541     }
   542 
   543     Local<Type> type(zone_, visitForLoad(node->expression()));
   544     if (!type)
   545         return;
   546 
   547     Local<Type> returnType(zone_, function_->type()->returnType());
   548     if (!typeCheckAssignment(node, type, returnType, true))
   549         return;
   550 }
   551 
   552 void
   553 SemanticAnalysis::visit(ForStatement *node)
   554 {
   555     LoopScope loop(&loop_);
   556 
   557     if (node->scope())
   558         scope_ = node->scope();
   559 
   560     if (node->initialization())
   561         node->initialization()->accept(this);
   562 
   563     if (node->condition()) {
   564         Local<Type> type(zone_, visitForLoad(node->condition()));
   565         if (!type || !canTest(node->condition(), type)) {
   566             return;
   567         }
   568     }
   569 
   570     if (node->update())
   571         node->update()->accept(this);
   572 
   573     ControlStatus status = visitForControl(node->body());
   574 
   575     // If there is a condition, we treat this like a while loop. Otherwise,
   576     // join point is only reachable if the loop contains a break. The
   577     // termination status doesn't tell us anything yet.
   578     if (node->condition() || loop.breaks())
   579         control_->merge(status, ControlStatus(false, Returns_Never));
   580     else
   581         control_->terminate(status.returns());
   582 
   583     if (node->scope())
   584         scope_ = scope_->enclosing();
   585 }
   586 
   587 void 
   588 SemanticAnalysis::visit(WhileStatement *node)
   589 {
   590     LoopScope loop(&loop_);
   591 
   592     Local<Type> type(zone_, visitForLoad(node->condition()));
   593     if (!type || !canTest(node->condition(), type)) {
   594         return;
   595     }
   596 
   597     ControlStatus status = visitForControl(node->body());
   598 
   599     // Detect loops that will always have a fork in the control-flow graph.
   600     // This will be a |while| loop, or a |do-while| loop whose body does
   601     // not terminate.
   602     //
   603     // For now, we treat these as an |if| regardless of the direction the
   604     // branch can take. That means the control-flow is always conditional.
   605     if (node->token() == TOK_WHILE ||
   606         !status.terminates() ||
   607         loop.breaks())
   608     {
   609         control_->merge(status, ControlStatus(false, Returns_Never));
   610     } else {
   611         // At this point, we've got a do-while loop with a |return| or
   612         // |continue|, meaning that the rest of the block is unreachable.
   613         control_->terminate(status.returns());
   614     }
   615 }
   616 
   617 void
   618 SemanticAnalysis::visit(BlockStatement *node)
   619 {
   620     if (node->scope())
   621         scope_ = node->scope();
   622     for (size_t i = 0; i < node->statements()->length(); i++) {
   623         Statement *statement = node->statements()->at(i);
   624         statement->accept(this);
   625     }
   626     if (node->scope())
   627         scope_ = scope_->enclosing();
   628 }
   629 
   630 void
   631 SemanticAnalysis::visit(VariableDeclaration *node)
   632 {
   633     Local<String> tag(zone_, node->tag());
   634     Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
   635     if (!type)
   636         return;
   637 
   638     if (node->postDimensions()) {
   639         Local<Type> init(zone_);
   640         if (node->initialization()) {
   641             if ((init = visitForLoad(node->initialization())) == NULL)
   642                 return;
   643         }
   644 
   645         if (node->postDimensions()->length() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
   646             cc_.reportError(node->pos(), Message_MaximumArrayDepth);
   647             return;
   648         }
   649 
   650         // If we have an initializer, make sure it's the same type.
   651         if (init && node->postDimensions()->length() != init->levels()) {
   652             cc_.reportError(node->pos(), Message_ArrayInitializerDepth);
   653             return;
   654         }
   655 
   656         Local<Type> check(zone_, init);
   657         for (size_t i = node->postDimensions()->length() - 1; i < node->postDimensions()->length(); i--) {
   658             Expression *expr = node->postDimensions()->at(i);
   659             int size = -1;
   660 
   661             if (expr) {
   662                 Local<Type> exprType(zone_, visitForLoad(expr));
   663                 if (!exprType)
   664                     return;
   665 
   666                 if (!IsPrimitiveType(exprType, PrimitiveType_Int32)) {
   667                     cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
   668                     return;
   669                 }
   670 
   671                 BoxedPrimitive box;
   672                 if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
   673                     size = box.toInt();
   674                     if (size <= 0) {
   675                         cc_.reportError(expr->pos(), Message_BadArraySize);
   676                         return;
   677                     }
   678                     if (size >= int(INT_MAX / sizeof(int))) {
   679                         cc_.reportError(expr->pos(), Message_ArraySizeTooBig);
   680                         return;
   681                     }
   682 
   683                     if (check) {
   684                         if (check->elements() == -1) {
   685                             cc_.reportError(expr->pos(), Message_ArraySizeCannotBeDetermined);
   686                             return;
   687                         }
   688 
   689                         if (check->isCharArray()) {
   690                             if (check->elements() > size) {
   691                                 cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
   692                                 return;
   693                             }
   694                         } else if (check->elements() != size) {
   695                             cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, unsigned(i));
   696                             return;
   697                         }
   698                     }
   699                 } else {
   700                     if (init) {
   701                         cc_.reportError(node->pos(), Message_DynamicArrayHasInitializer);
   702                         return;
   703                     }
   704 
   705                     // here until we get dynamic array support.
   706                     cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
   707                     return;
   708                 }
   709             } else {
   710                 // Infer the size from the initializer.
   711                 if (!init) {
   712                     cc_.reportError(node->pos(), Message_ArraySizeNotSpecified);
   713                     return;
   714                 }
   715                 if (init->elements() == -1) {
   716                     cc_.reportError(node->pos(), Message_ArraySizeCannotBeDetermined);
   717                     return;
   718                 }
   719                 size = init->elements();
   720             }
   721 
   722             type = zone_->types()->unsafeArray(type, size, false);
   723             if (!type)
   724                 return;
   725 
   726             if (check)
   727                 check = check->contained();
   728         }
   729 
   730         // If this variable is stack allocated, we could use the LIFO heap
   731         // to allocate it. If that's the case, make sure to reserve a slot
   732         // so we can unwind the LIFO heap at the end of this scope.
   733         if (!node->variable()->needsHeapAllocation())
   734             scope_->setUsesLifoHeap();
   735     } else {
   736         if (node->initialization()) {
   737             Local<Type> right(zone_, visitForLoad(node->initialization()));
   738             if (!right)
   739                 return;
   740             if (!typeCheckAssignment(node, type, right, true))
   741                 return;
   742         }
   743         if (type->primitive() == PrimitiveType_Char) {
   744             cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
   745             return;
   746         }
   747     }
   748 
   749     node->variable()->setType(type);
   750 }
   751 
   752 void
   753 SemanticAnalysis::visit(IntegerLiteral *node)
   754 {
   755     node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
   756 }
   757 
   758 void
   759 SemanticAnalysis::visit(BooleanLiteral *node)
   760 {
   761     node->setType(zone_->types()->getPrimitive(PrimitiveType_Bool));
   762 }
   763 
   764 void
   765 SemanticAnalysis::visit(ExpressionStatement *node)
   766 {
   767     visitAndApplyType(node->expression());
   768 }
   769 
   770 bool
   771 SemanticAnalysis::preanalyze(FunctionStatement *node)
   772 {
   773     Local<FixedArray> args(zone_, FixedArray::New(zone_, node->parameters()->length(), Heap::Tenure_Old));
   774     if (!args)
   775         return false;
   776 
   777     // Apply types to arguments.
   778     for (size_t i = 0; i < node->parameters()->length(); i++) {
   779         Parameter *parameter = node->parameters()->at(i);
   780         
   781         Local<String> tag(zone_, parameter->tag());
   782         Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
   783         if (!type)
   784             return false;
   785 
   786         if (parameter->reference()) {
   787             if (parameter->dimensions()) {
   788                 cc_.reportError(parameter->variable()->pos(), Message_ArrayCantBeReference);
   789                 return NULL;
   790             }
   791 
   792             type = zone_->types()->getReference(type, parameter->isConst());
   793             if (!type)
   794                 return false;
   795         } else if (parameter->dimensions()) {
   796             if (parameter->dimensions()->length() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
   797                 cc_.reportError(parameter->variable()->pos(), Message_MaximumArrayDepth);
   798                 return false;
   799             }
   800 
   801             if (node->fun()->isNative() && parameter->dimensions()->length() > 1) {
   802                 cc_.reportError(parameter->variable()->pos(), Message_MultiArrayInNative);
   803                 return false;
   804             }
   805 
   806             for (size_t i = parameter->dimensions()->length() - 1;
   807                  i < parameter->dimensions()->length();
   808                  i++)
   809             {
   810                 int size = Type::UNKNOWN_SIZE;
   811                 if (Expression *expr = parameter->dimensions()->at(i)) {
   812                     BoxedPrimitive box;
   813                     if (!EvaluateForConstant(expr, &box)) {
   814                         cc_.reportError(expr->pos(), Message_ArraySizeMustBeConstant);
   815                         return false;
   816                     }
   817                     size = box.toInt();
   818                 }
   819 
   820                 type = zone_->types()->unsafeArray(type, size, parameter->isConst());
   821                 if (!type)
   822                     return false;
   823             }
   824         }
   825 
   826         if ((type->isPrimitive() && type->primitive() == PrimitiveType_Char) ||
   827             (type->isReference() && type->contained()->primitive() == PrimitiveType_Char))
   828         {
   829             cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
   830             return false;
   831         }
   832 
   833         args->set(zone_, i, type);
   834         parameter->variable()->setType(type);
   835     }
   836 
   837     Local<Type> returnType(zone_);
   838     if (node->returnTag()) {
   839         Local<String> tag(zone_, node->returnTag());
   840         returnType = zone_->types()->getPrimitiveForTag(tag);
   841     } else if (node->hasExplicitReturn() || node->fun()->isNative()) {
   842         returnType = zone_->types()->getPrimitive(PrimitiveType_Int32);
   843     } else {
   844         returnType = zone_->types()->getVoid();
   845     }
   846     if (!returnType)
   847         return false;
   848 
   849     Local<Type> funtype(zone_);
   850     if (node->fun()->isNative())
   851         funtype = zone_->types()->newNative(returnType, args, node->fun()->isNativeVariadic());
   852     else
   853         funtype = zone_->types()->newFunction(returnType, args);
   854     if (!funtype)
   855         return false;
   856     
   857     // If the function already has a type, it was forward declared before, and
   858     // now this is our chance to type check the second declaration.
   859     if (node->fun()->type()) {
   860         Local<Type> forward(zone_, node->fun()->type());
   861         if (!Type::Compare(funtype, forward)) {
   862             cc_.reportError(node->pos(), Message_ForwardDeclareMismatches);
   863             return false;
   864         }
   865         node->fun()->setForwardType(forward);
   866     }
   867 
   868     node->fun()->setType(funtype);
   869 
   870     return true;
   871 }
   872 
   873 void
   874 SemanticAnalysis::visit(FunctionStatement *node)
   875 {
   876     function_ = node->fun();
   877     scope_ = node->scope();
   878 
   879     ControlScope control(&control_);
   880     if (node->body()) {
   881         node->body()->accept(this);
   882 
   883         ControlStatus status = control.status();
   884         if (status.returns() == Returns_Sometimes) {
   885             cc_.reportError(node->pos(), Message_NotAllPathsReturnValue);
   886         } else if (status.returns() == Returns_Never) {
   887             if (!function_->type()->returnType()->isVoid())
   888                 cc_.reportError(node->pos(), Message_MissingReturnValue);
   889         }
   890     }
   891 
   892     scope_ = NULL;
   893     function_ = NULL;
   894 }
   895 
   896 bool
   897 SemanticAnalysis::typeCheckArrayAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
   898 {
   899     Local<Type> actual(zone_, argActual);
   900     Local<Type> given(zone_, argGiven);
   901 
   902     if (!given->isArray()) {
   903         cc_.reportError(node->pos(), Message_ExpectedArray);
   904         return false;
   905     }
   906     if (given->levels() != actual->levels()) {
   907         cc_.reportError(node->pos(), Message_ArrayDimensionsMismatch);
   908         return false;
   909     }
   910 
   911     unsigned level = 0;
   912     while (given->isArray()) {
   913         if (actual->elements() != -1) {
   914             if (forAssign) {
   915                 if (given->elements() == -1 || actual->elements() == -1) {
   916                     cc_.reportError(node->pos(), Message_ArraySizeNotKnown);
   917                     return false;
   918                 }
   919 
   920                 if (actual->isCharArray()) {
   921                     // String assignment can have a truncated |given|.
   922                     if (given->elements() > actual->elements()) {
   923                         cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
   924                         return false;
   925                     }
   926                 } else {
   927                     if (given->elements() != actual->elements()) {
   928                         cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
   929                         return false;
   930                     }
   931                 }
   932             } else {
   933                 if (actual->elements() != -1 && given->elements() != actual->elements()) {
   934                     cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
   935                     return false;
   936                 }
   937             }
   938         }
   939         given = given->contained();
   940         actual = actual->contained();
   941     }
   942 
   943     if (given->primitive() != actual->primitive()) {
   944         // :TODO: leaks an interior pointer.
   945         const char *givenTag = given->tag() ? given->tag()->chars() : "_";
   946         const char *actualTag = given->tag() ? given->tag()->chars() : "_";
   947         cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
   948         return false;
   949     }
   950 
   951     return true;
   952 }
   953 
   954 bool
   955 SemanticAnalysis::typeCheckAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
   956 {
   957     Local<Type> actual(zone_, argActual);
   958     Local<Type> given(zone_, argGiven);
   959 
   960     if (actual->isArray())
   961         return typeCheckArrayAssignment(node, given, actual, forAssign);
   962 
   963     if (given->isArray()) {
   964         cc_.reportError(node->pos(), Message_CannotAssignArrayToScalar);
   965         return false;
   966     }
   967 
   968     // The given type may not have been dereferenced.
   969     if (given->isReference())
   970         given = given->contained();
   971     if (actual->isReference())
   972         actual = actual->contained();
   973 
   974     if (!given->isPrimitive() || !actual->isPrimitive()) {
   975         cc_.reportError(node->pos(), Message_UnsupportedType);
   976         return false;
   977     }
   978     
   979     if (given->primitive() != actual->primitive()) {
   980         // :TODO: leaks an interior pointer
   981         const char *givenTag = given->tag() ? given->tag()->chars() : "_";
   982         const char *actualTag = actual->tag() ? actual->tag()->chars() : "_";
   983         cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
   984         return false;
   985     }
   986 
   987     return true;
   988 }
   989 
   990 bool
   991 SemanticAnalysis::typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual)
   992 {
   993     return typeCheckAssignment(node, given, actual, false);
   994 }
   995 
   996 void
   997 SemanticAnalysis::visit(CallExpression *node)
   998 {
   999     Local<Type> type(zone_, visitForLoad(node->callee()));
  1000     if (!type)
  1001         return;
  1002 
  1003     if (!type->isFunction()) {
  1004         cc_.reportError(node->pos(), Message_CalleeNotFunction);
  1005         return;
  1006     }
  1007     if (node->arguments()->length() != type->parameters()->length()) {
  1008         if (!type->isNative() ||
  1009             !type->isNativeVariadic() ||
  1010             node->arguments()->length() < type->parameters()->length())
  1011         {
  1012             cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
  1013             return;
  1014         }
  1015     }
  1016 
  1017     // Currently, only calls from a NameProxy are possible.
  1018     NamedFunction *fun = node->callee()->toNameProxy()->binding()->toNamedFunction();
  1019     if (fun->isForward()) {
  1020         cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
  1021         return;
  1022     }
  1023 
  1024     for (unsigned i = 0; i < node->arguments()->length(); i++) {
  1025         // Note: we don't compute references unless the callee needs a
  1026         // reference type.
  1027         Expression *expression = node->arguments()->at(i);
  1028         Local<Type> given(zone_, visitAndApplyType(expression));
  1029         if (!given)
  1030             return;
  1031 
  1032         // Since we skip a load, check for a call expression that returns void.
  1033         if (given->isVoid()) {
  1034             assert(expression->isCallExpression());
  1035             CallExpression *call = expression->toCallExpression();
  1036             cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
  1037             return;
  1038         }
  1039         
  1040         // If it's an IndexExpression, we special case the ability to compute
  1041         // a reference.
  1042         if (expression->isIndexExpression())
  1043             given = given->contained();
  1044 
  1045         bool mustComputeReference;
  1046         if (i >= type->parameters()->length()) {
  1047             // Special handling for natives. Arguments past the formal must
  1048             // always have references computed. However, arrays are already
  1049             // references for natives.  
  1050             assert(type->isNative() && type->isNativeVariadic());
  1051             mustComputeReference = !given->isReference() && !given->isArray();
  1052         } else {
  1053             Local<Type> actual(zone_, type->parameterAt(i));
  1054             if (!typeCheckParameter(expression, given, actual))
  1055                 return;
  1056             mustComputeReference = actual->isReference() && !given->isReference();
  1057         }
  1058 
  1059         // If the actual is a reference, and the given is not, we'll need to
  1060         // compute a reference, which may be allocated on the stack.
  1061         if (mustComputeReference)
  1062             scope_->setUsesLifoHeap();
  1063     }
  1064 
  1065     node->setType(fun->type()->returnType());
  1066 }
  1067 
  1068 void
  1069 SemanticAnalysis::ControlScope::merge(const ControlStatus &left, const ControlStatus &right)
  1070 {
  1071     // If both sides terminate in a return, we consider this a return as well.
  1072     if (left.returns() == Returns_Always && right.returns() == Returns_Always) {
  1073         terminate(Returns_Always);
  1074         return;
  1075     }
  1076 
  1077     ReturnStatus status = (left.returns() == Returns_Never && right.returns() == Returns_Never)
  1078                           ? Returns_Never
  1079                           : Returns_Sometimes;
  1080 
  1081     if (left.terminates() && right.terminates())
  1082         terminate(status);
  1083     else
  1084         returns(status);
  1085 }
  1086 
  1087 void
  1088 SemanticAnalysis::visit(IfStatement *node)
  1089 {
  1090     Local<Type> type(zone_, visitForLoad(node->condition()));
  1091     if (!type)
  1092         return;
  1093 
  1094     if (!canTest(node, type))
  1095         return;
  1096 
  1097     ControlStatus trueBranch = visitForControl(node->ifTrue());
  1098     ControlStatus falseBranch = ControlStatus(false, Returns_Never);
  1099 
  1100     if (node->ifFalse())
  1101         falseBranch = visitForControl(node->ifFalse());
  1102 
  1103     control_->merge(trueBranch, falseBranch);
  1104 }
  1105 
  1106 void
  1107 SemanticAnalysis::visit(IndexExpression *node)
  1108 {
  1109     Local<Type> left(zone_, visitForLoad(node->left()));
  1110     Local<Type> right(zone_, visitForLoad(node->right()));
  1111 
  1112     if (!left || !right)
  1113         return;
  1114 
  1115     if (!right->isInt32()) {
  1116         cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
  1117         return;
  1118     }
  1119     if (!left->isArray()) {
  1120         cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
  1121         return;
  1122     }
  1123     node->setType(left);
  1124 }
  1125 
  1126 void
  1127 SemanticAnalysis::visit(EnumStatement *node)
  1128 {
  1129     // Forbid the blessed types.
  1130     Local<String> tag(zone_, node->name());
  1131     if (!strcmp(tag->chars(), "Float") ||
  1132         !strcmp(tag->chars(), "String") ||
  1133         !strcmp(tag->chars(), "any") ||
  1134         !strcmp(tag->chars(), "bool"))
  1135     {
  1136         cc_.reportError(node->pos(), Message_InvalidEnumName);
  1137         return;
  1138     }
  1139 
  1140     Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
  1141     if (!type)
  1142         return;
  1143 
  1144     int value = 0;
  1145     for (size_t i = 0; i < node->entries()->length(); i++) {
  1146         EnumStatement::Entry &entry = node->entries()->at(i);
  1147 
  1148         BoxedPrimitive box = BoxedPrimitive::Int(value);
  1149         if (entry.expr) {
  1150             entry.expr->accept(this);
  1151             if (!EvaluateForConstant(entry.expr, &box)) {
  1152                 cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
  1153                 return;
  1154             }
  1155 
  1156             assert(box.type() == PrimitiveType_Int32);
  1157             value = box.toInt();
  1158         }
  1159 
  1160         entry.name->set(type, box);
  1161         value++;
  1162     }
  1163 }
  1164 
  1165 void
  1166 SemanticAnalysis::visit(StringLiteral *node)
  1167 {
  1168     Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Char));
  1169     if (!type)
  1170         return;
  1171 
  1172     type = Type::NewArray(zone_, type, node->string()->length() + 1, true);
  1173     if (!type)
  1174         return;
  1175 
  1176     node->setType(type);
  1177 }
  1178 
  1179 void
  1180 SemanticAnalysis::visit(FloatLiteral *node)
  1181 {
  1182     Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
  1183     if (!type)
  1184         return;
  1185 
  1186     node->setType(type);
  1187 }
  1188 
  1189 void
  1190 SemanticAnalysis::visit(BreakStatement *node)
  1191 {
  1192     if (!loop_) {
  1193         cc_.reportError(node->pos(), Message_BreakOutsideLoop);
  1194         return;
  1195     }
  1196 
  1197     // Note: ignore breaks that occur in unreachable control-flow.
  1198     if (!control_->status().terminates())
  1199         loop_->addBreak();
  1200 
  1201     control_->terminate(Returns_Never);
  1202 }
  1203 
  1204 void
  1205 SemanticAnalysis::visit(ContinueStatement *node)
  1206 {
  1207     if (!loop_) {
  1208         cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
  1209         return;
  1210     }
  1211 
  1212     // Note: ignore continues that occur in unreachable control-flow.
  1213     if (!control_->status().terminates())
  1214         loop_->addContinue();
  1215 
  1216     control_->terminate(Returns_Never);
  1217 }