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