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