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