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