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