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