src/SemanticAnalysis.cpp
author David Anderson <dvander@alliedmods.net>
Sat Aug 04 19:33:06 2012 -0700 (2012-08-04)
changeset 147 9c544823d090
parent 146 dc7d3b7a918c
child 148 c0740249963c
permissions -rw-r--r--
Structure declaration support.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of JITCraft.
     6  *
     7  * JITCraft is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * JITCraft. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #include <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->isIndexExpression()) {
   268         if (type->isArray())
   269             expression->setType(type->contained());
   270     } else if (expression->isCallExpression()) {
   271         if (type->isVoid()) {
   272             CallExpression *call = expression->toCallExpression();
   273             cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
   274             return NULL;
   275         }
   276     }
   277 
   278     return expression->type();
   279 }
   280 
   281 // :TODO: this leaks an interior pointer.
   282 const char *
   283 ke::GetTypeName(Type *type)
   284 {
   285     if (type->isArray())
   286         return "array";
   287     if (type->isFunction())
   288         return "function";
   289     if (type->isVoid())
   290         return "void";
   291     if (type->isEnum() || type->isStruct())
   292         return type->name()->chars();
   293     if (type->isReference())
   294         type = type->contained();
   295     switch (type->primitive()) {
   296       case PrimitiveType_Bool:
   297         return "bool";
   298       case PrimitiveType_Char:
   299         return "String";
   300       case PrimitiveType_Int32:
   301         return "int";
   302       case PrimitiveType_Float:
   303         return "float";
   304       default:
   305         return "<unknown>";
   306     }
   307 }
   308 
   309 void
   310 SemanticAnalysis::unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type)
   311 {
   312     const char *op = TokenNames[token];
   313     const char *name = GetTypeName(type);
   314 
   315     cc_.reportError(node->pos(), Message_UnaryTypeError, op, name);
   316 }
   317 
   318 void
   319 SemanticAnalysis::binaryTypeError(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
   320 {
   321     const char *op = TokenNames[token];
   322     const char *leftName = GetTypeName(left);
   323     const char *rightName = GetTypeName(right);
   324 
   325     cc_.reportError(node->pos(), Message_BinaryTypeError, op, leftName, rightName);
   326 }
   327 
   328 Type *
   329 SemanticAnalysis::typeCheckBinary(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
   330 {
   331     if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
   332         (token >= TOK_ASSIGN_ADD && token <= TOK_ASSIGN_DIV))
   333     {
   334         // If either side is a float, the other side must be a float or int.
   335         if (left->isFloat() || right->isFloat()) {
   336             Type *floatType = left->isFloat() ? left : right;
   337             Type *other = left->isFloat() ? right : left;
   338             if (other->isFloat() || other->isInt32())
   339                 return floatType;
   340         }
   341     }
   342 
   343     if (token == TOK_OR || token == TOK_AND) {
   344         if (!canTest(node, left) || !canTest(node, right))
   345             return NULL;
   346         return zone_->types()->getPrimitive(PrimitiveType_Bool);
   347     }
   348 
   349     if (token >= TOK_EQUALS && token <= TOK_GE) {
   350         if ((left->isFloat() || left->isInt32()) &&
   351             (right->isFloat() || right->isInt32()))
   352         {
   353             return zone_->types()->getPrimitive(PrimitiveType_Bool);
   354         }
   355         binaryTypeError(node, token, left, right);
   356         return NULL;
   357     }
   358 
   359     if (!left->isInt32() || !right->isInt32()) {
   360         binaryTypeError(node, token, left, right);
   361         return NULL;
   362     }
   363 
   364     return left;
   365 }
   366 
   367 bool
   368 SemanticAnalysis::canTest(AstNode *node, Handle<Type> type)
   369 {
   370     if (!type->isPrimitive() && !type->isEnum()) {
   371         cc_.reportError(node->pos(), Message_ArrayIsNotBoolean);
   372         return false;
   373     }
   374     return true;
   375 }
   376 
   377 Type *
   378 SemanticAnalysis::visitForLValue(Expression *expression)
   379 {
   380     if (expression->isIndexExpression()) {
   381         Type *type = visitAndApplyType(expression);
   382         if (!type)
   383             return NULL;
   384 
   385         if (type->isConst()) {
   386             cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
   387             return NULL;
   388         }
   389 
   390         return type->contained();
   391     }
   392 
   393     if (!expression->isNameProxy()) {
   394         cc_.reportError(expression->pos(), Message_ExpectedLValue);
   395         return NULL;
   396     }
   397 
   398     NameProxy *proxy = expression->toNameProxy();
   399     if (!proxy->binding()->kind() == BoundName::VARIABLE) {
   400         cc_.reportError(expression->pos(), Message_ExpectedLValue);
   401         return NULL;
   402     }
   403 
   404     Variable *var = proxy->binding()->toVariable();
   405     if (!var->type())
   406         return NULL;
   407 
   408     if  (var->type()->isReference()) {
   409         if (var->type()->isConst()) {
   410             cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
   411             return NULL;
   412         }
   413         return var->type()->contained();
   414     }
   415     return var->type();
   416 }
   417 
   418 SemanticAnalysis::ControlStatus
   419 SemanticAnalysis::visitForControl(Statement *statement)
   420 {
   421     ControlScope scope(&control_);
   422     statement->accept(this);
   423     return scope.status();
   424 }
   425 
   426 void
   427 SemanticAnalysis::visit(NameProxy *name)
   428 {
   429     BoundName *binding = name->binding();
   430 
   431     if (binding->scope()->kind() == Scope::GLOBAL) {
   432         if (!function_ || function_->isPublic()) {
   433             // Whatever we're referencing must be kept alive no matter what.
   434             // As such, we simply mark it used, and don't do anything special.
   435             binding->setUsed();
   436         } else if (!binding->used() && binding->kind() == BoundName::FUNCTION) {
   437             // Otherwise, we're inside a normal stock or function. Since we
   438             // don't really know if we've been used yet, we shouldn't
   439             // prematurely references as alive. Instead, we keep a list of
   440             // which names have been used, so we can mark them later if needed.
   441             //
   442             // Note that we skip this step if the binding is already in the
   443             // root set.
   444             if (!function_->addUsedGlobal(binding))
   445                 return;
   446         }
   447     }
   448 
   449     name->setType(binding->type());
   450 }
   451 
   452 void
   453 SemanticAnalysis::visit(Assignment *node)
   454 {
   455     Local<Type> exprType(zone_, visitForLoad(node->expression()));
   456     if (!exprType)
   457         return ;
   458 
   459     Local<Type> type(zone_, visitForLValue(node->lvalue()));
   460     if (!type)
   461         return;
   462 
   463     if (node->token() != TOK_ASSIGN) {
   464         if (!typeCheckBinary(node, node->token(), type, exprType))
   465             return;
   466     }
   467 
   468     if (!typeCheckAssignment(node, exprType, type, true))
   469         return;
   470 
   471     node->setType(type);
   472 }
   473 
   474 void
   475 SemanticAnalysis::visit(IncDecExpression *node)
   476 {
   477     Local<Type> type(zone_, visitForLValue(node->expression()));
   478     if (!type)
   479         return;
   480 
   481     assert(!type->isReference());
   482 
   483     if (!type->isInt32() && !type->isFloat()) {
   484         unaryTypeError(node, node->token(), type);
   485         return;
   486     }
   487 
   488     node->setType(type);
   489 }
   490 
   491 void
   492 SemanticAnalysis::visit(UnaryExpression *node)
   493 {
   494     Local<Type> type(zone_, visitForLoad(node->expression()));
   495     if (!type)
   496         return;
   497 
   498     switch (node->token())
   499     {
   500       case TOK_NOT:
   501         if (!canTest(node->expression(), type))
   502             return;
   503         type = zone_->types()->getPrimitive(PrimitiveType_Int32);
   504         if (!type)
   505             return;
   506         node->setType(type);
   507         break;
   508 
   509       case TOK_MINUS:
   510         if (!type->isFloat() && !type->isInt32()) {
   511             unaryTypeError(node, node->token(), type);
   512             return;
   513         }
   514         node->setType(type);
   515         break;
   516 
   517       case TOK_LABEL:
   518       {
   519         Local<Type> to(zone_, bindType(node->pos(), node->type()));
   520         if (!to)
   521             return;
   522 
   523         if ((!type->isFloat() && !type->isInt32OrEnum()) ||
   524             (!to->isFloat() && !to->isInt32OrEnum()))
   525         {
   526             unaryTypeError(node, node->token(), type);
   527             return;
   528         }
   529 
   530         node->setType(to);
   531         break;
   532       }
   533 
   534       default:
   535         assert(node->token() == TOK_TILDE);
   536         if (!type->isInt32()) {
   537             unaryTypeError(node, node->token(), type);
   538             return;
   539         }
   540         node->setType(type);
   541         break;
   542     }
   543 }
   544 
   545 void
   546 SemanticAnalysis::visit(TernaryExpression *node)
   547 {
   548     Local<Type> type(zone_, visitForLoad(node->condition()));
   549     if (!type)
   550         return;
   551 
   552     if (!canTest(node->condition(), type))
   553         return;
   554 
   555     Local<Type> left(zone_, visitForLoad(node->left()));
   556     Local<Type> right(zone_, visitForLoad(node->right()));
   557     if (!left || !right)
   558         return;
   559 
   560     if (left != right) {
   561         binaryTypeError(node, TOK_QMARK, left, right);
   562         return;
   563     }
   564 }
   565 
   566 void
   567 SemanticAnalysis::visit(BinaryExpression *node)
   568 {
   569     Local<Type> left(zone_, visitForLoad(node->left()));
   570     Local<Type> right(zone_, visitForLoad(node->right()));
   571     if (!left || !right)
   572         return;
   573 
   574     Local<Type> result(zone_, typeCheckBinary(node, node->token(), left, right));
   575     if (!result)
   576         return;
   577 
   578     node->setType(result);
   579 }
   580 
   581 void
   582 SemanticAnalysis::visit(ReturnStatement *node)
   583 {
   584     // Set this early, so if we error we don't get more errors.
   585     control_->returns(Returns_Always);
   586 
   587     if (!node->expression()) {
   588         if (!function_->type()->returnType()->isVoid())
   589             cc_.reportError(node->pos(), Message_NotAllPathsReturnValue);
   590         return;
   591     }
   592 
   593     Local<Type> type(zone_, visitForLoad(node->expression()));
   594     if (!type)
   595         return;
   596 
   597     Local<Type> returnType(zone_, function_->type()->returnType());
   598     if (!typeCheckAssignment(node, type, returnType, true))
   599         return;
   600 }
   601 
   602 void
   603 SemanticAnalysis::visit(ForStatement *node)
   604 {
   605     LoopScope loop(&loop_);
   606 
   607     if (node->scope())
   608         scope_ = node->scope();
   609 
   610     if (node->initialization())
   611         node->initialization()->accept(this);
   612 
   613     if (node->condition()) {
   614         Local<Type> type(zone_, visitForLoad(node->condition()));
   615         if (!type || !canTest(node->condition(), type)) {
   616             return;
   617         }
   618     }
   619 
   620     if (node->update())
   621         node->update()->accept(this);
   622 
   623     ControlStatus status = visitForControl(node->body());
   624 
   625     // If there is a condition, we treat this like a while loop. Otherwise,
   626     // join point is only reachable if the loop contains a break. The
   627     // termination status doesn't tell us anything yet.
   628     if (node->condition() || loop.breaks())
   629         control_->merge(status, ControlStatus(false, Returns_Never));
   630     else
   631         control_->terminate(status.returns());
   632 
   633     if (node->scope())
   634         scope_ = scope_->enclosing();
   635 }
   636 
   637 void 
   638 SemanticAnalysis::visit(WhileStatement *node)
   639 {
   640     LoopScope loop(&loop_);
   641 
   642     Local<Type> type(zone_, visitForLoad(node->condition()));
   643     if (!type || !canTest(node->condition(), type)) {
   644         return;
   645     }
   646 
   647     ControlStatus status = visitForControl(node->body());
   648 
   649     // Detect loops that will always have a fork in the control-flow graph.
   650     // This will be a |while| loop, or a |do-while| loop whose body does
   651     // not terminate.
   652     //
   653     // For now, we treat these as an |if| regardless of the direction the
   654     // branch can take. That means the control-flow is always conditional.
   655     if (node->token() == TOK_WHILE ||
   656         !status.terminates() ||
   657         loop.breaks())
   658     {
   659         control_->merge(status, ControlStatus(false, Returns_Never));
   660     } else {
   661         // At this point, we've got a do-while loop with a |return| or
   662         // |continue|, meaning that the rest of the block is unreachable.
   663         control_->terminate(status.returns());
   664     }
   665 }
   666 
   667 void
   668 SemanticAnalysis::visit(BlockStatement *node)
   669 {
   670     if (node->scope())
   671         scope_ = node->scope();
   672     for (size_t i = 0; i < node->statements()->length(); i++) {
   673         Statement *statement = node->statements()->at(i);
   674         statement->accept(this);
   675     }
   676     if (node->scope())
   677         scope_ = scope_->enclosing();
   678 }
   679 
   680 static inline bool
   681 IsScalarString(Type *type)
   682 {
   683     if (type->isPrimitive() && type->primitive() == PrimitiveType_Char)
   684         return true;
   685     if (type->isReference())
   686         return IsScalarString(type->contained());
   687     return false;
   688 }
   689 
   690 void
   691 SemanticAnalysis::visit(VariableDeclaration *node)
   692 {
   693     Local<Type> type(zone_, bindType(node->pos(), node->type()));
   694     if (!type)
   695         return;
   696 
   697     if (node->postDimensions()) {
   698         Local<Type> init(zone_);
   699         if (node->initialization()) {
   700             if ((init = visitForLoad(node->initialization())) == NULL)
   701                 return;
   702         }
   703 
   704         if (node->postDimensions()->length() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
   705             cc_.reportError(node->pos(), Message_MaximumArrayDepth);
   706             return;
   707         }
   708 
   709         // If we have an initializer, make sure it's the same type.
   710         if (init && node->postDimensions()->length() != init->levels()) {
   711             cc_.reportError(node->pos(), Message_ArrayInitializerDepth);
   712             return;
   713         }
   714 
   715         Local<Type> check(zone_, init);
   716         for (size_t i = node->postDimensions()->length() - 1; i < node->postDimensions()->length(); i--) {
   717             Expression *expr = node->postDimensions()->at(i);
   718             int size = -1;
   719 
   720             if (expr) {
   721                 Local<Type> exprType(zone_, visitForLoad(expr));
   722                 if (!exprType)
   723                     return;
   724 
   725                 if (!IsPrimitiveType(exprType, PrimitiveType_Int32)) {
   726                     cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
   727                     return;
   728                 }
   729 
   730                 BoxedPrimitive box;
   731                 if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
   732                     size = box.toInt();
   733                     if (size <= 0) {
   734                         cc_.reportError(expr->pos(), Message_BadArraySize);
   735                         return;
   736                     }
   737                     if (size >= int(INT_MAX / sizeof(int))) {
   738                         cc_.reportError(expr->pos(), Message_ArraySizeTooBig);
   739                         return;
   740                     }
   741 
   742                     if (check) {
   743                         if (check->elements() == -1) {
   744                             cc_.reportError(expr->pos(), Message_ArraySizeCannotBeDetermined);
   745                             return;
   746                         }
   747 
   748                         if (check->isCharArray()) {
   749                             if (check->elements() > size) {
   750                                 cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
   751                                 return;
   752                             }
   753                         } else if (check->elements() != size) {
   754                             cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, unsigned(i));
   755                             return;
   756                         }
   757                     }
   758                 } else {
   759                     if (init) {
   760                         cc_.reportError(node->pos(), Message_DynamicArrayHasInitializer);
   761                         return;
   762                     }
   763 
   764                     // here until we get dynamic array support.
   765                     cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
   766                     return;
   767                 }
   768             } else {
   769                 // Infer the size from the initializer.
   770                 if (!init) {
   771                     cc_.reportError(node->pos(), Message_ArraySizeNotSpecified);
   772                     return;
   773                 }
   774                 if (init->elements() == -1) {
   775                     cc_.reportError(node->pos(), Message_ArraySizeCannotBeDetermined);
   776                     return;
   777                 }
   778                 size = init->elements();
   779             }
   780 
   781             type = zone_->types()->unsafeArray(type, size, false);
   782             if (!type)
   783                 return;
   784 
   785             if (check)
   786                 check = check->contained();
   787         }
   788     } else {
   789         if (node->initialization()) {
   790             Local<Type> right(zone_, visitForLoad(node->initialization()));
   791             if (!right)
   792                 return;
   793             if (!typeCheckAssignment(node, type, right, true))
   794                 return;
   795         }
   796 
   797         if (type->isPrimitive() && type->primitive() == PrimitiveType_Char) {
   798             cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
   799             return;
   800         }
   801     }
   802 
   803     // If this variable is stack allocated, we could use the LIFO heap
   804     // to allocate it. If that's the case, make sure to reserve a slot
   805     // so we can unwind the LIFO heap at the end of this scope.
   806     if (!node->variable()->needsHeapAllocation()) {
   807         if (type->isArray() || type->isStruct())
   808             scope_->setUsesLifoHeap();
   809     }
   810 
   811     node->variable()->setType(type);
   812 }
   813 
   814 void
   815 SemanticAnalysis::visit(IntegerLiteral *node)
   816 {
   817     node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
   818 }
   819 
   820 void
   821 SemanticAnalysis::visit(BooleanLiteral *node)
   822 {
   823     node->setType(zone_->types()->getPrimitive(PrimitiveType_Bool));
   824 }
   825 
   826 void
   827 SemanticAnalysis::visit(ExpressionStatement *node)
   828 {
   829     visitAndApplyType(node->expression());
   830 }
   831 
   832 bool
   833 SemanticAnalysis::preanalyze(FunctionStatement *node)
   834 {
   835     Local<FixedArray> args(zone_, FixedArray::New(zone_, node->parameters()->length(), Heap::Tenure_Old));
   836     if (!args)
   837         return false;
   838 
   839     // Apply types to arguments.
   840     for (size_t i = 0; i < node->parameters()->length(); i++) {
   841         Parameter *parameter = node->parameters()->at(i);
   842         
   843         Local<Type> type(zone_, bindType(parameter->variable()->pos(), parameter->type()));
   844         if (!type)
   845             return false;
   846 
   847         if (parameter->reference()) {
   848             if (parameter->dimensions()) {
   849                 cc_.reportError(parameter->variable()->pos(), Message_ArrayCantBeReference);
   850                 return NULL;
   851             }
   852 
   853             type = zone_->types()->getReference(type, parameter->isConst());
   854             if (!type)
   855                 return false;
   856         } else if (parameter->dimensions()) {
   857             if (parameter->dimensions()->length() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
   858                 cc_.reportError(parameter->variable()->pos(), Message_MaximumArrayDepth);
   859                 return false;
   860             }
   861 
   862             if (node->fun()->isNative() && parameter->dimensions()->length() > 1) {
   863                 cc_.reportError(parameter->variable()->pos(), Message_MultiArrayInNative);
   864                 return false;
   865             }
   866 
   867             for (size_t i = parameter->dimensions()->length() - 1;
   868                  i < parameter->dimensions()->length();
   869                  i++)
   870             {
   871                 int size = Type::UNKNOWN_SIZE;
   872                 if (Expression *expr = parameter->dimensions()->at(i)) {
   873                     BoxedPrimitive box;
   874                     if (!EvaluateForConstant(expr, &box)) {
   875                         cc_.reportError(expr->pos(), Message_ArraySizeMustBeConstant);
   876                         return false;
   877                     }
   878                     size = box.toInt();
   879                 }
   880 
   881                 type = zone_->types()->unsafeArray(type, size, parameter->isConst());
   882                 if (!type)
   883                     return false;
   884             }
   885         }
   886 
   887         if (IsScalarString(type)) {
   888             cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
   889             return false;
   890         }
   891 
   892         args->set(zone_, i, type);
   893         parameter->variable()->setType(type);
   894     }
   895 
   896     Local<Type> returnType(zone_);
   897     if (node->returnType() ||
   898         node->hasExplicitReturn() ||
   899         node->fun()->isNative())
   900     {
   901         returnType = bindType(node->pos(), node->returnType());
   902     } else {
   903         returnType = zone_->types()->getVoid();
   904     }
   905     if (!returnType)
   906         return false;
   907 
   908     Local<Type> funtype(zone_);
   909     if (node->fun()->isNative())
   910         funtype = zone_->types()->newNative(returnType, args, node->fun()->isNativeVariadic());
   911     else
   912         funtype = zone_->types()->newFunction(returnType, args);
   913     if (!funtype)
   914         return false;
   915     
   916     // If the function already has a type, it was forward declared before, and
   917     // now this is our chance to type check the second declaration.
   918     if (node->fun()->type()) {
   919         Local<Type> forward(zone_, node->fun()->type());
   920         if (!Type::Compare(funtype, forward)) {
   921             cc_.reportError(node->pos(), Message_ForwardDeclareMismatches);
   922             return false;
   923         }
   924         node->fun()->setForwardType(forward);
   925     }
   926 
   927     node->fun()->setType(funtype);
   928 
   929     return true;
   930 }
   931 
   932 void
   933 SemanticAnalysis::visit(FunctionStatement *node)
   934 {
   935     function_ = node->fun();
   936     scope_ = node->scope();
   937 
   938     ControlScope control(&control_);
   939     if (node->body()) {
   940         node->body()->accept(this);
   941 
   942         ControlStatus status = control.status();
   943         if (status.returns() == Returns_Sometimes) {
   944             cc_.reportError(node->pos(), Message_NotAllPathsReturnValue);
   945         } else if (status.returns() == Returns_Never) {
   946             if (!function_->type()->returnType()->isVoid())
   947                 cc_.reportError(node->pos(), Message_MissingReturnValue);
   948         }
   949     }
   950 
   951     scope_ = NULL;
   952     function_ = NULL;
   953 }
   954 
   955 void
   956 SemanticAnalysis::typeMismatch(AstNode *node, Handle<Type> actual, Handle<Type> given)
   957 {
   958     cc_.reportError(node->pos(),Message_TypeMismatch,
   959                     GetTypeName(actual),
   960                     GetTypeName(given));
   961 }
   962 
   963 bool
   964 SemanticAnalysis::typeCheckArrayAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
   965 {
   966     Local<Type> actual(zone_, argActual);
   967     Local<Type> given(zone_, argGiven);
   968 
   969     if (!given->isArray()) {
   970         cc_.reportError(node->pos(), Message_ExpectedArray);
   971         return false;
   972     }
   973     if (given->levels() != actual->levels()) {
   974         cc_.reportError(node->pos(), Message_ArrayDimensionsMismatch);
   975         return false;
   976     }
   977 
   978     unsigned level = 0;
   979     while (given->isArray()) {
   980         if (actual->elements() != -1) {
   981             if (forAssign) {
   982                 if (given->elements() == -1 || actual->elements() == -1) {
   983                     cc_.reportError(node->pos(), Message_ArraySizeNotKnown);
   984                     return false;
   985                 }
   986 
   987                 if (actual->isCharArray()) {
   988                     // String assignment can have a truncated |given|.
   989                     if (given->elements() > actual->elements()) {
   990                         cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
   991                         return false;
   992                     }
   993                 } else {
   994                     if (given->elements() != actual->elements()) {
   995                         cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
   996                         return false;
   997                     }
   998                 }
   999             } else {
  1000                 if (actual->elements() != -1 && given->elements() != actual->elements()) {
  1001                     cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
  1002                     return false;
  1003                 }
  1004             }
  1005         }
  1006         given = given->contained();
  1007         actual = actual->contained();
  1008     }
  1009 
  1010     return typeCheckAssignment(node, given, actual, forAssign);
  1011 }
  1012 
  1013 bool
  1014 SemanticAnalysis::typeCheckAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
  1015 {
  1016     Local<Type> actual(zone_, argActual);
  1017     Local<Type> given(zone_, argGiven);
  1018 
  1019     if (actual->isArray())
  1020         return typeCheckArrayAssignment(node, given, actual, forAssign);
  1021 
  1022     if (given->isArray()) {
  1023         cc_.reportError(node->pos(), Message_CannotAssignArrayToScalar);
  1024         return false;
  1025     }
  1026 
  1027     // The given type may not have been dereferenced.
  1028     if (given->isReference())
  1029         given = given->contained();
  1030     if (actual->isReference())
  1031         actual = actual->contained();
  1032 
  1033     if (actual->isEnum()) {
  1034         if (!given->isEnum() || actual != given) {
  1035             typeMismatch(node, actual, given);
  1036             return false;
  1037         }
  1038         return true;
  1039     }
  1040 
  1041     if (given->isEnum() || given->isFunction()) {
  1042         typeMismatch(node, actual, given);
  1043         return false;
  1044     }
  1045 
  1046     if (given->primitive() != actual->primitive()) {
  1047         typeMismatch(node, actual, given);
  1048         return false;
  1049     }
  1050 
  1051     return true;
  1052 }
  1053 
  1054 bool
  1055 SemanticAnalysis::typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual)
  1056 {
  1057     return typeCheckAssignment(node, given, actual, false);
  1058 }
  1059 
  1060 void
  1061 SemanticAnalysis::visit(CallExpression *node)
  1062 {
  1063     Local<Type> type(zone_, visitForLoad(node->callee()));
  1064     if (!type)
  1065         return;
  1066 
  1067     if (!type->isFunction()) {
  1068         cc_.reportError(node->pos(), Message_CalleeNotFunction);
  1069         return;
  1070     }
  1071     if (node->arguments()->length() != type->parameters()->length()) {
  1072         if (!type->isNative() ||
  1073             !type->isNativeVariadic() ||
  1074             node->arguments()->length() < type->parameters()->length())
  1075         {
  1076             cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
  1077             return;
  1078         }
  1079     }
  1080 
  1081     // Currently, only calls from a NameProxy are possible.
  1082     NamedFunction *fun = node->callee()->toNameProxy()->binding()->toNamedFunction();
  1083     if (fun->isForward()) {
  1084         cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
  1085         return;
  1086     }
  1087 
  1088     for (unsigned i = 0; i < node->arguments()->length(); i++) {
  1089         // Note: we don't compute references unless the callee needs a
  1090         // reference type.
  1091         Expression *expression = node->arguments()->at(i);
  1092         Local<Type> given(zone_, visitAndApplyType(expression));
  1093         if (!given)
  1094             return;
  1095 
  1096         // Since we skip a load, check for a call expression that returns void.
  1097         if (given->isVoid()) {
  1098             assert(expression->isCallExpression());
  1099             CallExpression *call = expression->toCallExpression();
  1100             cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
  1101             return;
  1102         }
  1103         
  1104         // If it's an IndexExpression, we special case the ability to compute
  1105         // a reference.
  1106         if (expression->isIndexExpression())
  1107             given = given->contained();
  1108 
  1109         bool mustComputeReference;
  1110         if (i >= type->parameters()->length()) {
  1111             // Special handling for natives. Arguments past the formal must
  1112             // always have references computed. However, arrays are already
  1113             // references for natives.  
  1114             assert(type->isNative() && type->isNativeVariadic());
  1115             mustComputeReference = !given->isReference() && !given->isArray();
  1116         } else {
  1117             Local<Type> actual(zone_, type->parameterAt(i));
  1118             if (!typeCheckParameter(expression, given, actual))
  1119                 return;
  1120             mustComputeReference = actual->isReference() && !given->isReference();
  1121         }
  1122 
  1123         // If the actual is a reference, and the given is not, we'll need to
  1124         // compute a reference, which may be allocated on the stack.
  1125         if (mustComputeReference)
  1126             scope_->setUsesLifoHeap();
  1127     }
  1128 
  1129     node->setType(fun->type()->returnType());
  1130 }
  1131 
  1132 void
  1133 SemanticAnalysis::ControlScope::merge(const ControlStatus &left, const ControlStatus &right)
  1134 {
  1135     // If both sides terminate in a return, we consider this a return as well.
  1136     if (left.returns() == Returns_Always && right.returns() == Returns_Always) {
  1137         terminate(Returns_Always);
  1138         return;
  1139     }
  1140 
  1141     ReturnStatus status = (left.returns() == Returns_Never && right.returns() == Returns_Never)
  1142                           ? Returns_Never
  1143                           : Returns_Sometimes;
  1144 
  1145     if (left.terminates() && right.terminates())
  1146         terminate(status);
  1147     else
  1148         returns(status);
  1149 }
  1150 
  1151 void
  1152 SemanticAnalysis::visit(IfStatement *node)
  1153 {
  1154     Local<Type> type(zone_, visitForLoad(node->condition()));
  1155     if (!type)
  1156         return;
  1157 
  1158     if (!canTest(node, type))
  1159         return;
  1160 
  1161     ControlStatus trueBranch = visitForControl(node->ifTrue());
  1162     ControlStatus falseBranch = ControlStatus(false, Returns_Never);
  1163 
  1164     if (node->ifFalse())
  1165         falseBranch = visitForControl(node->ifFalse());
  1166 
  1167     control_->merge(trueBranch, falseBranch);
  1168 }
  1169 
  1170 void
  1171 SemanticAnalysis::visit(IndexExpression *node)
  1172 {
  1173     Local<Type> left(zone_, visitForLoad(node->left()));
  1174     Local<Type> right(zone_, visitForLoad(node->right()));
  1175 
  1176     if (!left || !right)
  1177         return;
  1178 
  1179     if (!right->isInt32() && !right->isEnum()) {
  1180         cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
  1181         return;
  1182     }
  1183     if (!left->isArray()) {
  1184         cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
  1185         return;
  1186     }
  1187     node->setType(left);
  1188 }
  1189 
  1190 void
  1191 SemanticAnalysis::visit(EnumStatement *node)
  1192 {
  1193     Local<Type> type(zone_, node->decl()->type());
  1194 
  1195     assert(type);
  1196 
  1197     int value = 0;
  1198     for (size_t i = 0; i < node->entries()->length(); i++) {
  1199         EnumStatement::Entry &entry = node->entries()->at(i);
  1200 
  1201         BoxedPrimitive box = BoxedPrimitive::Int(value);
  1202         if (entry.expr) {
  1203             entry.expr->accept(this);
  1204             if (!EvaluateForConstant(entry.expr, &box)) {
  1205                 cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
  1206                 return;
  1207             }
  1208 
  1209             assert(box.type() == PrimitiveType_Int32);
  1210             value = box.toInt();
  1211         }
  1212 
  1213         entry.name->set(type, box);
  1214         value++;
  1215     }
  1216 }
  1217 
  1218 void
  1219 SemanticAnalysis::visit(StructureStatement *node)
  1220 {
  1221     // If this node already has a type, it was pre-analyzed, so skip it.
  1222     if (node->decl()->type())
  1223         return;
  1224 
  1225     FieldList *fields = node->fields();
  1226     Local<FixedArray> desctable(zone_, FixedArray::New(zone_, fields->length(), Heap::Tenure_Old));
  1227     if (!desctable)
  1228         return;
  1229 
  1230     StructureBufferBuilder builder;
  1231 
  1232     Local<Type> type(zone_);
  1233     Local<String> name(zone_);
  1234     Local<Descriptor> desc(zone_);
  1235     for (size_t i = 0; i < fields->length(); i++) {
  1236         StructureStatement::Field *field = fields->at(i);
  1237 
  1238         type = bindType(field->pos(), field->type());
  1239         if (!type)
  1240             return;
  1241 
  1242         unsigned offset;
  1243         if (!builder.add(type, &offset))
  1244             return;
  1245 
  1246         name = field->name();
  1247         desc = Descriptor::New(zone_, name, type, offset);
  1248         if (!desc)
  1249             return;
  1250 
  1251         desctable->set(zone_, i, desc);
  1252     }
  1253 
  1254     Local<StructMap> map(zone_, StructMap::New(zone_, builder));
  1255     if (!map)
  1256         return;
  1257 
  1258     name = node->decl()->name();
  1259     type = zone_->types()->newStruct(name, desctable, map);
  1260     if (!type)
  1261         return;
  1262 
  1263     map->setType(type);
  1264     node->decl()->setType(type);
  1265 }
  1266 
  1267 void
  1268 SemanticAnalysis::visit(StringLiteral *node)
  1269 {
  1270     Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Char));
  1271     if (!type)
  1272         return;
  1273 
  1274     type = Type::NewArray(zone_, type, node->string()->length() + 1, true);
  1275     if (!type)
  1276         return;
  1277 
  1278     node->setType(type);
  1279 }
  1280 
  1281 void
  1282 SemanticAnalysis::visit(FloatLiteral *node)
  1283 {
  1284     Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
  1285     if (!type)
  1286         return;
  1287 
  1288     node->setType(type);
  1289 }
  1290 
  1291 void
  1292 SemanticAnalysis::visit(BreakStatement *node)
  1293 {
  1294     if (!loop_) {
  1295         cc_.reportError(node->pos(), Message_BreakOutsideLoop);
  1296         return;
  1297     }
  1298 
  1299     // Note: ignore breaks that occur in unreachable control-flow.
  1300     if (!control_->status().terminates())
  1301         loop_->addBreak();
  1302 
  1303     control_->terminate(Returns_Never);
  1304 }
  1305 
  1306 void
  1307 SemanticAnalysis::visit(ContinueStatement *node)
  1308 {
  1309     if (!loop_) {
  1310         cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
  1311         return;
  1312     }
  1313 
  1314     // Note: ignore continues that occur in unreachable control-flow.
  1315     if (!control_->status().terminates())
  1316         loop_->addContinue();
  1317 
  1318     control_->terminate(Returns_Never);
  1319 }