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