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