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