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