1.1 --- a/jitcraft/SemanticAnalysis.cpp Sun Jul 01 18:39:11 2012 -0700
1.2 +++ b/jitcraft/SemanticAnalysis.cpp Mon Jul 02 01:24:57 2012 -0700
1.3 @@ -92,8 +92,9 @@
1.4 }
1.5 }
1.6
1.7 -SemanticAnalysis::SemanticAnalysis(ParseTree *tree)
1.8 - : tree_(tree),
1.9 +SemanticAnalysis::SemanticAnalysis(CompileContext &cc, ParseTree *tree)
1.10 + : cc_(cc),
1.11 + tree_(tree),
1.12 loopDepth_(0),
1.13 scope_(NULL)
1.14 {
1.15 @@ -102,35 +103,48 @@
1.16 bool
1.17 SemanticAnalysis::analyze()
1.18 {
1.19 + if (cc_.failures())
1.20 + return false;
1.21 +
1.22 + for (size_t i = 0; i < tree_->statements()->length(); i++) {
1.23 + Statement *statement = tree_->statements()->at(i);
1.24 + if (statement->isFunctionStatement()) {
1.25 + FunctionStatement *funstmt = statement->toFunctionStatement();
1.26 + if (!preanalyze(funstmt))
1.27 + return false;
1.28 + }
1.29 + }
1.30 +
1.31 for (size_t i = 0; i < tree_->statements()->length(); i++) {
1.32 Statement *statement = tree_->statements()->at(i);
1.33 statement->accept(this);
1.34 }
1.35
1.36 - return true;
1.37 + return !cc_.failures();
1.38 }
1.39
1.40 -void
1.41 -SemanticAnalysis::visit(NameProxy *name)
1.42 +Type *
1.43 +SemanticAnalysis::visitAndApplyType(Expression *expression)
1.44 {
1.45 - name->setType(name->binding()->type());
1.46 + expression->accept(this);
1.47 + return expression->type();
1.48 }
1.49
1.50 Type *
1.51 SemanticAnalysis::visitForLoad(Expression *expression)
1.52 {
1.53 - expression->accept(this);
1.54 - if (!expression->type())
1.55 + // :TODO: use Local
1.56 + Type *type = visitAndApplyType(expression);
1.57 + if (!type)
1.58 return NULL;
1.59
1.60 - // :TODO: use Local
1.61 - Type *type = expression->type();
1.62 if (type->isReference()) {
1.63 expression->setType(type->contained());
1.64 } else if (expression->isIndexExpression()) {
1.65 if (type->isArray())
1.66 expression->setType(type->contained());
1.67 }
1.68 +
1.69 return expression->type();
1.70 }
1.71
1.72 @@ -141,94 +155,93 @@
1.73 return expression->type();
1.74 }
1.75
1.76 -static inline bool
1.77 -TypeCheck(Type *left, Type *right)
1.78 +static inline const char *
1.79 +GetTypeName(Type *type)
1.80 {
1.81 - if (!left || !right)
1.82 - return false;
1.83 -
1.84 - if (left->isPrimitive()) {
1.85 - if (!right->isPrimitive())
1.86 - return false;
1.87 - return left->primitive() == right->primitive();
1.88 - }
1.89 -
1.90 - return false;
1.91 + if (type->isArray())
1.92 + return "array";
1.93 + if (type->isFunction())
1.94 + return "function";
1.95 + if (type->isReference())
1.96 + type = type->contained();
1.97 + if (type->tag())
1.98 + return type->tag();
1.99 + return "int";
1.100 }
1.101
1.102 -static inline bool
1.103 -TypeCheckAssignment(Type *left, Type *right)
1.104 +void
1.105 +SemanticAnalysis::unaryTypeError(AstNode *node, TokenKind token, Type *type)
1.106 {
1.107 - if (!left || !right)
1.108 - return false;
1.109 -
1.110 - if (left->isPrimitive()) {
1.111 - if (!right->isPrimitive())
1.112 - return false;
1.113 - return left->primitive() == right->primitive();
1.114 - }
1.115 -
1.116 - if (left->isArray() != right->isArray())
1.117 - return false;
1.118 + const char *op = TokenNames[token];
1.119 + const char *name = GetTypeName(type);
1.120
1.121 - if (left->levels() != 1 || right->levels() != 1)
1.122 - return false;
1.123 -
1.124 - if (left->elements() == -1 || right->elements() == -1)
1.125 - return false;
1.126 -
1.127 - if (!TypeCheckAssignment(left->contained(), right->contained()))
1.128 - return false;
1.129 -
1.130 - if (left->elements() != right->elements()) {
1.131 - if (left->isCharArray() && (left->elements() >= right->elements()))
1.132 - return true;
1.133 - return false;
1.134 - }
1.135 -
1.136 - return false;
1.137 + cc_.reportError(node->pos(), Message_UnaryTypeError, op, name);
1.138 }
1.139
1.140 -static inline Type *
1.141 -TypeCheckBinary(TokenKind token, Type *left, Type *right)
1.142 +void
1.143 +SemanticAnalysis::binaryTypeError(AstNode *node, TokenKind token, Type *left, Type *right)
1.144 {
1.145 - if (!left || !right)
1.146 - return NULL;
1.147 + const char *op = TokenNames[token];
1.148 + const char *leftName = GetTypeName(left);
1.149 + const char *rightName = GetTypeName(right);
1.150
1.151 + cc_.reportError(node->pos(), Message_BinaryTypeError, op, leftName, rightName);
1.152 +}
1.153 +
1.154 +Type *
1.155 +SemanticAnalysis::typeCheckBinary(AstNode *node, TokenKind token, Type *left, Type *right)
1.156 +{
1.157 if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
1.158 (token >= TOK_ASSIGN_ADD && token <= TOK_ASSIGN_DIV))
1.159 {
1.160 // If either side is a float, the other side must be a float or int.
1.161 if (left->isFloat() || right->isFloat()) {
1.162 - assert(left->isFloat() || left->isInt32());
1.163 - assert(right->isFloat() || right->isInt32());
1.164 - return left->isFloat() ? left : right;
1.165 + Type *floatType = left->isFloat() ? left : right;
1.166 + Type *other = left->isFloat() ? right : left;
1.167 + if (other->isFloat() || (other->isInt32() && !other->tag()))
1.168 + return other;
1.169 }
1.170 }
1.171
1.172 - assert(left->isInt32() && right->isInt32());
1.173 - assert(!left->tag() && !right->tag());
1.174 + if ((!left->isInt32() || left->tag()) ||
1.175 + (!right->isInt32() || right->tag()))
1.176 + {
1.177 + binaryTypeError(node, token, left, right);
1.178 + return NULL;
1.179 + }
1.180 +
1.181 return left;
1.182 }
1.183
1.184 +bool
1.185 +SemanticAnalysis::canTest(AstNode *node, Type *type)
1.186 +{
1.187 + if (type->isArray()) {
1.188 + cc_.reportError(node->pos(), Message_ArrayIsNotBoolean);
1.189 + return false;
1.190 + }
1.191 + return true;
1.192 +}
1.193 +
1.194 Type *
1.195 SemanticAnalysis::visitForLValue(Expression *expression)
1.196 {
1.197 if (expression->isIndexExpression()) {
1.198 - expression->accept(this);
1.199 - if (!expression->type())
1.200 + Type *type = visitAndApplyType(expression);
1.201 + if (!type)
1.202 return NULL;
1.203 - return expression->type()->contained();
1.204 +
1.205 + return type->contained();
1.206 }
1.207
1.208 if (!expression->isNameProxy()) {
1.209 - assert(false);
1.210 + cc_.reportError(expression->pos(), Message_ExpectedLValue);
1.211 return NULL;
1.212 }
1.213
1.214 NameProxy *proxy = expression->toNameProxy();
1.215 if (!proxy->binding()->kind() == BoundName::VARIABLE) {
1.216 - fprintf(stderr, "error\n");
1.217 + cc_.reportError(expression->pos(), Message_ExpectedLValue);
1.218 return NULL;
1.219 }
1.220
1.221 @@ -242,20 +255,32 @@
1.222 }
1.223
1.224 void
1.225 +SemanticAnalysis::visit(NameProxy *name)
1.226 +{
1.227 + name->setType(name->binding()->type());
1.228 +}
1.229 +
1.230 +void
1.231 SemanticAnalysis::visit(Assignment *node)
1.232 {
1.233 - visitForLoad(node->expression());
1.234 + Type *exprType = visitForLoad(node->expression());
1.235 + if (!exprType)
1.236 + return ;
1.237
1.238 // :TODO: use Local
1.239 Type *type = visitForLValue(node->lvalue());
1.240 if (!type)
1.241 return;
1.242 - node->setType(type);
1.243
1.244 - if (node->token() != TOK_ASSIGN)
1.245 - assert(TypeCheckBinary(node->token(), node->type(), node->expression()->type()));
1.246 + if (node->token() != TOK_ASSIGN) {
1.247 + if (!typeCheckBinary(node, node->token(), type, exprType))
1.248 + return;
1.249 + }
1.250
1.251 - assert(TypeCheckAssignment(node->type(), node->expression()->type()));
1.252 + if (!typeCheckAssignment(node, exprType, type, true))
1.253 + return;
1.254 +
1.255 + node->setType(type);
1.256 }
1.257
1.258 void
1.259 @@ -267,13 +292,12 @@
1.260 return;
1.261
1.262 assert(!type->isReference());
1.263 - if (type->isArray()) {
1.264 - // can't a[]++
1.265 - assert(false);
1.266 +
1.267 + if ((!type->isInt32() || (type->isInt32() && type->tag())) && !type->isFloat()) {
1.268 + unaryTypeError(node, node->token(), type);
1.269 return;
1.270 }
1.271
1.272 - assert((type->isInt32() && !type->tag()) || type->isFloat());
1.273 node->setType(type);
1.274 }
1.275
1.276 @@ -283,17 +307,25 @@
1.277 // :TODO: use Local
1.278 Type *left = visitForLoad(node->left());
1.279 Type *right = visitForLoad(node->right());
1.280 + if (!left || !right)
1.281 + return;
1.282
1.283 - Type *result = TypeCheckBinary(node->token(), left, right);
1.284 + Type *result = typeCheckBinary(node, node->token(), left, right);
1.285 + if (!result)
1.286 + return;
1.287 +
1.288 node->setType(result);
1.289 }
1.290
1.291 void
1.292 SemanticAnalysis::visit(ReturnStatement *node)
1.293 {
1.294 - visitForLoad(node->expression());
1.295 + Type *type = visitForLoad(node->expression());
1.296 + if (!type)
1.297 + return;
1.298
1.299 - // :TODO: type check
1.300 + if (!typeCheckAssignment(node, type, function_->returnType(), true))
1.301 + return;
1.302 }
1.303
1.304 void
1.305 @@ -302,13 +334,23 @@
1.306 loopDepth_++;
1.307 if (node->scope())
1.308 scope_ = node->scope();
1.309 +
1.310 if (node->initialization())
1.311 node->initialization()->accept(this);
1.312 - if (node->condition())
1.313 - visitForLoad(node->condition());
1.314 +
1.315 + if (node->condition()) {
1.316 + Type *type = visitForLoad(node->condition());
1.317 + if (!type || !canTest(node->condition(), type)) {
1.318 + loopDepth_--;
1.319 + return;
1.320 + }
1.321 + }
1.322 +
1.323 if (node->update())
1.324 node->update()->accept(this);
1.325 +
1.326 node->body()->accept(this);
1.327 +
1.328 if (node->scope())
1.329 scope_ = scope_->enclosing();
1.330 loopDepth_--;
1.331 @@ -318,7 +360,13 @@
1.332 SemanticAnalysis::visit(WhileStatement *node)
1.333 {
1.334 loopDepth_++;
1.335 - node->condition()->accept(this);
1.336 +
1.337 + Type *type = visitForLoad(node->condition());
1.338 + if (!type || !canTest(node->condition(), type)) {
1.339 + loopDepth_--;
1.340 + return;
1.341 + }
1.342 +
1.343 node->body()->accept(this);
1.344 loopDepth_--;
1.345 }
1.346 @@ -347,61 +395,90 @@
1.347 if (node->postDimensions()) {
1.348 Type *init = NULL;
1.349 if (node->initialization()) {
1.350 - node->initialization()->accept(this);
1.351 - if ((init = node->initialization()->type()) == NULL)
1.352 + if ((init = visitAndApplyType(node->initialization())) == NULL)
1.353 return;
1.354 }
1.355
1.356 if (node->postDimensions()->size() > Type::MAX_UNSAFE_ARRAY_DEPTH) {
1.357 - error();
1.358 + cc_.reportError(node->pos(), Message_MaximumArrayDepth);
1.359 return;
1.360 }
1.361
1.362 // If we have an initializer, make sure it's the same type.
1.363 - if (init) {
1.364 - assert(init->levels() == node->postDimensions()->size());
1.365 + if (init && node->postDimensions()->size() != init->levels()) {
1.366 + cc_.reportError(node->pos(), Message_ArrayInitializerDepth);
1.367 + return;
1.368 }
1.369
1.370 Type *check = init;
1.371 for (size_t i = node->postDimensions()->size() - 1; i < node->postDimensions()->size(); i--) {
1.372 Expression *expr = node->postDimensions()->at(i);
1.373 - visitForLoad(expr);
1.374 + int size = -1;
1.375
1.376 - if (!IsPrimitiveType(expr->type(), PrimitiveType_Int32)) {
1.377 - typeError(expr, "integer");
1.378 - return;
1.379 - }
1.380 + if (expr) {
1.381 + Type *exprType = visitForLoad(expr);
1.382 + if (!exprType)
1.383 + return;
1.384
1.385 - int size = -1;
1.386 - if (expr->isIntegerLiteral()) {
1.387 - size = expr->toIntegerLiteral()->value();
1.388 - if (size <= 0) {
1.389 - error();
1.390 + if (!IsPrimitiveType(exprType, PrimitiveType_Int32)) {
1.391 + cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
1.392 return;
1.393 }
1.394 - if (size >= INT_MAX / sizeof(int)) {
1.395 - error();
1.396 +
1.397 + BoxedPrimitive box;
1.398 + if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
1.399 + size = box.toInt();
1.400 + if (size <= 0) {
1.401 + cc_.reportError(expr->pos(), Message_BadArraySize);
1.402 + return;
1.403 + }
1.404 + if (size >= INT_MAX / sizeof(int)) {
1.405 + cc_.reportError(expr->pos(), Message_ArraySizeTooBig);
1.406 + return;
1.407 + }
1.408 +
1.409 + if (check) {
1.410 + if (check->elements() == -1) {
1.411 + cc_.reportError(expr->pos(), Message_ArraySizeCannotBeDetermined);
1.412 + return;
1.413 + }
1.414 +
1.415 + if (check->isCharArray()) {
1.416 + if (check->elements() > size) {
1.417 + cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
1.418 + return;
1.419 + }
1.420 + } else if (check->elements() != size) {
1.421 + cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, unsigned(i));
1.422 + return;
1.423 + }
1.424 + }
1.425 + } else {
1.426 + if (init) {
1.427 + cc_.reportError(node->pos(), Message_DynamicArrayHasInitializer);
1.428 + return;
1.429 + }
1.430 +
1.431 + // here until we get dynamic array support.
1.432 + cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
1.433 return;
1.434 }
1.435 } else {
1.436 - assert(false);
1.437 + // Infer the size from the initializer.
1.438 + if (!init) {
1.439 + cc_.reportError(node->pos(), Message_ArraySizeNotSpecified);
1.440 + return;
1.441 + }
1.442 + if (init->elements() == -1) {
1.443 + cc_.reportError(node->pos(), Message_ArraySizeCannotBeDetermined);
1.444 + return;
1.445 + }
1.446 + size = init->elements();
1.447 }
1.448
1.449 type = ZONE()->types()->unsafeArray(type, size);
1.450 -
1.451 - if (check) {
1.452 - assert(check->elements() != -1);
1.453 - assert(size != -1);
1.454 -
1.455 - // If we're assigning a string, we're allowed to pad with
1.456 - // zeroes.
1.457 - if (check->isCharArray()) {
1.458 - assert(type->isCharArray());
1.459 - assert(type->elements() >= check->elements());
1.460 - } else {
1.461 - assert(false);
1.462 - }
1.463 - }
1.464 + if (!type)
1.465 + return;
1.466
1.467 if (check)
1.468 check = check->contained();
1.469 @@ -414,10 +491,13 @@
1.470 } else {
1.471 if (node->initialization()) {
1.472 Type *right = visitForLoad(node->initialization());
1.473 - assert(TypeCheck(type, right));
1.474 + if (!right)
1.475 + return;
1.476 + if (!typeCheckAssignment(node, type, right, true))
1.477 + return;
1.478 }
1.479 if (type->primitive() == PrimitiveType_Char) {
1.480 - assert(false);
1.481 + cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
1.482 return;
1.483 }
1.484 }
1.485 @@ -454,6 +534,11 @@
1.486 if (!type)
1.487 return false;
1.488
1.489 + if (type->primitive() == PrimitiveType_Char) {
1.490 + cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
1.491 + return false;
1.492 + }
1.493 +
1.494 if (parameter->reference()) {
1.495 type = ZONE()->types()->getReference(type);
1.496 if (!type)
1.497 @@ -479,60 +564,137 @@
1.498 void
1.499 SemanticAnalysis::visit(FunctionStatement *node)
1.500 {
1.501 + function_ = node->fun()->type();
1.502 scope_ = node->scope();
1.503 -
1.504 - // :TODO: call this ahead of time.
1.505 - if (!preanalyze(node))
1.506 - return;
1.507 -
1.508 node->body()->accept(this);
1.509 scope_ = NULL;
1.510 + function_ = NULL;
1.511 }
1.512
1.513 -// :TODO: use handles
1.514 -static inline bool
1.515 -TypeCheckParameter(Type *given, Type *actual)
1.516 +bool
1.517 +SemanticAnalysis::typeCheckArrayAssignment(AstNode *node, Type *given, Type *actual, bool forAssign)
1.518 {
1.519 - if (actual->isReference()) {
1.520 - if (given->isReference())
1.521 - given = given->contained();
1.522 - return TypeCheck(given, actual->contained());
1.523 + if (!given->isArray()) {
1.524 + cc_.reportError(node->pos(), Message_ExpectedArray);
1.525 + return false;
1.526 + }
1.527 + if (given->levels() != actual->levels()) {
1.528 + cc_.reportError(node->pos(), Message_ArrayDimensionsMismatch);
1.529 + return false;
1.530 + }
1.531 +
1.532 + unsigned level = 0;
1.533 + while (given->isArray()) {
1.534 + if (actual->elements() != -1) {
1.535 + if (forAssign) {
1.536 + if (given->elements() == -1 || actual->elements() == -1) {
1.537 + cc_.reportError(node->pos(), Message_ArraySizeNotKnown);
1.538 + return false;
1.539 + }
1.540 +
1.541 + if (actual->isCharArray()) {
1.542 + // String assignment can have a truncated |given|.
1.543 + if (given->elements() > actual->elements()) {
1.544 + cc_.reportError(node->pos(), Message_ArrayAssignmentTooBig);
1.545 + return false;
1.546 + }
1.547 + } else {
1.548 + if (given->elements() != actual->elements()) {
1.549 + cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
1.550 + return false;
1.551 + }
1.552 + }
1.553 + } else {
1.554 + if (actual->elements() != -1 && given->elements() != actual->elements()) {
1.555 + cc_.reportError(node->pos(), Message_ArrayDimensionSizeMismatch, level);
1.556 + return false;
1.557 + }
1.558 + }
1.559 + }
1.560 + given = given->contained();
1.561 + actual = actual->contained();
1.562 }
1.563
1.564 - return TypeCheck(given, actual);
1.565 + if (given->primitive() != actual->primitive()) {
1.566 + const char *givenTag = given->tag() ? given->tag() : "_";
1.567 + const char *actualTag = given->tag() ? given->tag() : "_";
1.568 + cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
1.569 + return false;
1.570 + }
1.571 +
1.572 + return true;
1.573 +}
1.574 +
1.575 +bool
1.576 +SemanticAnalysis::typeCheckAssignment(AstNode *node, Type *given, Type *actual, bool forAssign)
1.577 +{
1.578 + if (actual->isArray())
1.579 + return typeCheckArrayAssignment(node, given, actual, forAssign);
1.580 +
1.581 + if (given->isArray()) {
1.582 + cc_.reportError(node->pos(), Message_CannotAssignArrayToScalar);
1.583 + return false;
1.584 + }
1.585 +
1.586 + if (!given->isPrimitive() || !actual->primitive()) {
1.587 + cc_.reportError(node->pos(), Message_UnsupportedType);
1.588 + return false;
1.589 + }
1.590 +
1.591 + // The given type may not have been dereferenced.
1.592 + if (given->isReference())
1.593 + given = given->contained();
1.594 + if (actual->isReference())
1.595 + actual = given->contained();
1.596 +
1.597 + if (given->primitive() != actual->primitive()) {
1.598 + const char *givenTag = given->tag() ? given->tag() : "_";
1.599 + const char *actualTag = given->tag() ? given->tag() : "_";
1.600 + cc_.reportError(node->pos(), Message_TagMismatch, actualTag, givenTag);
1.601 + return false;
1.602 + }
1.603 +
1.604 + return true;
1.605 +}
1.606 +
1.607 +bool
1.608 +SemanticAnalysis::typeCheckParameter(AstNode *node, Type *given, Type *actual)
1.609 +{
1.610 + return typeCheckAssignment(node, given, actual, false);
1.611 }
1.612
1.613 void
1.614 SemanticAnalysis::visit(CallExpression *node)
1.615 {
1.616 - visitForLoad(node->callee());
1.617 -
1.618 - // :TODO: use locals
1.619 - Type *type = node->callee()->type();
1.620 + Type *type = visitForLoad(node->callee());
1.621 if (!type)
1.622 return;
1.623
1.624 - assert(type->isFunction());
1.625 - assert(node->arguments()->size() == type->parameters()->length());
1.626 + if (!type->isFunction()) {
1.627 + cc_.reportError(node->pos(), Message_CalleeNotFunction);
1.628 + return;
1.629 + }
1.630 + if (node->arguments()->size() != type->parameters()->length()) {
1.631 + cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
1.632 + return;
1.633 + }
1.634
1.635 for (unsigned i = 0; i < node->arguments()->size(); i++) {
1.636 // Note: we don't compute references unless the callee needs a
1.637 // reference type.
1.638 Expression *expression = node->arguments()->at(i);
1.639 - expression->accept(this);
1.640 -
1.641 - Type *given = expression->type();
1.642 + Type *given = visitAndApplyType(expression);
1.643 if (!given)
1.644 return;
1.645
1.646 // If it's an IndexExpression, we special case the ability to compute
1.647 - // a reference. Maybe we should compute actual Ref types for
1.648 - // IndexExpression?
1.649 + // a reference.
1.650 if (expression->isIndexExpression())
1.651 given = given->contained();
1.652
1.653 - Type *actual = Type::cast(type->parameters()->at(i));
1.654 - assert(TypeCheckParameter(given, actual));
1.655 + Type *actual = type->parameterAt(i);
1.656 + if (!typeCheckParameter(expression, given, actual))
1.657 + return;
1.658
1.659 // If the actual is a reference, and the given is not, we'll need to
1.660 // compute a reference, which may be allocated on the stack.
1.661 @@ -544,7 +706,13 @@
1.662 void
1.663 SemanticAnalysis::visit(IfStatement *node)
1.664 {
1.665 - visitForLoad(node->condition());
1.666 + Type *type = visitForLoad(node->condition());
1.667 + if (!type)
1.668 + return;
1.669 +
1.670 + if (!canTest(node, type))
1.671 + return;
1.672 +
1.673 node->ifTrue()->accept(this);
1.674 if (node->ifFalse())
1.675 node->ifFalse()->accept(this);
1.676 @@ -557,12 +725,15 @@
1.677 Type *left = visitForRef(node->left());
1.678 Type *right = visitForLoad(node->right());
1.679
1.680 - if (!right || !right->isInt32()) {
1.681 - typeError(node->right(), "integer");
1.682 + if (!left || !right)
1.683 + return;
1.684 +
1.685 + if (!right->isInt32()) {
1.686 + cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
1.687 return;
1.688 }
1.689 - if (!left || !left->isArray() || !left->contained()->isPrimitive()) {
1.690 - typeError(node->left(), "array");
1.691 + if (!left->isArray()) {
1.692 + cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
1.693 return;
1.694 }
1.695 node->setType(left);
1.696 @@ -571,8 +742,16 @@
1.697 void
1.698 SemanticAnalysis::visit(EnumStatement *node)
1.699 {
1.700 - // :TODO: test "enum Float { ..."
1.701 + // Forbid the blessed types.
1.702 Name *tag = node->name();
1.703 + if (!strcmp(tag, "Float") ||
1.704 + !strcmp(tag, "String") ||
1.705 + !strcmp(tag, "any") ||
1.706 + !strcmp(tag, "bool"))
1.707 + {
1.708 + cc_.reportError(node->pos(), Message_InvalidEnumName);
1.709 + return;
1.710 + }
1.711
1.712 Type *type = ZONE()->types()->getPrimitiveForTag(tag);
1.713 if (!type)
1.714 @@ -585,8 +764,10 @@
1.715 BoxedPrimitive box = BoxedPrimitive::Int(value);
1.716 if (entry.expr) {
1.717 entry.expr->accept(this);
1.718 - if (!EvaluateForConstant(entry.expr, &box))
1.719 - fprintf(stderr, "expected constant integer expression\n");
1.720 + if (!EvaluateForConstant(entry.expr, &box)) {
1.721 + cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
1.722 + return;
1.723 + }
1.724
1.725 assert(box.type() == PrimitiveType_Int32);
1.726 value = box.toInt();
1.727 @@ -624,11 +805,13 @@
1.728 void
1.729 SemanticAnalysis::visit(BreakStatement *node)
1.730 {
1.731 - assert(loopDepth_ > 0);
1.732 + if (loopDepth_ == 0)
1.733 + cc_.reportError(node->pos(), Message_BreakOutsideLoop);
1.734 }
1.735
1.736 void
1.737 SemanticAnalysis::visit(ContinueStatement *node)
1.738 {
1.739 - assert(loopDepth_ > 0);
1.740 + if (loopDepth_ == 0)
1.741 + cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
1.742 }