jitcraft/SemanticAnalysis.cpp
author David Anderson <dvander@alliedmods.net>
Mon Jul 09 22:25:52 2012 -0700 (2012-07-09)
changeset 67 b765a6383849
parent 66 cbba1997dc71
child 68 b40b0e18a918
permissions -rw-r--r--
Implemented const for references and arrays.
     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 "SemanticAnalysis.h"
    20 #include "Types.h"
    21 #include "Zone.h"
    22 #include "TypeManager.h"
    23 #include "Scopes.h"
    24 #include "Heap-inl.h"
    25 #include "Strings.h"
    26 
    27 using namespace ke;
    28 
    29 static inline bool
    30 IsPrimitiveType(Type *type, PrimitiveType primitive)
    31 {
    32     if (!type)
    33         return false;
    34 
    35     if (!type->isPrimitive())
    36         return false;
    37 
    38     return primitive == type->primitive();
    39 }
    40 
    41 static inline bool
    42 EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
    43                         BoxedPrimitive *out)
    44 {
    45     switch (kind) {
    46       case TOK_PLUS:
    47         *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
    48         return true;
    49 
    50       case TOK_SHL:
    51         *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
    52         return true;
    53 
    54       default:
    55         return false;
    56     }
    57 }
    58 
    59 static bool
    60 EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
    61 {
    62     switch (expression->kind()) {
    63       case AstNode::kBinaryExpression:
    64       {
    65         BoxedPrimitive left;
    66         BoxedPrimitive right;
    67         BinaryExpression *b = expression->toBinaryExpression();
    68         if (!EvaluateForConstant(b->left(), &left) ||
    69             !EvaluateForConstant(b->right(), &right))
    70         {
    71             return false;
    72         }
    73         return EvaluateBinaryOperation(b->token(), left, right, out);
    74       }
    75 
    76       case AstNode::kNameProxy:
    77       {
    78         NameProxy *proxy = expression->toNameProxy();
    79         if (proxy->binding()->kind() != BoundName::CONSTANT)
    80             return false;
    81 
    82         NamedConstant *c = proxy->binding()->toNamedConstant();
    83         if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
    84             return false;
    85 
    86         *out = c->value();
    87         return true;
    88       }
    89 
    90       case AstNode::kIntegerLiteral:
    91         *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
    92         return true;
    93 
    94       default:
    95         return false;
    96     }
    97 }
    98 
    99 SemanticAnalysis::SemanticAnalysis(Zone *zone, CompileContext &cc, ParseTree *tree)
   100   : zone_(zone),
   101     cc_(cc),
   102     tree_(tree),
   103     loopDepth_(0),
   104     scope_(NULL)
   105 {
   106 }
   107 
   108 bool
   109 SemanticAnalysis::analyze()
   110 {
   111     if (cc_.failures())
   112         return false;
   113 
   114     for (size_t i = 0; i < tree_->statements()->length(); i++) {
   115         Statement *statement = tree_->statements()->at(i);
   116         if (statement->isFunctionStatement()) {
   117             FunctionStatement *funstmt = statement->toFunctionStatement();
   118             if (!preanalyze(funstmt))
   119                 return false;
   120         }
   121     }
   122 
   123     for (size_t i = 0; i < tree_->statements()->length(); i++) {
   124         Statement *statement = tree_->statements()->at(i);
   125         statement->accept(this);
   126     }
   127 
   128     return !cc_.failures();
   129 }
   130 
   131 Type *
   132 SemanticAnalysis::visitAndApplyType(Expression *expression)
   133 {
   134     expression->accept(this);
   135     return expression->type();
   136 }
   137 
   138 Type *
   139 SemanticAnalysis::visitForLoad(Expression *expression)
   140 {
   141     Local<Type> type(zone_, visitAndApplyType(expression));
   142     if (!type)
   143         return NULL;
   144 
   145     if (type->isReference()) {
   146         expression->setType(type->contained());
   147     } else if (expression->isIndexExpression()) {
   148         if (type->isArray())
   149             expression->setType(type->contained());
   150     }
   151 
   152     return expression->type();
   153 }
   154 
   155 Type *
   156 SemanticAnalysis::visitForRef(Expression *expression)
   157 {
   158     expression->accept(this);
   159     return expression->type();
   160 }
   161 
   162 // :TODO: this leaks an interior pointer.
   163 static inline const char *
   164 GetTypeName(Type *type)
   165 {
   166     if (type->isArray())
   167         return "array";
   168     if (type->isFunction())
   169         return "function";
   170     if (type->isReference())
   171         type = type->contained();
   172     if (type->tag())
   173         return type->tag()->chars();
   174     return "int";
   175 }
   176 
   177 void
   178 SemanticAnalysis::unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type)
   179 {
   180     const char *op = TokenNames[token];
   181     const char *name = GetTypeName(type);
   182 
   183     cc_.reportError(node->pos(), Message_UnaryTypeError, op, name);
   184 }
   185 
   186 void
   187 SemanticAnalysis::binaryTypeError(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
   188 {
   189     const char *op = TokenNames[token];
   190     const char *leftName = GetTypeName(left);
   191     const char *rightName = GetTypeName(right);
   192 
   193     cc_.reportError(node->pos(), Message_BinaryTypeError, op, leftName, rightName);
   194 }
   195 
   196 Type *
   197 SemanticAnalysis::typeCheckBinary(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
   198 {
   199     if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
   200         (token >= TOK_ASSIGN_ADD && token <= TOK_ASSIGN_DIV))
   201     {
   202         // If either side is a float, the other side must be a float or int.
   203         if (left->isFloat() || right->isFloat()) {
   204             Type *floatType = left->isFloat() ? left : right;
   205             Type *other = left->isFloat() ? right : left;
   206             if (other->isFloat() || (other->isInt32() && !other->tag()))
   207                 return floatType;
   208         }
   209     }
   210 
   211     if ((!left->isInt32() || left->tag()) ||
   212         (!right->isInt32() || right->tag()))
   213     {
   214         binaryTypeError(node, token, left, right);
   215         return NULL;
   216     }
   217 
   218     return left;
   219 }
   220 
   221 bool
   222 SemanticAnalysis::canTest(AstNode *node, Handle<Type> type)
   223 {
   224     if (type->isArray()) {
   225         cc_.reportError(node->pos(), Message_ArrayIsNotBoolean);
   226         return false;
   227     }
   228     return true;
   229 }
   230 
   231 Type *
   232 SemanticAnalysis::visitForLValue(Expression *expression)
   233 {
   234     if (expression->isIndexExpression()) {
   235         Type *type = visitAndApplyType(expression);
   236         if (!type)
   237             return NULL;
   238 
   239         if (type->isConst()) {
   240             cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
   241             return NULL;
   242         }
   243 
   244         return type->contained();
   245     }
   246 
   247     if (!expression->isNameProxy()) {
   248         cc_.reportError(expression->pos(), Message_ExpectedLValue);
   249         return NULL;
   250     }
   251 
   252     NameProxy *proxy = expression->toNameProxy();
   253     if (!proxy->binding()->kind() == BoundName::VARIABLE) {
   254         cc_.reportError(expression->pos(), Message_ExpectedLValue);
   255         return NULL;
   256     }
   257 
   258     Variable *var = proxy->binding()->toVariable();
   259     if (!var->type())
   260         return NULL;
   261 
   262     if  (var->type()->isReference()) {
   263         if (var->type()->isConst()) {
   264             cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
   265             return NULL;
   266         }
   267         return var->type()->contained();
   268     }
   269     return var->type();
   270 }
   271 
   272 void
   273 SemanticAnalysis::visit(NameProxy *name)
   274 {
   275     name->setType(name->binding()->type());
   276 }
   277 
   278 void
   279 SemanticAnalysis::visit(Assignment *node)
   280 {
   281     Local<Type> exprType(zone_, visitForLoad(node->expression()));
   282     if (!exprType)
   283         return ;
   284 
   285     Local<Type> type(zone_, visitForLValue(node->lvalue()));
   286     if (!type)
   287         return;
   288 
   289     if (node->token() != TOK_ASSIGN) {
   290         if (!typeCheckBinary(node, node->token(), type, exprType))
   291             return;
   292     }
   293 
   294     if (!typeCheckAssignment(node, exprType, type, true))
   295         return;
   296 
   297     node->setType(type);
   298 }
   299 
   300 void
   301 SemanticAnalysis::visit(IncDecExpression *node)
   302 {
   303     Local<Type> type(zone_, visitForLValue(node->expression()));
   304     if (!type)
   305         return;
   306 
   307     assert(!type->isReference());
   308 
   309     if ((!type->isInt32() || (type->isInt32() && type->tag())) && !type->isFloat()) {
   310         unaryTypeError(node, node->token(), type);
   311         return;
   312     }
   313 
   314     node->setType(type);
   315 }
   316 
   317 void
   318 SemanticAnalysis::visit(BinaryExpression *node)
   319 {
   320     Local<Type> left(zone_, visitForLoad(node->left()));
   321     Local<Type> right(zone_, visitForLoad(node->right()));
   322     if (!left || !right)
   323         return;
   324 
   325     Local<Type> result(zone_, typeCheckBinary(node, node->token(), left, right));
   326     if (!result)
   327         return;
   328 
   329     node->setType(result);
   330 }
   331 
   332 void
   333 SemanticAnalysis::visit(ReturnStatement *node)
   334 {
   335     Local<Type> type(zone_, visitForLoad(node->expression()));
   336     if (!type)
   337         return;
   338 
   339     Local<Type> returnType(zone_, function_->returnType());
   340     if (!typeCheckAssignment(node, type, returnType, true))
   341         return;
   342 }
   343 
   344 void
   345 SemanticAnalysis::visit(ForStatement *node)
   346 {
   347     loopDepth_++;
   348     if (node->scope())
   349         scope_ = node->scope();
   350 
   351     if (node->initialization())
   352         node->initialization()->accept(this);
   353 
   354     if (node->condition()) {
   355         Local<Type> type(zone_, visitForLoad(node->condition()));
   356         if (!type || !canTest(node->condition(), type)) {
   357             loopDepth_--;
   358             return;
   359         }
   360     }
   361 
   362     if (node->update())
   363         node->update()->accept(this);
   364 
   365     node->body()->accept(this);
   366 
   367     if (node->scope())
   368         scope_ = scope_->enclosing();
   369     loopDepth_--;
   370 }
   371 
   372 void 
   373 SemanticAnalysis::visit(WhileStatement *node)
   374 {
   375     loopDepth_++;
   376 
   377     Local<Type> type(zone_, visitForLoad(node->condition()));
   378     if (!type || !canTest(node->condition(), type)) {
   379         loopDepth_--;
   380         return;
   381     }
   382 
   383     node->body()->accept(this);
   384     loopDepth_--;
   385 }
   386 
   387 void
   388 SemanticAnalysis::visit(BlockStatement *node)
   389 {
   390     if (node->scope())
   391         scope_ = node->scope();
   392     for (size_t i = 0; i < node->statements()->length(); i++) {
   393         Statement *statement = node->statements()->at(i);
   394         statement->accept(this);
   395     }
   396     if (node->scope())
   397         scope_ = scope_->enclosing();
   398 }
   399 
   400 void
   401 SemanticAnalysis::visit(VariableDeclaration *node)
   402 {
   403     Local<String> tag(zone_, node->tag());
   404     Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
   405     if (!type)
   406         return;
   407 
   408     if (node->postDimensions()) {
   409         Local<Type> init(zone_);
   410         if (node->initialization()) {
   411             if ((init = visitAndApplyType(node->initialization())) == NULL)
   412                 return;
   413         }
   414 
   415         if (node->postDimensions()->length() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
   416             cc_.reportError(node->pos(), Message_MaximumArrayDepth);
   417             return;
   418         }
   419 
   420         // If we have an initializer, make sure it's the same type.
   421         if (init && node->postDimensions()->length() != init->levels()) {
   422             cc_.reportError(node->pos(), Message_ArrayInitializerDepth);
   423             return;
   424         }
   425 
   426         Local<Type> check(zone_, init);
   427         for (size_t i = node->postDimensions()->length() - 1; i < node->postDimensions()->length(); i--) {
   428             Expression *expr = node->postDimensions()->at(i);
   429             int size = -1;
   430 
   431             if (expr) {
   432                 Local<Type> exprType(zone_, visitForLoad(expr));
   433                 if (!exprType)
   434                     return;
   435 
   436                 if (!IsPrimitiveType(exprType, PrimitiveType_Int32)) {
   437                     cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
   438                     return;
   439                 }
   440 
   441                 BoxedPrimitive box;
   442                 if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
   443                     size = box.toInt();
   444                     if (size <= 0) {
   445                         cc_.reportError(expr->pos(), Message_BadArraySize);
   446                         return;
   447                     }
   448                     if (size >= INT_MAX / sizeof(int)) {
   449                         cc_.reportError(expr->pos(), Message_ArraySizeTooBig);
   450                         return;
   451                     }
   452 
   453                     if (check) {
   454                         if (check->elements() == -1) {
   455                             cc_.reportError(expr->pos(), Message_ArraySizeCannotBeDetermined);
   456                             return;
   457                         }
   458 
   459                         if (check->isCharArray()) {
   460                             if (check->elements() > size) {
   461                                 cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
   462                                 return;
   463                             }
   464                         } else if (check->elements() != size) {
   465                             cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, unsigned(i));
   466                             return;
   467                         }
   468                     }
   469                 } else {
   470                     if (init) {
   471                         cc_.reportError(node->pos(), Message_DynamicArrayHasInitializer);
   472                         return;
   473                     }
   474 
   475                     // here until we get dynamic array support.
   476                     cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
   477                     return;
   478                 }
   479             } else {
   480                 // Infer the size from the initializer.
   481                 if (!init) {
   482                     cc_.reportError(node->pos(), Message_ArraySizeNotSpecified);
   483                     return;
   484                 }
   485                 if (init->elements() == -1) {
   486                     cc_.reportError(node->pos(), Message_ArraySizeCannotBeDetermined);
   487                     return;
   488                 }
   489                 size = init->elements();
   490             }
   491 
   492             type = zone_->types()->unsafeArray(type, size, false);
   493             if (!type)
   494                 return;
   495 
   496             if (check)
   497                 check = check->contained();
   498         }
   499 
   500         // Right now, any array is allowed on the LIFO heap. In case the
   501         // runtime actually decides to use the LIFO heap, we must reserve
   502         // a slot so we can unwind the heap when the current scope leaves.
   503         scope_->setUsesLifoHeap();
   504     } else {
   505         if (node->initialization()) {
   506             Local<Type> right(zone_, visitForLoad(node->initialization()));
   507             if (!right)
   508                 return;
   509             if (!typeCheckAssignment(node, type, right, true))
   510                 return;
   511         }
   512         if (type->primitive() == PrimitiveType_Char) {
   513             cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
   514             return;
   515         }
   516     }
   517 
   518     node->variable()->setType(type);
   519 }
   520 
   521 void
   522 SemanticAnalysis::visit(IntegerLiteral *node)
   523 {
   524     node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
   525 }
   526 
   527 void
   528 SemanticAnalysis::visit(ExpressionStatement *node)
   529 {
   530     node->expression()->accept(this);
   531 }
   532 
   533 bool
   534 SemanticAnalysis::preanalyze(FunctionStatement *node)
   535 {
   536     Local<FixedArray> args(zone_, FixedArray::New(zone_, node->parameters()->length(), Heap::Tenure_Old));
   537     if (!args)
   538         return false;
   539 
   540     // Apply types to arguments.
   541     for (size_t i = 0; i < node->parameters()->length(); i++) {
   542         Parameter *parameter = node->parameters()->at(i);
   543         
   544         Local<String> tag(zone_, parameter->tag());
   545         Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
   546         if (!type)
   547             return false;
   548 
   549         if (type->primitive() == PrimitiveType_Char) {
   550             cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
   551             return false;
   552         }
   553 
   554         if (parameter->reference()) {
   555             if (parameter->dimensions()) {
   556                 cc_.reportError(parameter->variable()->pos(), Message_ArrayCantBeReference);
   557                 return NULL;
   558             }
   559 
   560             type = zone_->types()->getReference(type, parameter->isConst());
   561             if (!type)
   562                 return false;
   563         } else if (parameter->dimensions()) {
   564             if (parameter->dimensions()->length() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
   565                 cc_.reportError(node->pos(), Message_MaximumArrayDepth);
   566                 return false;
   567             }
   568 
   569             for (size_t i = parameter->dimensions()->length() - 1;
   570                  i < parameter->dimensions()->length();
   571                  i++)
   572             {
   573                 int size = Type::UNKNOWN_SIZE;
   574                 if (Expression *expr = parameter->dimensions()->at(i)) {
   575                     BoxedPrimitive box;
   576                     if (!EvaluateForConstant(expr, &box)) {
   577                         cc_.reportError(expr->pos(), Message_ArraySizeMustBeConstant);
   578                         return false;
   579                     }
   580                     size = box.toInt();
   581                 }
   582 
   583                 type = zone_->types()->unsafeArray(type, size, parameter->isConst());
   584                 if (!type)
   585                     return false;
   586             }
   587         }
   588 
   589         args->set(zone_, i, type);
   590         parameter->variable()->setType(type);
   591     }
   592 
   593     Local<Type> returnType(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
   594     if (!returnType)
   595         return false;
   596 
   597     Local<Type> funtype(zone_, zone_->types()->newFunction(returnType, args));
   598     if (!funtype)
   599         return false;
   600     
   601     // If the function already has a type, it was forward declared before, and
   602     // now this is our chance to type check the second declaration.
   603     if (node->fun()->type()) {
   604         Local<Type> forward(zone_, node->fun()->type());
   605         if (!Type::Compare(funtype, forward)) {
   606             cc_.reportError(node->pos(), Message_ForwardDeclareMismatches);
   607             return false;
   608         }
   609         node->fun()->setForwardType(forward);
   610     }
   611 
   612     node->fun()->setType(funtype);
   613 
   614     return true;
   615 }
   616 
   617 void
   618 SemanticAnalysis::visit(FunctionStatement *node)
   619 {
   620     function_ = node->fun()->type();
   621     scope_ = node->scope();
   622     if (node->body())
   623         node->body()->accept(this);
   624     scope_ = NULL;
   625     function_ = NULL;
   626 }
   627 
   628 bool
   629 SemanticAnalysis::typeCheckArrayAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
   630 {
   631     Local<Type> actual(zone_, argActual);
   632     Local<Type> given(zone_, argGiven);
   633 
   634     if (!given->isArray()) {
   635         cc_.reportError(node->pos(), Message_ExpectedArray);
   636         return false;
   637     }
   638     if (given->levels() != actual->levels()) {
   639         cc_.reportError(node->pos(), Message_ArrayDimensionsMismatch);
   640         return false;
   641     }
   642 
   643     unsigned level = 0;
   644     while (given->isArray()) {
   645         if (actual->elements() != -1) {
   646             if (forAssign) {
   647                 if (given->elements() == -1 || actual->elements() == -1) {
   648                     cc_.reportError(node->pos(), Message_ArraySizeNotKnown);
   649                     return false;
   650                 }
   651 
   652                 if (actual->isCharArray()) {
   653                     // String assignment can have a truncated |given|.
   654                     if (given->elements() > actual->elements()) {
   655                         cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
   656                         return false;
   657                     }
   658                 } else {
   659                     if (given->elements() != actual->elements()) {
   660                         cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
   661                         return false;
   662                     }
   663                 }
   664             } else {
   665                 if (actual->elements() != -1 && given->elements() != actual->elements()) {
   666                     cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
   667                     return false;
   668                 }
   669             }
   670         }
   671         given = given->contained();
   672         actual = actual->contained();
   673     }
   674 
   675     if (given->primitive() != actual->primitive()) {
   676         // :TODO: leaks an interior pointer.
   677         const char *givenTag = given->tag() ? given->tag()->chars() : "_";
   678         const char *actualTag = given->tag() ? given->tag()->chars() : "_";
   679         cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
   680         return false;
   681     }
   682 
   683     return true;
   684 }
   685 
   686 bool
   687 SemanticAnalysis::typeCheckAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
   688 {
   689     Local<Type> actual(zone_, argActual);
   690     Local<Type> given(zone_, argGiven);
   691 
   692     if (actual->isArray())
   693         return typeCheckArrayAssignment(node, given, actual, forAssign);
   694 
   695     if (given->isArray()) {
   696         cc_.reportError(node->pos(), Message_CannotAssignArrayToScalar);
   697         return false;
   698     }
   699 
   700     // The given type may not have been dereferenced.
   701     if (given->isReference())
   702         given = given->contained();
   703     if (actual->isReference())
   704         actual = actual->contained();
   705 
   706     if (!given->isPrimitive() || !actual->isPrimitive()) {
   707         cc_.reportError(node->pos(), Message_UnsupportedType);
   708         return false;
   709     }
   710     
   711     if (given->primitive() != actual->primitive()) {
   712         // :TODO: leaks an interior pointer
   713         const char *givenTag = given->tag() ? given->tag()->chars() : "_";
   714         const char *actualTag = given->tag() ? given->tag()->chars() : "_";
   715         cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
   716         return false;
   717     }
   718 
   719     return true;
   720 }
   721 
   722 bool
   723 SemanticAnalysis::typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual)
   724 {
   725     return typeCheckAssignment(node, given, actual, false);
   726 }
   727 
   728 void
   729 SemanticAnalysis::visit(CallExpression *node)
   730 {
   731     Local<Type> type(zone_, visitForLoad(node->callee()));
   732     if (!type)
   733         return;
   734 
   735     if (!type->isFunction()) {
   736         cc_.reportError(node->pos(), Message_CalleeNotFunction);
   737         return;
   738     }
   739     if (node->arguments()->length() != type->parameters()->length()) {
   740         cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
   741         return;
   742     }
   743 
   744     // Currently, only calls from a NameProxy are possible.
   745     NamedFunction *fun = node->callee()->toNameProxy()->binding()->toNamedFunction();
   746     if (fun->isForward()) {
   747         cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
   748         return;
   749     }
   750 
   751     for (unsigned i = 0; i < node->arguments()->length(); i++) {
   752         // Note: we don't compute references unless the callee needs a
   753         // reference type.
   754         Expression *expression = node->arguments()->at(i);
   755         Local<Type> given(zone_, visitAndApplyType(expression));
   756         if (!given)
   757             return;
   758 
   759         // If it's an IndexExpression, we special case the ability to compute
   760         // a reference.
   761         if (expression->isIndexExpression())
   762             given = given->contained();
   763 
   764         Local<Type> actual(zone_, type->parameterAt(i));
   765         if (!typeCheckParameter(expression, given, actual))
   766             return;
   767 
   768         // If the actual is a reference, and the given is not, we'll need to
   769         // compute a reference, which may be allocated on the stack.
   770         if (actual->isReference() && !given->isReference())
   771             scope_->setUsesLifoHeap();
   772     }
   773 
   774     node->setType(fun->type()->returnType());
   775 }
   776 
   777 void
   778 SemanticAnalysis::visit(IfStatement *node)
   779 {
   780     Local<Type> type(zone_, visitForLoad(node->condition()));
   781     if (!type)
   782         return;
   783 
   784     if (!canTest(node, type))
   785         return;
   786 
   787     node->ifTrue()->accept(this);
   788     if (node->ifFalse())
   789         node->ifFalse()->accept(this);
   790 }
   791 
   792 void
   793 SemanticAnalysis::visit(IndexExpression *node)
   794 {
   795     Local<Type> left(zone_, visitForRef(node->left()));
   796     Local<Type> right(zone_, visitForLoad(node->right()));
   797 
   798     if (!left || !right)
   799         return;
   800 
   801     if (!right->isInt32()) {
   802         cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
   803         return;
   804     }
   805     if (!left->isArray()) {
   806         cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
   807         return;
   808     }
   809     node->setType(left);
   810 }
   811 
   812 void
   813 SemanticAnalysis::visit(EnumStatement *node)
   814 {
   815     // Forbid the blessed types.
   816     Local<String> tag(zone_, node->name());
   817     if (!strcmp(tag->chars(), "Float") ||
   818         !strcmp(tag->chars(), "String") ||
   819         !strcmp(tag->chars(), "any") ||
   820         !strcmp(tag->chars(), "bool"))
   821     {
   822         cc_.reportError(node->pos(), Message_InvalidEnumName);
   823         return;
   824     }
   825 
   826     Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
   827     if (!type)
   828         return;
   829 
   830     int value = 0;
   831     for (size_t i = 0; i < node->entries()->length(); i++) {
   832         EnumStatement::Entry &entry = node->entries()->at(i);
   833 
   834         BoxedPrimitive box = BoxedPrimitive::Int(value);
   835         if (entry.expr) {
   836             entry.expr->accept(this);
   837             if (!EvaluateForConstant(entry.expr, &box)) {
   838                 cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
   839                 return;
   840             }
   841 
   842             assert(box.type() == PrimitiveType_Int32);
   843             value = box.toInt();
   844         }
   845 
   846         entry.name->set(type, box);
   847         value++;
   848     }
   849 }
   850 
   851 void
   852 SemanticAnalysis::visit(StringLiteral *node)
   853 {
   854     Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Char));
   855     if (!type)
   856         return;
   857 
   858     type = Type::NewArray(zone_, type, node->string()->length() + 1, true);
   859     if (!type)
   860         return;
   861 
   862     node->setType(type);
   863 }
   864 
   865 void
   866 SemanticAnalysis::visit(FloatLiteral *node)
   867 {
   868     Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
   869     if (!type)
   870         return;
   871 
   872     node->setType(type);
   873 }
   874 
   875 void
   876 SemanticAnalysis::visit(BreakStatement *node)
   877 {
   878     if (loopDepth_ == 0)
   879         cc_.reportError(node->pos(), Message_BreakOutsideLoop);
   880 }
   881 
   882 void
   883 SemanticAnalysis::visit(ContinueStatement *node)
   884 {
   885     if (loopDepth_ == 0)
   886         cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
   887 }