jitcraft/SemanticAnalysis.cpp
author David Anderson <dvander@alliedmods.net>
Sat Jul 07 21:30:23 2012 -0700 (2012-07-07)
changeset 59 b7d61ddb3c8d
parent 57 8f1e74d35718
child 63 dd57743d220e
permissions -rw-r--r--
Rename jc:: to ke::
     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         return type->contained();
   240     }
   241 
   242     if (!expression->isNameProxy()) {
   243         cc_.reportError(expression->pos(), Message_ExpectedLValue);
   244         return NULL;
   245     }
   246 
   247     NameProxy *proxy = expression->toNameProxy();
   248     if (!proxy->binding()->kind() == BoundName::VARIABLE) {
   249         cc_.reportError(expression->pos(), Message_ExpectedLValue);
   250         return NULL;
   251     }
   252 
   253     Variable *var = proxy->binding()->toVariable();
   254     if (!var->type())
   255         return NULL;
   256 
   257     if  (var->type()->isReference())
   258         return var->type()->contained();
   259     return var->type();
   260 }
   261 
   262 void
   263 SemanticAnalysis::visit(NameProxy *name)
   264 {
   265     name->setType(name->binding()->type());
   266 }
   267 
   268 void
   269 SemanticAnalysis::visit(Assignment *node)
   270 {
   271     Local<Type> exprType(zone_, visitForLoad(node->expression()));
   272     if (!exprType)
   273         return ;
   274 
   275     Local<Type> type(zone_, visitForLValue(node->lvalue()));
   276     if (!type)
   277         return;
   278 
   279     if (node->token() != TOK_ASSIGN) {
   280         if (!typeCheckBinary(node, node->token(), type, exprType))
   281             return;
   282     }
   283 
   284     if (!typeCheckAssignment(node, exprType, type, true))
   285         return;
   286 
   287     node->setType(type);
   288 }
   289 
   290 void
   291 SemanticAnalysis::visit(IncDecExpression *node)
   292 {
   293     Local<Type> type(zone_, visitForLValue(node->expression()));
   294     if (!type)
   295         return;
   296 
   297     assert(!type->isReference());
   298 
   299     if ((!type->isInt32() || (type->isInt32() && type->tag())) && !type->isFloat()) {
   300         unaryTypeError(node, node->token(), type);
   301         return;
   302     }
   303 
   304     node->setType(type);
   305 }
   306 
   307 void
   308 SemanticAnalysis::visit(BinaryExpression *node)
   309 {
   310     Local<Type> left(zone_, visitForLoad(node->left()));
   311     Local<Type> right(zone_, visitForLoad(node->right()));
   312     if (!left || !right)
   313         return;
   314 
   315     Local<Type> result(zone_, typeCheckBinary(node, node->token(), left, right));
   316     if (!result)
   317         return;
   318 
   319     node->setType(result);
   320 }
   321 
   322 void
   323 SemanticAnalysis::visit(ReturnStatement *node)
   324 {
   325     Local<Type> type(zone_, visitForLoad(node->expression()));
   326     if (!type)
   327         return;
   328 
   329     Local<Type> returnType(zone_, function_->returnType());
   330     if (!typeCheckAssignment(node, type, returnType, true))
   331         return;
   332 }
   333 
   334 void
   335 SemanticAnalysis::visit(ForStatement *node)
   336 {
   337     loopDepth_++;
   338     if (node->scope())
   339         scope_ = node->scope();
   340 
   341     if (node->initialization())
   342         node->initialization()->accept(this);
   343 
   344     if (node->condition()) {
   345         Local<Type> type(zone_, visitForLoad(node->condition()));
   346         if (!type || !canTest(node->condition(), type)) {
   347             loopDepth_--;
   348             return;
   349         }
   350     }
   351 
   352     if (node->update())
   353         node->update()->accept(this);
   354 
   355     node->body()->accept(this);
   356 
   357     if (node->scope())
   358         scope_ = scope_->enclosing();
   359     loopDepth_--;
   360 }
   361 
   362 void 
   363 SemanticAnalysis::visit(WhileStatement *node)
   364 {
   365     loopDepth_++;
   366 
   367     Local<Type> type(zone_, visitForLoad(node->condition()));
   368     if (!type || !canTest(node->condition(), type)) {
   369         loopDepth_--;
   370         return;
   371     }
   372 
   373     node->body()->accept(this);
   374     loopDepth_--;
   375 }
   376 
   377 void
   378 SemanticAnalysis::visit(BlockStatement *node)
   379 {
   380     if (node->scope())
   381         scope_ = node->scope();
   382     for (size_t i = 0; i < node->statements()->length(); i++) {
   383         Statement *statement = node->statements()->at(i);
   384         statement->accept(this);
   385     }
   386     if (node->scope())
   387         scope_ = scope_->enclosing();
   388 }
   389 
   390 void
   391 SemanticAnalysis::visit(VariableDeclaration *node)
   392 {
   393     Local<String> tag(zone_, node->tag());
   394     Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
   395     if (!type)
   396         return;
   397 
   398     if (node->postDimensions()) {
   399         Local<Type> init(zone_);
   400         if (node->initialization()) {
   401             if ((init = visitAndApplyType(node->initialization())) == NULL)
   402                 return;
   403         }
   404 
   405         if (node->postDimensions()->length() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
   406             cc_.reportError(node->pos(), Message_MaximumArrayDepth);
   407             return;
   408         }
   409 
   410         // If we have an initializer, make sure it's the same type.
   411         if (init && node->postDimensions()->length() != init->levels()) {
   412             cc_.reportError(node->pos(), Message_ArrayInitializerDepth);
   413             return;
   414         }
   415 
   416         Local<Type> check(zone_, init);
   417         for (size_t i = node->postDimensions()->length() - 1; i < node->postDimensions()->length(); i--) {
   418             Expression *expr = node->postDimensions()->at(i);
   419             int size = -1;
   420 
   421             if (expr) {
   422                 Local<Type> exprType(zone_, visitForLoad(expr));
   423                 if (!exprType)
   424                     return;
   425 
   426                 if (!IsPrimitiveType(exprType, PrimitiveType_Int32)) {
   427                     cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
   428                     return;
   429                 }
   430 
   431                 BoxedPrimitive box;
   432                 if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
   433                     size = box.toInt();
   434                     if (size <= 0) {
   435                         cc_.reportError(expr->pos(), Message_BadArraySize);
   436                         return;
   437                     }
   438                     if (size >= INT_MAX / sizeof(int)) {
   439                         cc_.reportError(expr->pos(), Message_ArraySizeTooBig);
   440                         return;
   441                     }
   442 
   443                     if (check) {
   444                         if (check->elements() == -1) {
   445                             cc_.reportError(expr->pos(), Message_ArraySizeCannotBeDetermined);
   446                             return;
   447                         }
   448 
   449                         if (check->isCharArray()) {
   450                             if (check->elements() > size) {
   451                                 cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
   452                                 return;
   453                             }
   454                         } else if (check->elements() != size) {
   455                             cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, unsigned(i));
   456                             return;
   457                         }
   458                     }
   459                 } else {
   460                     if (init) {
   461                         cc_.reportError(node->pos(), Message_DynamicArrayHasInitializer);
   462                         return;
   463                     }
   464 
   465                     // here until we get dynamic array support.
   466                     cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
   467                     return;
   468                 }
   469             } else {
   470                 // Infer the size from the initializer.
   471                 if (!init) {
   472                     cc_.reportError(node->pos(), Message_ArraySizeNotSpecified);
   473                     return;
   474                 }
   475                 if (init->elements() == -1) {
   476                     cc_.reportError(node->pos(), Message_ArraySizeCannotBeDetermined);
   477                     return;
   478                 }
   479                 size = init->elements();
   480             }
   481 
   482             type = zone_->types()->unsafeArray(type, size);
   483             if (!type)
   484                 return;
   485 
   486             if (check)
   487                 check = check->contained();
   488         }
   489 
   490         // Right now, any array is allowed on the LIFO heap. In case the
   491         // runtime actually decides to use the LIFO heap, we must reserve
   492         // a slot so we can unwind the heap when the current scope leaves.
   493         scope_->setUsesLifoHeap();
   494     } else {
   495         if (node->initialization()) {
   496             Local<Type> right(zone_, visitForLoad(node->initialization()));
   497             if (!right)
   498                 return;
   499             if (!typeCheckAssignment(node, type, right, true))
   500                 return;
   501         }
   502         if (type->primitive() == PrimitiveType_Char) {
   503             cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
   504             return;
   505         }
   506     }
   507 
   508     node->variable()->setType(type);
   509 }
   510 
   511 void
   512 SemanticAnalysis::visit(IntegerLiteral *node)
   513 {
   514     node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
   515 }
   516 
   517 void
   518 SemanticAnalysis::visit(ExpressionStatement *node)
   519 {
   520     node->expression()->accept(this);
   521 }
   522 
   523 bool
   524 SemanticAnalysis::preanalyze(FunctionStatement *node)
   525 {
   526     Local<FixedArray> args(zone_, FixedArray::New(zone_, node->parameters()->length(), Heap::Tenure_Old));
   527     if (!args)
   528         return false;
   529 
   530     // Apply types to arguments.
   531     for (size_t i = 0; i < node->parameters()->length(); i++) {
   532         Parameter *parameter = node->parameters()->at(i);
   533         
   534         Local<String> tag(zone_, parameter->tag());
   535         Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
   536         if (!type)
   537             return false;
   538 
   539         if (type->primitive() == PrimitiveType_Char) {
   540             cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
   541             return false;
   542         }
   543 
   544         if (parameter->reference()) {
   545             type = zone_->types()->getReference(type);
   546             if (!type)
   547                 return false;
   548         }
   549 
   550         args->set(zone_, i, type);
   551         parameter->variable()->setType(type);
   552     }
   553 
   554     Local<Type> returnType(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
   555     if (!returnType)
   556         return false;
   557 
   558     Local<Type> funtype(zone_, zone_->types()->newFunction(returnType, args));
   559     if (!funtype)
   560         return false;
   561 
   562     node->fun()->setType(funtype);
   563     return true;
   564 }
   565 
   566 void
   567 SemanticAnalysis::visit(FunctionStatement *node)
   568 {
   569     function_ = node->fun()->type();
   570     scope_ = node->scope();
   571     node->body()->accept(this);
   572     scope_ = NULL;
   573     function_ = NULL;
   574 }
   575 
   576 bool
   577 SemanticAnalysis::typeCheckArrayAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
   578 {
   579     Local<Type> actual(zone_, argActual);
   580     Local<Type> given(zone_, argGiven);
   581 
   582     if (!given->isArray()) {
   583         cc_.reportError(node->pos(), Message_ExpectedArray);
   584         return false;
   585     }
   586     if (given->levels() != actual->levels()) {
   587         cc_.reportError(node->pos(), Message_ArrayDimensionsMismatch);
   588         return false;
   589     }
   590 
   591     unsigned level = 0;
   592     while (given->isArray()) {
   593         if (actual->elements() != -1) {
   594             if (forAssign) {
   595                 if (given->elements() == -1 || actual->elements() == -1) {
   596                     cc_.reportError(node->pos(), Message_ArraySizeNotKnown);
   597                     return false;
   598                 }
   599 
   600                 if (actual->isCharArray()) {
   601                     // String assignment can have a truncated |given|.
   602                     if (given->elements() > actual->elements()) {
   603                         cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
   604                         return false;
   605                     }
   606                 } else {
   607                     if (given->elements() != actual->elements()) {
   608                         cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
   609                         return false;
   610                     }
   611                 }
   612             } else {
   613                 if (actual->elements() != -1 && given->elements() != actual->elements()) {
   614                     cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
   615                     return false;
   616                 }
   617             }
   618         }
   619         given = given->contained();
   620         actual = actual->contained();
   621     }
   622 
   623     if (given->primitive() != actual->primitive()) {
   624         // :TODO: leaks an interior pointer.
   625         const char *givenTag = given->tag() ? given->tag()->chars() : "_";
   626         const char *actualTag = given->tag() ? given->tag()->chars() : "_";
   627         cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
   628         return false;
   629     }
   630 
   631     return true;
   632 }
   633 
   634 bool
   635 SemanticAnalysis::typeCheckAssignment(AstNode *node, Handle<Type> argGiven, Handle<Type> argActual, bool forAssign)
   636 {
   637     Local<Type> actual(zone_, argActual);
   638     Local<Type> given(zone_, argGiven);
   639 
   640     if (actual->isArray())
   641         return typeCheckArrayAssignment(node, given, actual, forAssign);
   642 
   643     if (given->isArray()) {
   644         cc_.reportError(node->pos(), Message_CannotAssignArrayToScalar);
   645         return false;
   646     }
   647 
   648     // The given type may not have been dereferenced.
   649     if (given->isReference())
   650         given = given->contained();
   651     if (actual->isReference())
   652         actual = actual->contained();
   653 
   654     if (!given->isPrimitive() || !actual->isPrimitive()) {
   655         cc_.reportError(node->pos(), Message_UnsupportedType);
   656         return false;
   657     }
   658     
   659     if (given->primitive() != actual->primitive()) {
   660         // :TODO: leaks an interior pointer
   661         const char *givenTag = given->tag() ? given->tag()->chars() : "_";
   662         const char *actualTag = given->tag() ? given->tag()->chars() : "_";
   663         cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
   664         return false;
   665     }
   666 
   667     return true;
   668 }
   669 
   670 bool
   671 SemanticAnalysis::typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual)
   672 {
   673     return typeCheckAssignment(node, given, actual, false);
   674 }
   675 
   676 void
   677 SemanticAnalysis::visit(CallExpression *node)
   678 {
   679     Local<Type> type(zone_, visitForLoad(node->callee()));
   680     if (!type)
   681         return;
   682 
   683     if (!type->isFunction()) {
   684         cc_.reportError(node->pos(), Message_CalleeNotFunction);
   685         return;
   686     }
   687     if (node->arguments()->length() != type->parameters()->length()) {
   688         cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
   689         return;
   690     }
   691 
   692     for (unsigned i = 0; i < node->arguments()->length(); i++) {
   693         // Note: we don't compute references unless the callee needs a
   694         // reference type.
   695         Expression *expression = node->arguments()->at(i);
   696         Local<Type> given(zone_, visitAndApplyType(expression));
   697         if (!given)
   698             return;
   699 
   700         // If it's an IndexExpression, we special case the ability to compute
   701         // a reference.
   702         if (expression->isIndexExpression())
   703             given = given->contained();
   704 
   705         Local<Type> actual(zone_, type->parameterAt(i));
   706         if (!typeCheckParameter(expression, given, actual))
   707             return;
   708 
   709         // If the actual is a reference, and the given is not, we'll need to
   710         // compute a reference, which may be allocated on the stack.
   711         if (actual->isReference() && !given->isReference())
   712             scope_->setUsesLifoHeap();
   713     }
   714 }
   715 
   716 void
   717 SemanticAnalysis::visit(IfStatement *node)
   718 {
   719     Local<Type> type(zone_, visitForLoad(node->condition()));
   720     if (!type)
   721         return;
   722 
   723     if (!canTest(node, type))
   724         return;
   725 
   726     node->ifTrue()->accept(this);
   727     if (node->ifFalse())
   728         node->ifFalse()->accept(this);
   729 }
   730 
   731 void
   732 SemanticAnalysis::visit(IndexExpression *node)
   733 {
   734     Local<Type> left(zone_, visitForRef(node->left()));
   735     Local<Type> right(zone_, visitForLoad(node->right()));
   736 
   737     if (!left || !right)
   738         return;
   739 
   740     if (!right->isInt32()) {
   741         cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
   742         return;
   743     }
   744     if (!left->isArray()) {
   745         cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
   746         return;
   747     }
   748     node->setType(left);
   749 }
   750 
   751 void
   752 SemanticAnalysis::visit(EnumStatement *node)
   753 {
   754     // Forbid the blessed types.
   755     Local<String> tag(zone_, node->name());
   756     if (!strcmp(tag->chars(), "Float") ||
   757         !strcmp(tag->chars(), "String") ||
   758         !strcmp(tag->chars(), "any") ||
   759         !strcmp(tag->chars(), "bool"))
   760     {
   761         cc_.reportError(node->pos(), Message_InvalidEnumName);
   762         return;
   763     }
   764 
   765     Local<Type> type(zone_, zone_->types()->getPrimitiveForTag(tag));
   766     if (!type)
   767         return;
   768 
   769     int value = 0;
   770     for (size_t i = 0; i < node->entries()->length(); i++) {
   771         EnumStatement::Entry &entry = node->entries()->at(i);
   772 
   773         BoxedPrimitive box = BoxedPrimitive::Int(value);
   774         if (entry.expr) {
   775             entry.expr->accept(this);
   776             if (!EvaluateForConstant(entry.expr, &box)) {
   777                 cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
   778                 return;
   779             }
   780 
   781             assert(box.type() == PrimitiveType_Int32);
   782             value = box.toInt();
   783         }
   784 
   785         entry.name->set(type, box);
   786         value++;
   787     }
   788 }
   789 
   790 void
   791 SemanticAnalysis::visit(StringLiteral *node)
   792 {
   793     Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Char));
   794     if (!type)
   795         return;
   796 
   797     type = Type::NewArray(zone_, type, node->string()->length() + 1, true);
   798     if (!type)
   799         return;
   800 
   801     node->setType(type);
   802 }
   803 
   804 void
   805 SemanticAnalysis::visit(FloatLiteral *node)
   806 {
   807     Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
   808     if (!type)
   809         return;
   810 
   811     node->setType(type);
   812 }
   813 
   814 void
   815 SemanticAnalysis::visit(BreakStatement *node)
   816 {
   817     if (loopDepth_ == 0)
   818         cc_.reportError(node->pos(), Message_BreakOutsideLoop);
   819 }
   820 
   821 void
   822 SemanticAnalysis::visit(ContinueStatement *node)
   823 {
   824     if (loopDepth_ == 0)
   825         cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
   826 }