1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/OldSema.cpp Sat Nov 17 18:41:01 2012 -0800
1.3 @@ -0,0 +1,1899 @@
1.4 +/* vim: set ts=4 sw=4 tw=99 et:
1.5 + *
1.6 + * Copyright (C) 2012 David Anderson
1.7 + *
1.8 + * This file is part of JITCraft.
1.9 + *
1.10 + * JITCraft is free software: you can redistribute it and/or modify it under
1.11 + * the terms of the GNU General Public License as published by the Free
1.12 + * Software Foundation, either version 3 of the License, or (at your option)
1.13 + * any later version.
1.14 + *
1.15 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
1.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License along with
1.20 + * JITCraft. If not, see http://www.gnu.org/licenses/.
1.21 + */
1.22 +#include <string.h>
1.23 +#include "SemanticAnalysis.h"
1.24 +#include "../Types.h"
1.25 +#include "../Zone.h"
1.26 +#include "../TypeManager.h"
1.27 +#include "../Strings.h"
1.28 +#include "../Box.h"
1.29 +#include "../Array.h"
1.30 +#include "../Heap-inl.h"
1.31 +#include "Scopes.h"
1.32 +#include "NameBinding.h"
1.33 +
1.34 +using namespace ke;
1.35 +
1.36 +SemanticAnalysis::SemanticAnalysis(Zone *zone, CompileContext &cc, ParseTree *tree)
1.37 + : zone_(zone),
1.38 + cc_(cc),
1.39 + tree_(tree),
1.40 + scope_(NULL),
1.41 + loop_(NULL)
1.42 +{
1.43 +}
1.44 +
1.45 +bool
1.46 +SemanticAnalysis::analyze()
1.47 +{
1.48 + assert(false);
1.49 + return false;
1.50 +}
1.51 +
1.52 +
1.53 +#if 0
1.54 +
1.55 +static inline bool
1.56 +IsPrimitiveType(Type *type, PrimitiveType primitive)
1.57 +{
1.58 + if (!type)
1.59 + return false;
1.60 +
1.61 + if (!type->isPrimitive())
1.62 + return false;
1.63 +
1.64 + return primitive == type->primitive();
1.65 +}
1.66 +
1.67 +static inline bool
1.68 +EvaluateBinaryOperation(TokenKind kind, const BoxedPrimitive &left, const BoxedPrimitive &right,
1.69 + BoxedPrimitive *out)
1.70 +{
1.71 + switch (kind) {
1.72 + case TOK_PLUS:
1.73 + *out = BoxedPrimitive::Int(left.toInt() + right.toInt());
1.74 + return true;
1.75 +
1.76 + case TOK_SHL:
1.77 + *out = BoxedPrimitive::Int(left.toInt() << right.toInt());
1.78 + return true;
1.79 +
1.80 + default:
1.81 + return false;
1.82 + }
1.83 +}
1.84 +
1.85 +static inline bool
1.86 +EvaluateUnaryOperation(TokenKind kind, const BoxedPrimitive &inner, BoxedPrimitive *out)
1.87 +{
1.88 + switch (kind) {
1.89 + case TOK_MINUS:
1.90 + *out = BoxedPrimitive::Int(-inner.toInt());
1.91 + return true;
1.92 +
1.93 + default:
1.94 + return false;
1.95 + }
1.96 +}
1.97 +
1.98 +static bool
1.99 +EvaluateForConstant(Expression *expression, BoxedPrimitive *out)
1.100 +{
1.101 + switch (expression->kind()) {
1.102 + case AstNode::kBinaryExpression:
1.103 + {
1.104 + BoxedPrimitive left;
1.105 + BoxedPrimitive right;
1.106 + BinaryExpression *b = expression->toBinaryExpression();
1.107 + if (!EvaluateForConstant(b->left(), &left) ||
1.108 + !EvaluateForConstant(b->right(), &right))
1.109 + {
1.110 + return false;
1.111 + }
1.112 + return EvaluateBinaryOperation(b->token(), left, right, out);
1.113 + }
1.114 +
1.115 + case AstNode::kUnaryExpression:
1.116 + {
1.117 + BoxedPrimitive inner;
1.118 + UnaryExpression *u = expression->toUnaryExpression();
1.119 + if (!EvaluateForConstant(u->expression(), &inner))
1.120 + return false;
1.121 + return EvaluateUnaryOperation(u->token(), inner, out);
1.122 + }
1.123 +
1.124 + case AstNode::kNameProxy:
1.125 + {
1.126 + NameProxy *proxy = expression->toNameProxy();
1.127 + if (proxy->binding()->kind() != BoundName::CONSTANT)
1.128 + return false;
1.129 +
1.130 + NamedConstant *c = proxy->binding()->toNamedConstant();
1.131 + if (!IsPrimitiveType(c->type(), PrimitiveType_Int32))
1.132 + return false;
1.133 +
1.134 + *out = c->value();
1.135 + return true;
1.136 + }
1.137 +
1.138 + case AstNode::kBooleanLiteral:
1.139 + *out = BoxedPrimitive::Int(expression->toBooleanLiteral()->token() == TOK_TRUE ? 1 : 0);
1.140 + return true;
1.141 +
1.142 + case AstNode::kIntegerLiteral:
1.143 + *out = BoxedPrimitive::Int(expression->toIntegerLiteral()->value());
1.144 + return true;
1.145 +
1.146 + default:
1.147 + return false;
1.148 + }
1.149 +}
1.150 +
1.151 +SemanticAnalysis::SemanticAnalysis(Zone *zone, CompileContext &cc, ParseTree *tree)
1.152 + : zone_(zone),
1.153 + cc_(cc),
1.154 + tree_(tree),
1.155 + scope_(NULL),
1.156 + loop_(NULL)
1.157 +{
1.158 +}
1.159 +
1.160 +bool
1.161 +SemanticAnalysis::analyze()
1.162 +{
1.163 + if (cc_.failures())
1.164 + return false;
1.165 +
1.166 + scope_ = tree_->globalScope();
1.167 + assert(scope_->kind() == Scope::GLOBAL);
1.168 +
1.169 + for (size_t i = 0; i < tree_->statements()->length(); i++) {
1.170 + Statement *statement = tree_->statements()->at(i);
1.171 + if (statement->isFunctionStatement()) {
1.172 + FunctionStatement *funstmt = statement->toFunctionStatement();
1.173 + if (!preanalyze(funstmt))
1.174 + return false;
1.175 + } else if (statement->isEnumStatement()) {
1.176 + EnumStatement *enumstmt = statement->toEnumStatement();
1.177 +
1.178 + // We pre-fill global enum types, since they may occur in function
1.179 + // signatures. This should probably be somewhere else...
1.180 + enumstmt->accept(this);
1.181 + } else if (statement->isStructureStatement()) {
1.182 + StructureStatement *node = statement->toStructureStatement();
1.183 + node->accept(this);
1.184 + if (!node->decl()->type())
1.185 + return false;
1.186 + } else if (statement->isFunctionTypeStatement()) {
1.187 + FunctionTypeStatement *node = statement->toFunctionTypeStatement();
1.188 + node->accept(this);
1.189 + if (!node->decl()->type())
1.190 + return false;
1.191 + }
1.192 + }
1.193 +
1.194 + for (size_t i = 0; i < tree_->statements()->length(); i++) {
1.195 + Statement *statement = tree_->statements()->at(i);
1.196 +
1.197 + // We can't double-process these. Maybe put this check somewhere else.
1.198 + if (statement->isEnumStatement())
1.199 + continue;
1.200 +
1.201 + statement->accept(this);
1.202 + }
1.203 +
1.204 + if (!determineLiveFunctions())
1.205 + return false;
1.206 +
1.207 + return !cc_.failures();
1.208 +}
1.209 +
1.210 +bool
1.211 +SemanticAnalysis::determineLiveFunctions()
1.212 +{
1.213 + Vector<NamedFunction *> worklist;
1.214 +
1.215 + // Add the root set.
1.216 + for (size_t i = 0; i < tree_->statements()->length(); i++) {
1.217 + Statement *statement = tree_->statements()->at(i);
1.218 + if (!statement->isFunctionStatement())
1.219 + continue;
1.220 +
1.221 + FunctionStatement *stmt = statement->toFunctionStatement();
1.222 + NamedFunction *fun = stmt->fun();
1.223 + if (!fun->used())
1.224 + continue;
1.225 +
1.226 + for (size_t i = 0; i < fun->usedGlobals()->length(); i++) {
1.227 + NamedFunction *name = fun->usedGlobals()->at(i)->toNamedFunction();
1.228 +
1.229 + // Names in these lists are always unused, however, we mark them
1.230 + // as used while inserting into the work queue, to avoid double-
1.231 + // insertion.
1.232 + if (name->used())
1.233 + continue;
1.234 +
1.235 + if (!worklist.append(name))
1.236 + return false;
1.237 +
1.238 + name->setUsed();
1.239 + }
1.240 + }
1.241 +
1.242 + while (!worklist.empty()) {
1.243 + NamedFunction *fun = worklist.popCopy();
1.244 +
1.245 + for (size_t i = 0; i < fun->usedGlobals()->length(); i++) {
1.246 + NamedFunction *name = fun->usedGlobals()->at(i)->toNamedFunction();
1.247 + if (name->used())
1.248 + continue;
1.249 + if (!worklist.append(name))
1.250 + return false;
1.251 + name->setUsed();
1.252 + }
1.253 + }
1.254 +
1.255 + return true;
1.256 +}
1.257 +
1.258 +Type *
1.259 +SemanticAnalysis::bindType(const SourcePosition &pos, BoundName *name)
1.260 +{
1.261 + if (!name)
1.262 + return zone_->types()->getPrimitive(PrimitiveType_Int32);
1.263 +
1.264 + if (name->kind() == BoundName::UNBOUND) {
1.265 + cc_.reportError(pos, Message_TypeNotFound, name->name()->chars());
1.266 + return NULL;
1.267 + }
1.268 +
1.269 + if (name->kind() != BoundName::TYPE) {
1.270 + cc_.reportError(pos, Message_IdentifierIsNotAType, name->name()->chars());
1.271 + return NULL;
1.272 + }
1.273 +
1.274 + if (!name->type())
1.275 + return NULL;
1.276 +
1.277 + return name->type();
1.278 +}
1.279 +
1.280 +Type *
1.281 +SemanticAnalysis::visitAndApplyType(Expression *expression)
1.282 +{
1.283 + expression->accept(this);
1.284 + return expression->type();
1.285 +}
1.286 +
1.287 +Type *
1.288 +SemanticAnalysis::visitForLoad(Expression *expression)
1.289 +{
1.290 + Local<Type> type(zone_, visitAndApplyType(expression));
1.291 + if (!type)
1.292 + return NULL;
1.293 +
1.294 + if (type->isReference()) {
1.295 + expression->setType(type->contained());
1.296 + } else if (expression->isCallExpression()) {
1.297 + if (type->isVoid()) {
1.298 + CallExpression *call = expression->toCallExpression();
1.299 + cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
1.300 + return NULL;
1.301 + }
1.302 + }
1.303 +
1.304 + return expression->type();
1.305 +}
1.306 +
1.307 +void
1.308 +SemanticAnalysis::unaryTypeError(AstNode *node, TokenKind token, Handle<Type> type)
1.309 +{
1.310 + const char *op = TokenNames[token];
1.311 + const char *name = GetTypeName(type);
1.312 +
1.313 + cc_.reportError(node->pos(), Message_UnaryTypeError, op, name);
1.314 +}
1.315 +
1.316 +void
1.317 +SemanticAnalysis::binaryTypeError(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
1.318 +{
1.319 + const char *op = TokenNames[token];
1.320 + const char *leftName = GetTypeName(left);
1.321 + const char *rightName = GetTypeName(right);
1.322 +
1.323 + cc_.reportError(node->pos(), Message_BinaryTypeError, op, leftName, rightName);
1.324 +}
1.325 +
1.326 +Type *
1.327 +SemanticAnalysis::typeCheckBinary(AstNode *node, TokenKind token, Handle<Type> left, Handle<Type> right)
1.328 +{
1.329 + if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
1.330 + (token >= TOK_ASSIGN_ADD && token <= TOK_ASSIGN_DIV))
1.331 + {
1.332 + // If either side is a float, the other side must be a float or int.
1.333 + if (left->isFloat() || right->isFloat()) {
1.334 + Type *floatType = left->isFloat() ? left : right;
1.335 + Type *other = left->isFloat() ? right : left;
1.336 + if (other->isFloat() || other->isInt32())
1.337 + return floatType;
1.338 + }
1.339 + }
1.340 +
1.341 + if (token == TOK_OR || token == TOK_AND) {
1.342 + if (!canTest(node, left) || !canTest(node, right))
1.343 + return NULL;
1.344 + return zone_->types()->getPrimitive(PrimitiveType_Bool);
1.345 + }
1.346 +
1.347 + if (token >= TOK_EQUALS && token <= TOK_GE) {
1.348 + if ((left->isFloat() || left->isInt32()) &&
1.349 + (right->isFloat() || right->isInt32()))
1.350 + {
1.351 + return zone_->types()->getPrimitive(PrimitiveType_Bool);
1.352 + }
1.353 + binaryTypeError(node, token, left, right);
1.354 + return NULL;
1.355 + }
1.356 +
1.357 + if (!left->isInt32() || !right->isInt32()) {
1.358 + binaryTypeError(node, token, left, right);
1.359 + return NULL;
1.360 + }
1.361 +
1.362 + return left;
1.363 +}
1.364 +
1.365 +bool
1.366 +SemanticAnalysis::canTest(AstNode *node, Handle<Type> type)
1.367 +{
1.368 + if (!type->isPrimitive() && !type->isEnum()) {
1.369 + cc_.reportError(node->pos(), Message_ArrayIsNotBoolean);
1.370 + return false;
1.371 + }
1.372 + return true;
1.373 +}
1.374 +
1.375 +Type *
1.376 +SemanticAnalysis::visitForLValue(Expression *expression)
1.377 +{
1.378 + if (expression->isIndexExpression()) {
1.379 + Type *type = visitAndApplyType(expression);
1.380 + if (!type)
1.381 + return NULL;
1.382 +
1.383 + // if (type->isConst()) {
1.384 + // cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
1.385 + // return NULL;
1.386 + // }
1.387 +
1.388 + return type;
1.389 + }
1.390 +
1.391 + if (expression->isFieldExpression()) {
1.392 + Type *type = visitAndApplyType(expression);
1.393 + if (!type)
1.394 + return NULL;
1.395 +
1.396 + // if (expression->toFieldExpression()->left()->type()->isConst()) {
1.397 + // cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
1.398 + // return NULL;
1.399 + // }
1.400 +
1.401 + return type;
1.402 + }
1.403 +
1.404 + if (!expression->isNameProxy()) {
1.405 + cc_.reportError(expression->pos(), Message_ExpectedLValue);
1.406 + return NULL;
1.407 + }
1.408 +
1.409 + NameProxy *proxy = expression->toNameProxy();
1.410 + if (!proxy->binding()->kind() == BoundName::VARIABLE) {
1.411 + cc_.reportError(expression->pos(), Message_ExpectedLValue);
1.412 + return NULL;
1.413 + }
1.414 +
1.415 + Variable *var = proxy->binding()->toVariable();
1.416 + if (!var->type())
1.417 + return NULL;
1.418 +
1.419 + if (var->type()->isReference()) {
1.420 + if (var->type()->isConst()) {
1.421 + cc_.reportError(expression->pos(), Message_ReferenceIsConstant);
1.422 + return NULL;
1.423 + }
1.424 + return var->type()->contained();
1.425 + }
1.426 + return var->type();
1.427 +}
1.428 +
1.429 +SemanticAnalysis::ControlStatus
1.430 +SemanticAnalysis::visitForControl(Statement *statement)
1.431 +{
1.432 + ControlScope scope(&control_);
1.433 + statement->accept(this);
1.434 + return scope.status();
1.435 +}
1.436 +
1.437 +void
1.438 +SemanticAnalysis::visit(NameProxy *name)
1.439 +{
1.440 + BoundName *binding = name->binding();
1.441 +
1.442 + if (binding->scope()->kind() == Scope::GLOBAL) {
1.443 + if (!function_ || function_->isPublic()) {
1.444 + // Whatever we're referencing must be kept alive no matter what.
1.445 + // As such, we simply mark it used, and don't do anything special.
1.446 + binding->setUsed();
1.447 + } else if (!binding->used() && binding->kind() == BoundName::FUNCTION) {
1.448 + // Otherwise, we're inside a normal stock or function. Since we
1.449 + // don't really know if we've been used yet, we shouldn't
1.450 + // prematurely references as alive. Instead, we keep a list of
1.451 + // which names have been used, so we can mark them later if needed.
1.452 + //
1.453 + // Note that we skip this step if the binding is already in the
1.454 + // root set.
1.455 + if (!function_->addUsedGlobal(binding))
1.456 + return;
1.457 + }
1.458 + }
1.459 +
1.460 + name->setType(binding->type());
1.461 +}
1.462 +
1.463 +void
1.464 +SemanticAnalysis::visit(Assignment *node)
1.465 +{
1.466 + Local<Type> exprType(zone_, visitForLoad(node->expression()));
1.467 + if (!exprType)
1.468 + return ;
1.469 +
1.470 + Local<Type> type(zone_, visitForLValue(node->lvalue()));
1.471 + if (!type)
1.472 + return;
1.473 +
1.474 + if (node->token() != TOK_ASSIGN) {
1.475 + if (!typeCheckBinary(node, node->token(), type, exprType))
1.476 + return;
1.477 + }
1.478 +
1.479 + if (!typeCheckAssignment(node->pos(), exprType, type, true))
1.480 + return;
1.481 +
1.482 + node->setType(type);
1.483 +}
1.484 +
1.485 +void
1.486 +SemanticAnalysis::visit(IncDecExpression *node)
1.487 +{
1.488 + Local<Type> type(zone_, visitForLValue(node->expression()));
1.489 + if (!type)
1.490 + return;
1.491 +
1.492 + assert(!type->isReference());
1.493 +
1.494 + if (!type->isInt32() && !type->isFloat()) {
1.495 + unaryTypeError(node, node->token(), type);
1.496 + return;
1.497 + }
1.498 +
1.499 + node->setType(type);
1.500 +}
1.501 +
1.502 +void
1.503 +SemanticAnalysis::visit(UnaryExpression *node)
1.504 +{
1.505 + Local<Type> type(zone_, visitForLoad(node->expression()));
1.506 + if (!type)
1.507 + return;
1.508 +
1.509 + switch (node->token())
1.510 + {
1.511 + case TOK_NOT:
1.512 + if (!canTest(node->expression(), type))
1.513 + return;
1.514 + type = zone_->types()->getPrimitive(PrimitiveType_Int32);
1.515 + if (!type)
1.516 + return;
1.517 + node->setType(type);
1.518 + break;
1.519 +
1.520 + case TOK_MINUS:
1.521 + if (!type->isFloat() && !type->isInt32()) {
1.522 + unaryTypeError(node, node->token(), type);
1.523 + return;
1.524 + }
1.525 + node->setType(type);
1.526 + break;
1.527 +
1.528 + case TOK_LABEL:
1.529 + {
1.530 + Local<Type> to(zone_, bindType(node->pos(), node->type()));
1.531 + if (!to)
1.532 + return;
1.533 +
1.534 + if ((!type->isFloat() && !type->isInt32OrEnum()) ||
1.535 + (!to->isFloat() && !to->isInt32OrEnum()))
1.536 + {
1.537 + unaryTypeError(node, node->token(), type);
1.538 + return;
1.539 + }
1.540 +
1.541 + node->setType(to);
1.542 + break;
1.543 + }
1.544 +
1.545 + case TOK_SIZEOF:
1.546 + {
1.547 + if (!type->isArray()) {
1.548 + cc_.reportError(node->pos(), Message_SizeofNeedsArray);
1.549 + return;
1.550 + }
1.551 + node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
1.552 + break;
1.553 + }
1.554 +
1.555 + default:
1.556 + assert(node->token() == TOK_TILDE);
1.557 + if (!type->isInt32()) {
1.558 + unaryTypeError(node, node->token(), type);
1.559 + return;
1.560 + }
1.561 + node->setType(type);
1.562 + break;
1.563 + }
1.564 +}
1.565 +
1.566 +void
1.567 +SemanticAnalysis::visit(TernaryExpression *node)
1.568 +{
1.569 + Local<Type> type(zone_, visitForLoad(node->condition()));
1.570 + if (!type)
1.571 + return;
1.572 +
1.573 + if (!canTest(node->condition(), type))
1.574 + return;
1.575 +
1.576 + Local<Type> left(zone_, visitForLoad(node->left()));
1.577 + Local<Type> right(zone_, visitForLoad(node->right()));
1.578 + if (!left || !right)
1.579 + return;
1.580 +
1.581 + if (left != right) {
1.582 + binaryTypeError(node, TOK_QMARK, left, right);
1.583 + return;
1.584 + }
1.585 +}
1.586 +
1.587 +void
1.588 +SemanticAnalysis::visit(BinaryExpression *node)
1.589 +{
1.590 + Local<Type> left(zone_, visitForLoad(node->left()));
1.591 + Local<Type> right(zone_, visitForLoad(node->right()));
1.592 + if (!left || !right)
1.593 + return;
1.594 +
1.595 + Local<Type> result(zone_, typeCheckBinary(node, node->token(), left, right));
1.596 + if (!result)
1.597 + return;
1.598 +
1.599 + node->setType(result);
1.600 +}
1.601 +
1.602 +void
1.603 +SemanticAnalysis::visit(ReturnStatement *node)
1.604 +{
1.605 + // Set this early, so if we error we don't get more errors.
1.606 + control_->returns(Returns_Always);
1.607 +
1.608 + if (!node->expression()) {
1.609 + if (!function_->type()->returnType()->isVoid())
1.610 + cc_.reportError(node->pos(), Message_NotAllPathsReturnValue);
1.611 + return;
1.612 + }
1.613 +
1.614 + Local<Type> type(zone_, visitForLoad(node->expression()));
1.615 + if (!type)
1.616 + return;
1.617 +
1.618 + Local<Type> returnType(zone_, function_->type()->returnType());
1.619 + if (!typeCheckAssignment(node->pos(), type, returnType, true))
1.620 + return;
1.621 +}
1.622 +
1.623 +void
1.624 +SemanticAnalysis::visit(ForStatement *node)
1.625 +{
1.626 + LoopScope loop(&loop_);
1.627 +
1.628 + if (node->scope())
1.629 + scope_ = node->scope();
1.630 +
1.631 + if (node->initialization())
1.632 + node->initialization()->accept(this);
1.633 +
1.634 + if (node->condition()) {
1.635 + Local<Type> type(zone_, visitForLoad(node->condition()));
1.636 + if (!type || !canTest(node->condition(), type)) {
1.637 + return;
1.638 + }
1.639 + }
1.640 +
1.641 + if (node->update())
1.642 + node->update()->accept(this);
1.643 +
1.644 + ControlStatus status = visitForControl(node->body());
1.645 +
1.646 + // If there is a condition, we treat this like a while loop. Otherwise,
1.647 + // join point is only reachable if the loop contains a break. The
1.648 + // termination status doesn't tell us anything yet.
1.649 + if (node->condition() || loop.breaks())
1.650 + control_->merge(status, ControlStatus(false, Returns_Never));
1.651 + else
1.652 + control_->terminate(status.returns());
1.653 +
1.654 + if (node->scope())
1.655 + scope_ = scope_->enclosing();
1.656 +}
1.657 +
1.658 +void
1.659 +SemanticAnalysis::visit(WhileStatement *node)
1.660 +{
1.661 + LoopScope loop(&loop_);
1.662 +
1.663 + Local<Type> type(zone_, visitForLoad(node->condition()));
1.664 + if (!type || !canTest(node->condition(), type)) {
1.665 + return;
1.666 + }
1.667 +
1.668 + ControlStatus status = visitForControl(node->body());
1.669 +
1.670 + // Detect loops that will always have a fork in the control-flow graph.
1.671 + // This will be a |while| loop, or a |do-while| loop whose body does
1.672 + // not terminate.
1.673 + //
1.674 + // For now, we treat these as an |if| regardless of the direction the
1.675 + // branch can take. That means the control-flow is always conditional.
1.676 + if (node->token() == TOK_WHILE ||
1.677 + !status.terminates() ||
1.678 + loop.breaks())
1.679 + {
1.680 + control_->merge(status, ControlStatus(false, Returns_Never));
1.681 + } else {
1.682 + // At this point, we've got a do-while loop with a |return| or
1.683 + // |continue|, meaning that the rest of the block is unreachable.
1.684 + control_->terminate(status.returns());
1.685 + }
1.686 +}
1.687 +
1.688 +void
1.689 +SemanticAnalysis::visit(BlockStatement *node)
1.690 +{
1.691 + if (node->scope())
1.692 + scope_ = node->scope();
1.693 + for (size_t i = 0; i < node->statements()->length(); i++) {
1.694 + Statement *statement = node->statements()->at(i);
1.695 + statement->accept(this);
1.696 + }
1.697 + if (node->scope())
1.698 + scope_ = scope_->enclosing();
1.699 +}
1.700 +
1.701 +static inline bool
1.702 +IsScalarString(Type *type)
1.703 +{
1.704 + if (type->isPrimitive() && type->primitive() == PrimitiveType_Char)
1.705 + return true;
1.706 + if (type->isReference())
1.707 + return IsScalarString(type->contained());
1.708 + return false;
1.709 +}
1.710 +
1.711 +static const int INFER_ARRAY_SIZE = 0;
1.712 +static const int EVAL_ARRAY_SIZE = -1;
1.713 +static const int DYNAMIC_ARRAY_SIZE = -2;
1.714 +
1.715 +bool
1.716 +SemanticAnalysis::evaluateDimensions(ExpressionList *exprs, int dims[MAX_ARRAY_DEPTH])
1.717 +{
1.718 + bool hadEmptySize = false;
1.719 +
1.720 + for (size_t i = 0; i < exprs->length(); i++) {
1.721 + Expression *expr = exprs->at(i);
1.722 + if (!expr) {
1.723 + dims[i] = INFER_ARRAY_SIZE;
1.724 + hadEmptySize = true;
1.725 + continue;
1.726 + }
1.727 +
1.728 + BoxedPrimitive box;
1.729 + if (EvaluateForConstant(expr, &box) && box.type() == PrimitiveType_Int32) {
1.730 + int size = box.toInt();
1.731 + if (size <= 0) {
1.732 + cc_.reportError(expr->pos(), Message_BadArraySize);
1.733 + return false;
1.734 + }
1.735 +
1.736 + dims[i] = size;
1.737 + continue;
1.738 + }
1.739 +
1.740 + Local<Type> exprType(zone_, visitForLoad(expr));
1.741 + if (!exprType)
1.742 + return false;
1.743 +
1.744 + if (!IsPrimitiveType(exprType, PrimitiveType_Int32)) {
1.745 + cc_.reportError(expr->pos(), Message_ArrayDimensionNotInteger);
1.746 + return false;
1.747 + }
1.748 +
1.749 + if (hadEmptySize) {
1.750 + cc_.reportError(expr->pos(), Message_BadDynamicInitializer);
1.751 + return false;
1.752 + }
1.753 +
1.754 + dims[i] = EVAL_ARRAY_SIZE;
1.755 + }
1.756 +
1.757 + return true;
1.758 +}
1.759 +
1.760 +bool
1.761 +SemanticAnalysis::inferFixedArrayLiteral(ArrayLiteral *literal, Handle<Type> contained,
1.762 + int dims[MAX_ARRAY_DEPTH],
1.763 + unsigned dimcount, unsigned level)
1.764 +{
1.765 + if (dims[level] == EVAL_ARRAY_SIZE) {
1.766 + cc_.reportError(literal->pos(), Message_CannotInitializeEvalArray);
1.767 + return false;
1.768 + }
1.769 +
1.770 + if (dims[level] == INFER_ARRAY_SIZE) {
1.771 + // Strings always become dynamic arrays.
1.772 + if (level != dimcount - 1 || !IsPrimitiveType(contained, PrimitiveType_Char))
1.773 + dims[level] = literal->expressions()->length();
1.774 + } else if (dims[level] == DYNAMIC_ARRAY_SIZE) {
1.775 + cc_.reportError(literal->pos(), Message_CannotInitializeEvalArray);
1.776 + return false;
1.777 + } else {
1.778 + if (literal->expressions()->length() != unsigned(dims[level])) {
1.779 + cc_.reportError(literal->pos(), Message_ArrayDimensionSizeMismatch, level + 1);
1.780 + return false;
1.781 + }
1.782 + }
1.783 +
1.784 + if (level == dimcount - 2 && IsPrimitiveType(contained, PrimitiveType_Char)) {
1.785 + for (size_t i = 0; i < literal->expressions()->length(); i++) {
1.786 + Expression *expr = literal->expressions()->at(i);
1.787 + if (!expr->isStringLiteral()) {
1.788 + cc_.reportError(expr->pos(), Message_ExpectedStringLiteral);
1.789 + return false;
1.790 + }
1.791 +
1.792 + StringLiteral *lit = expr->toStringLiteral();
1.793 + if (dims[level + 1] > 0 &&
1.794 + unsigned(dims[level]) < lit->string()->length())
1.795 + {
1.796 + cc_.reportError(lit->pos(), Message_ArrayDimensionSizeMismatch, level + 2);
1.797 + return false;
1.798 + }
1.799 + if (!visitAndApplyType(lit))
1.800 + return false;
1.801 + }
1.802 + } else if (level == dimcount - 1) {
1.803 + Local<Type> type(zone_);
1.804 + for (size_t i = 0; i < literal->expressions()->length(); i++) {
1.805 + Expression *expr = literal->expressions()->at(i);
1.806 + if (expr->isArrayLiteral()) {
1.807 + cc_.reportError(expr->pos(), Message_ArrayDimensionsMismatch);
1.808 + return false;
1.809 + }
1.810 +
1.811 + if ((type = visitAndApplyType(expr)) == NULL)
1.812 + return false;
1.813 +
1.814 + if (!typeCheckAssignment(expr->pos(), type, contained, true))
1.815 + return false;
1.816 + }
1.817 + } else {
1.818 + for (size_t i = 0; i < literal->expressions()->length(); i++) {
1.819 + Expression *expr = literal->expressions()->at(i);
1.820 + if (!expr->isArrayLiteral()) {
1.821 + cc_.reportError(expr->pos(), Message_ArrayDimensionsMismatch);
1.822 + return false;
1.823 + }
1.824 +
1.825 + assert(expr->toArrayLiteral()->isFixed());
1.826 +
1.827 + if (!inferFixedArrayLiteral(expr->toArrayLiteral(),
1.828 + contained,
1.829 + dims,
1.830 + dimcount,
1.831 + level + 1))
1.832 + {
1.833 + return false;
1.834 + }
1.835 + }
1.836 + }
1.837 +
1.838 + return true;
1.839 +}
1.840 +
1.841 +void
1.842 +SemanticAnalysis::visit(VariableDeclaration *node)
1.843 +{
1.844 + Local<Type> type(zone_, bindType(node->pos(), node->type()));
1.845 + if (!type)
1.846 + return;
1.847 +
1.848 +#if 0
1.849 + if (node->postDimensions() || type->isArray()) {
1.850 + // The type could be an array type, so sum the type and postDimensions
1.851 + // together.
1.852 + unsigned dimcount = node->postDimensions()->length();
1.853 + if (type->isArray())
1.854 + dimcount += type->levels();
1.855 + if (dimcount > MAX_ARRAY_DEPTH) {
1.856 + cc_.reportError(node->pos(), Message_MaximumArrayDepth);
1.857 + return;
1.858 + }
1.859 +
1.860 + // Take an initial guess at the array dimension sizes.
1.861 + int dims[MAX_ARRAY_DEPTH];
1.862 + if (!evaluateDimensions(node->postDimensions(), dims))
1.863 + return;
1.864 +
1.865 + // Now add in the type's array dimensions.
1.866 + Local<Type> contained(zone_, type);
1.867 + for (size_t i = node->postDimensions()->length(); i < dimcount; i++) {
1.868 + if (type->isFixedLength())
1.869 + dims[i] = type->fixedLength();
1.870 + else
1.871 + dims[i] = DYNAMIC_ARRAY_SIZE;
1.872 + contained = contained->contained();
1.873 + }
1.874 +
1.875 + Expression *initializer = node->initialization();
1.876 + if (initializer &&
1.877 + initializer->isArrayLiteral() &&
1.878 + initializer->toArrayLiteral()->isFixed())
1.879 + {
1.880 + // Fixed array initializers are special; we use them to infer any
1.881 + // missing information in the original array. We do not evaluate
1.882 + // the array initializer as an expression.
1.883 + if (!inferFixedArrayLiteral(initializer->toArrayLiteral(),
1.884 + contained,
1.885 + dims,
1.886 + dimcount,
1.887 + 0))
1.888 + {
1.889 + return;
1.890 + }
1.891 + initializer = NULL;
1.892 + }
1.893 +
1.894 + // We now have enough information to build the actual array type.
1.895 + // Start from the original dimcount, not the one computed for
1.896 + // initializers.
1.897 + for (size_t i = node->postDimensions()->length() - 1;
1.898 + i < node->postDimensions()->length();
1.899 + i--)
1.900 + {
1.901 + int size = dims[i] > 0
1.902 + ? dims[i]
1.903 + : Type::DYNAMIC_ARRAY_SIZE;
1.904 +
1.905 + type = zone_->types()->newArray(type, size, false);
1.906 + if (!type)
1.907 + return;
1.908 + }
1.909 +
1.910 + // Finally, if we had a non-fixed initializer, make sure it type
1.911 + // checks.
1.912 + if (initializer) {
1.913 + Local<Type> right(zone_, visitForLoad(initializer));
1.914 + if (!right)
1.915 + return;
1.916 +
1.917 + if (!typeCheckAssignment(node->pos(), right, type, true))
1.918 + return;
1.919 + }
1.920 + } else {
1.921 + if (node->initialization()) {
1.922 + Local<Type> right(zone_, visitForLoad(node->initialization()));
1.923 + if (!right)
1.924 + return;
1.925 + if (!typeCheckAssignment(node->pos(), right, type, true))
1.926 + return;
1.927 + }
1.928 +
1.929 + if (type->isPrimitive() && type->primitive() == PrimitiveType_Char) {
1.930 + cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
1.931 + return;
1.932 + }
1.933 + }
1.934 +#endif
1.935 +
1.936 +#if 0
1.937 + // If this variable is stack allocated, we could use the LIFO heap
1.938 + // to allocate it. If that's the case, make sure to reserve a slot
1.939 + // so we can unwind the LIFO heap at the end of this scope.
1.940 + if (!node->variable()->needsHeapAllocation()) {
1.941 + if (type->isArray() || type->isStruct())
1.942 + scope_->setUsesLifoHeap();
1.943 + }
1.944 +
1.945 + node->variable()->setType(type);
1.946 +#endif
1.947 +}
1.948 +
1.949 +void
1.950 +SemanticAnalysis::visit(IntegerLiteral *node)
1.951 +{
1.952 + node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
1.953 +}
1.954 +
1.955 +void
1.956 +SemanticAnalysis::visit(BooleanLiteral *node)
1.957 +{
1.958 + node->setType(zone_->types()->getPrimitive(PrimitiveType_Bool));
1.959 +}
1.960 +
1.961 +void
1.962 +SemanticAnalysis::visit(ExpressionStatement *node)
1.963 +{
1.964 + visitAndApplyType(node->expression());
1.965 +}
1.966 +
1.967 +Box *
1.968 +SemanticAnalysis::evaluateDefaultParameter(Handle<Type> type, Parameter *parameter)
1.969 +{
1.970 + Local<Type> given(zone_, visitForLoad(parameter->initializer()));
1.971 +
1.972 + BoxedPrimitive prim;
1.973 + if (EvaluateForConstant(parameter->initializer(), &prim)) {
1.974 + if (!typeCheckAssignment(parameter->initializer()->pos(), given, type, false))
1.975 + return NULL;
1.976 +
1.977 + if (prim.type() == PrimitiveType_Int32)
1.978 + return Box::New(zone_, given, prim.toInt());
1.979 + return Box::New(zone_, given, prim.toFloat());
1.980 + } else if (parameter->initializer()->isStringLiteral()) {
1.981 + StringLiteral *literal = parameter->initializer()->toStringLiteral();
1.982 +
1.983 + if (!typeCheckAssignment(parameter->initializer()->pos(), given, type, false))
1.984 + return NULL;
1.985 +
1.986 + Local<ArrayMap> map(zone_, ArrayMap::Attach(zone_, given));
1.987 + if (!map)
1.988 + return NULL;
1.989 +
1.990 + Local<Array> array(zone_,
1.991 + Array::NewString(zone_,
1.992 + map,
1.993 + literal->string()->raw(),
1.994 + literal->string()->length(),
1.995 + Heap::Tenure_Old));
1.996 + if (!array)
1.997 + return NULL;
1.998 +
1.999 + return Box::NewObj(zone_, given, array, Heap::Tenure_Old);
1.1000 + }
1.1001 +
1.1002 + cc_.reportError(parameter->initializer()->pos(), Message_MustBeConstant);
1.1003 + return NULL;
1.1004 +}
1.1005 +
1.1006 +bool
1.1007 +SemanticAnalysis::buildFunctionArgs(AstNode *node, TokenKind kind, const FunctionSignature &sig,
1.1008 + FixedArray **argsp, FixedArray **defaultsp)
1.1009 +{
1.1010 + Local<FixedArray> args(zone_, FixedArray::New(zone_, sig.parameters()->length(), Heap::Tenure_Old));
1.1011 + if (!args)
1.1012 + return false;
1.1013 +
1.1014 + Local<FixedArray> defaults(zone_);
1.1015 +
1.1016 + // Apply types to arguments.
1.1017 + for (size_t i = 0; i < sig.parameters()->length(); i++) {
1.1018 + Parameter *parameter = sig.parameters()->at(i);
1.1019 +
1.1020 +#if 0
1.1021 + Local<Type> type(zone_, bindType(parameter->variable()->pos(), parameter->type()));
1.1022 + if (!type)
1.1023 + return false;
1.1024 +
1.1025 + if (parameter->reference()) {
1.1026 + if (parameter->dimensions()) {
1.1027 + cc_.reportError(parameter->variable()->pos(), Message_ArrayCantBeReference);
1.1028 + return false;
1.1029 + }
1.1030 +
1.1031 + if (type->isStruct()) {
1.1032 + cc_.reportError(parameter->variable()->pos(), Message_StructCantBeReference);
1.1033 + return false;
1.1034 + }
1.1035 +
1.1036 + type = zone_->types()->getReference(type, parameter->isConst());
1.1037 + if (!type)
1.1038 + return false;
1.1039 + } else if (parameter->dimensions()) {
1.1040 + type = buildArrayType(type, parameter->dimensions(), parameter->isConst());
1.1041 + if (!type)
1.1042 + return false;
1.1043 +
1.1044 + if (kind == TOK_NATIVE && type->levels() > 1) {
1.1045 + cc_.reportError(parameter->variable()->pos(), Message_MultiArrayInNative);
1.1046 + return false;
1.1047 + }
1.1048 + }
1.1049 +
1.1050 + if (IsScalarString(type)) {
1.1051 + cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
1.1052 + return false;
1.1053 + }
1.1054 +
1.1055 + args->set(zone_, i, type);
1.1056 + parameter->variable()->setType(type);
1.1057 +
1.1058 + if (parameter->initializer()) {
1.1059 + if (!defaults) {
1.1060 + defaults = FixedArray::New(zone_, sig.parameters()->length(), Heap::Tenure_Old);
1.1061 + if (!defaults)
1.1062 + return false;
1.1063 + }
1.1064 +
1.1065 + Local<Box> box(zone_, evaluateDefaultParameter(type, parameter));
1.1066 + if (!box)
1.1067 + return false;
1.1068 +
1.1069 + defaults->set(zone_, i, box);
1.1070 + }
1.1071 +#endif
1.1072 + }
1.1073 +
1.1074 + *argsp = args;
1.1075 + *defaultsp = defaults;
1.1076 +
1.1077 + return true;
1.1078 +}
1.1079 +
1.1080 +void
1.1081 +SemanticAnalysis::visit(FunctionTypeStatement *node)
1.1082 +{
1.1083 + if (node->decl()->type())
1.1084 + return;
1.1085 +
1.1086 + Local<FixedArray> args(zone_);
1.1087 + Local<FixedArray> defaults(zone_);
1.1088 +
1.1089 + const FunctionSignature &sig= node->signature();
1.1090 + if (!buildFunctionArgs(node,
1.1091 + TOK_STOCK,
1.1092 + sig,
1.1093 + args.address(),
1.1094 + defaults.address()))
1.1095 + {
1.1096 + return;
1.1097 + }
1.1098 +
1.1099 +#if 0
1.1100 + Local<Type> returnType(zone_);
1.1101 + if (sig.returnType())
1.1102 + returnType = bindType(node->pos(), sig.returnType());
1.1103 + else
1.1104 + returnType = zone_->types()->getPrimitive(PrimitiveType_Int32);
1.1105 +
1.1106 + if (!returnType)
1.1107 + return;
1.1108 +
1.1109 + Local<Type> funtype(zone_, zone_->types()->newFunction(returnType, args, defaults));
1.1110 + if (!funtype)
1.1111 + return;
1.1112 +
1.1113 + node->decl()->setType(funtype);
1.1114 +#endif
1.1115 +}
1.1116 +
1.1117 +Type *
1.1118 +SemanticAnalysis::buildArrayType(Handle<Type> type, ExpressionList *dimensions, bool isConst)
1.1119 +{
1.1120 + Local<Type> arrayType(zone_, type);
1.1121 +
1.1122 + unsigned dimcount = dimensions->length();
1.1123 + if (type->isArray())
1.1124 + dimcount += type->levels();
1.1125 +
1.1126 + if (dimcount > MAX_ARRAY_DEPTH) {
1.1127 + cc_.reportError(dimensions->at(dimensions->length() - 1)->pos(),
1.1128 + Message_MaximumArrayDepth);
1.1129 + return false;
1.1130 + }
1.1131 +
1.1132 + // Note: constness is sort of bogus. Fix this sometime.
1.1133 + for (size_t i = dimensions->length() - 1; i < dimensions->length(); i--) {
1.1134 + Expression *expr = dimensions->at(i);
1.1135 + if (!expr) {
1.1136 + arrayType = zone_->types()->newArray(arrayType, Type::DYNAMIC_ARRAY_SIZE, isConst);
1.1137 + if (!arrayType)
1.1138 + return NULL;
1.1139 +
1.1140 + continue;
1.1141 + }
1.1142 +
1.1143 + BoxedPrimitive box;
1.1144 + if (!EvaluateForConstant(expr, &box) || box.type() != PrimitiveType_Int32) {
1.1145 + cc_.reportError(expr->pos(), Message_ArraySizeMustBeConstant);
1.1146 + return NULL;
1.1147 + }
1.1148 +
1.1149 + if (box.toInt() <= 0) {
1.1150 + cc_.reportError(expr->pos(), Message_BadArraySize);
1.1151 + return NULL;
1.1152 + }
1.1153 +
1.1154 + arrayType = zone_->types()->newArray(arrayType, box.toInt(), isConst);
1.1155 + if (!arrayType)
1.1156 + return NULL;
1.1157 + }
1.1158 +
1.1159 + return arrayType;
1.1160 +}
1.1161 +
1.1162 +bool
1.1163 +SemanticAnalysis::preanalyze(FunctionStatement *node)
1.1164 +{
1.1165 + Local<FixedArray> args(zone_);
1.1166 + Local<FixedArray> defaults(zone_);
1.1167 +
1.1168 + const FunctionSignature &sig = node->signature();
1.1169 + if (!buildFunctionArgs(node,
1.1170 + node->fun()->token(),
1.1171 + sig,
1.1172 + args.address(),
1.1173 + defaults.address()))
1.1174 + {
1.1175 + return false;
1.1176 + }
1.1177 +
1.1178 +#if 0
1.1179 + Local<Type> returnType(zone_);
1.1180 + if (sig.returnType() ||
1.1181 + node->hasExplicitReturn() ||
1.1182 + node->fun()->isNative())
1.1183 + {
1.1184 + returnType = bindType(node->pos(), sig.returnType());
1.1185 + } else {
1.1186 + returnType = zone_->types()->getVoid();
1.1187 + }
1.1188 + if (!returnType)
1.1189 + return false;
1.1190 +
1.1191 + if (sig.returnDimensions()) {
1.1192 + returnType = buildArrayType(returnType, sig.returnDimensions(), false);
1.1193 + if (!returnType)
1.1194 + return false;
1.1195 + }
1.1196 +
1.1197 + if (IsScalarString(returnType)) {
1.1198 + cc_.reportError(node->pos(), Message_CannotDeclareStringCell);
1.1199 + return false;
1.1200 + }
1.1201 +
1.1202 + Local<Type> funtype(zone_);
1.1203 + if (node->fun()->isNative())
1.1204 + funtype = zone_->types()->newNative(returnType, args, defaults, node->fun()->isNativeVariadic());
1.1205 + else
1.1206 + funtype = zone_->types()->newFunction(returnType, args, defaults);
1.1207 + if (!funtype)
1.1208 + return false;
1.1209 +
1.1210 + // If the function already has a type, it was forward declared before, and
1.1211 + // now this is our chance to type check the second declaration.
1.1212 + if (node->fun()->type()) {
1.1213 + Local<Type> forward(zone_, node->fun()->type());
1.1214 + if (!Type::Compare(funtype, forward)) {
1.1215 + cc_.reportError(node->pos(), Message_ForwardDeclareMismatches);
1.1216 + return false;
1.1217 + }
1.1218 + node->fun()->setForwardType(forward);
1.1219 + }
1.1220 +
1.1221 + node->fun()->setType(funtype);
1.1222 +#endif
1.1223 +
1.1224 + return true;
1.1225 +}
1.1226 +
1.1227 +void
1.1228 +SemanticAnalysis::visit(FunctionStatement *node)
1.1229 +{
1.1230 + function_ = node->fun();
1.1231 + scope_ = node->scope();
1.1232 +
1.1233 + ControlScope control(&control_);
1.1234 + if (node->body()) {
1.1235 + node->body()->accept(this);
1.1236 +
1.1237 + ControlStatus status = control.status();
1.1238 + if (status.returns() == Returns_Sometimes) {
1.1239 + cc_.reportError(node->pos(), Message_NotAllPathsReturnValue);
1.1240 + } else if (status.returns() == Returns_Never) {
1.1241 + if (!function_->type()->returnType()->isVoid())
1.1242 + cc_.reportError(node->pos(), Message_MissingReturnValue);
1.1243 + }
1.1244 + }
1.1245 +
1.1246 + scope_ = NULL;
1.1247 + function_ = NULL;
1.1248 +}
1.1249 +
1.1250 +void
1.1251 +SemanticAnalysis::typeMismatch(const SourcePosition &pos, Handle<Type> actual, Handle<Type> given)
1.1252 +{
1.1253 + cc_.reportError(pos, Message_TypeMismatch,
1.1254 + GetTypeName(actual),
1.1255 + GetTypeName(given));
1.1256 +}
1.1257 +
1.1258 +bool
1.1259 +SemanticAnalysis::typeCheckArrayAssignment(const SourcePosition &pos, Handle<Type> argGiven,
1.1260 + Handle<Type> argActual, bool forAssign)
1.1261 +{
1.1262 + Local<Type> actual(zone_, argActual);
1.1263 + Local<Type> given(zone_, argGiven);
1.1264 +
1.1265 + if (!given->isArray()) {
1.1266 + cc_.reportError(pos, Message_ExpectedArray);
1.1267 + return false;
1.1268 + }
1.1269 + if (given->levels() != actual->levels()) {
1.1270 + cc_.reportError(pos, Message_ArrayDimensionsMismatch);
1.1271 + return false;
1.1272 + }
1.1273 +
1.1274 + unsigned level = 1;
1.1275 + while (given->isArray()) {
1.1276 + if (actual->isFixedLength()) {
1.1277 + if (forAssign) {
1.1278 + if (!given->isFixedLength()) {
1.1279 + cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
1.1280 + return false;
1.1281 + }
1.1282 +
1.1283 + if (actual->isCharArray()) {
1.1284 + // String assignment can have a truncated |given|.
1.1285 + if (given->fixedLength() > actual->fixedLength()) {
1.1286 + cc_.reportError(pos, Message_ArrayAssignmentTooBig);
1.1287 + return false;
1.1288 + }
1.1289 + } else {
1.1290 + if (given->fixedLength() != actual->fixedLength()) {
1.1291 + cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
1.1292 + return false;
1.1293 + }
1.1294 + }
1.1295 + }
1.1296 + } else if (given->isFixedLength()) {
1.1297 + // We do not allow assignments in the form:
1.1298 + // [][] = [][Y]
1.1299 + //
1.1300 + // Otherwise, the following code could break the size guarantees
1.1301 + // of the right-hand side:
1.1302 + //
1.1303 + // new x[][5];
1.1304 + // new y[][];
1.1305 + // new z[3];
1.1306 + //
1.1307 + // y = x;
1.1308 + // y[0] = z;
1.1309 + //
1.1310 + // Now |x[0]| contains a 4-length array.
1.1311 + if (level > 1) {
1.1312 + cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
1.1313 + return false;
1.1314 + }
1.1315 + }
1.1316 + given = given->contained();
1.1317 + actual = actual->contained();
1.1318 + level++;
1.1319 + }
1.1320 +
1.1321 + return typeCheckAssignment(pos, given, actual, forAssign);
1.1322 +}
1.1323 +
1.1324 +bool
1.1325 +SemanticAnalysis::typeCheckAssignment(const SourcePosition &pos, Handle<Type> argGiven,
1.1326 + Handle<Type> argActual, bool forAssign)
1.1327 +{
1.1328 + Local<Type> actual(zone_, argActual);
1.1329 + Local<Type> given(zone_, argGiven);
1.1330 +
1.1331 + if (actual->isArray())
1.1332 + return typeCheckArrayAssignment(pos, given, actual, forAssign);
1.1333 +
1.1334 + if (given->isArray()) {
1.1335 + cc_.reportError(pos, Message_CannotAssignArrayToScalar);
1.1336 + return false;
1.1337 + }
1.1338 +
1.1339 + // The given type may not have been dereferenced.
1.1340 + if (given->isReference())
1.1341 + given = given->contained();
1.1342 + if (actual->isReference())
1.1343 + actual = actual->contained();
1.1344 +
1.1345 + // We coerce unchecked to a few things.
1.1346 + if (actual->isUnchecked() || given->isUnchecked()) {
1.1347 + Type *check = actual->isUnchecked() ? given : actual;
1.1348 + if (check->isUnchecked() ||
1.1349 + check->isEnum() ||
1.1350 + check->isInt32() ||
1.1351 + check->isBool() ||
1.1352 + check->isFloat())
1.1353 + {
1.1354 + return true;
1.1355 + }
1.1356 + typeMismatch(pos, actual, given);
1.1357 + return false;
1.1358 + }
1.1359 +
1.1360 + if (given->isFunction() && actual->isFunction()) {
1.1361 + if (!Type::Compare(given, actual)) {
1.1362 + typeMismatch(pos, actual, given);
1.1363 + return false;
1.1364 + }
1.1365 + return true;
1.1366 + }
1.1367 +
1.1368 + if (actual->isEnum()) {
1.1369 + if (!given->isEnum() || actual != given) {
1.1370 + typeMismatch(pos, actual, given);
1.1371 + return false;
1.1372 + }
1.1373 + return true;
1.1374 + }
1.1375 +
1.1376 + if (actual->isStruct()) {
1.1377 + if (!given->isStruct() || actual != given) {
1.1378 + typeMismatch(pos, actual, given);
1.1379 + return false;
1.1380 + }
1.1381 + return true;
1.1382 + }
1.1383 +
1.1384 + if (given->isEnum() || given->isFunction() || given->isStruct()) {
1.1385 + typeMismatch(pos, actual, given);
1.1386 + return false;
1.1387 + }
1.1388 +
1.1389 + // This coercion is trivial.
1.1390 + if (given->isBool() && actual->isInt32())
1.1391 + return true;
1.1392 +
1.1393 + if (given->primitive() != actual->primitive()) {
1.1394 + typeMismatch(pos, actual, given);
1.1395 + return false;
1.1396 + }
1.1397 +
1.1398 + return true;
1.1399 +}
1.1400 +
1.1401 +bool
1.1402 +SemanticAnalysis::typeCheckParameter(AstNode *node, Handle<Type> given, Handle<Type> actual)
1.1403 +{
1.1404 + return typeCheckAssignment(node->pos(), given, actual, false);
1.1405 +}
1.1406 +
1.1407 +bool
1.1408 +SemanticAnalysis::checkArgumentCount(Handle<Type> type, unsigned actual)
1.1409 +{
1.1410 + if (type->parameters()->length() == actual)
1.1411 + return true;
1.1412 +
1.1413 + if (actual > type->parameters()->length()) {
1.1414 + if (!type->isNative() || !type->isNativeVariadic())
1.1415 + return false;
1.1416 + return true;
1.1417 + }
1.1418 +
1.1419 + if (!type->defaults())
1.1420 + return false;
1.1421 +
1.1422 + // Missing arguments. See if there's a default argument for each missing
1.1423 + // actual.
1.1424 + for (unsigned i = actual; i < type->parameters()->length(); i++) {
1.1425 + if (!type->defaults()->at(i))
1.1426 + return false;
1.1427 + }
1.1428 +
1.1429 + return true;
1.1430 +}
1.1431 +
1.1432 +void
1.1433 +SemanticAnalysis::visit(CallExpression *node)
1.1434 +{
1.1435 + Local<Type> type(zone_, visitForLoad(node->callee()));
1.1436 + if (!type)
1.1437 + return;
1.1438 +
1.1439 + if (!type->isFunction()) {
1.1440 + cc_.reportError(node->pos(), Message_CalleeNotFunction);
1.1441 + return;
1.1442 + }
1.1443 +
1.1444 + if (!checkArgumentCount(type, node->arguments()->length())) {
1.1445 + cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
1.1446 + return;
1.1447 + }
1.1448 +
1.1449 + // NamedFunction *fun = node->callee()->toNameProxy()->binding()->toNamedFunction();
1.1450 + // if (fun->isForward()) {
1.1451 + // cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
1.1452 + // return;
1.1453 + // }
1.1454 +
1.1455 + for (unsigned i = 0; i < node->arguments()->length(); i++) {
1.1456 + // Note: we don't compute references unless the callee needs a
1.1457 + // reference type.
1.1458 + Expression *expression = node->arguments()->at(i);
1.1459 + Local<Type> given(zone_, visitAndApplyType(expression));
1.1460 + if (!given)
1.1461 + return;
1.1462 +
1.1463 + // Since we skip a load, check for a call expression that returns void.
1.1464 + if (given->isVoid()) {
1.1465 + assert(expression->isCallExpression());
1.1466 + CallExpression *call = expression->toCallExpression();
1.1467 + cc_.reportError(call->callee()->pos(), Message_FunctionDoesNotReturnValue);
1.1468 + return;
1.1469 + }
1.1470 +
1.1471 + bool mustComputeReference;
1.1472 + if (i >= type->parameters()->length()) {
1.1473 + // Special handling for natives. Arguments past the formal must
1.1474 + // always have references computed. However, arrays are already
1.1475 + // references for natives.
1.1476 + assert(type->isNative() && type->isNativeVariadic());
1.1477 + mustComputeReference = !given->isReference() && !given->isArray();
1.1478 + } else {
1.1479 + Local<Type> actual(zone_, type->parameterAt(i));
1.1480 +
1.1481 + if (expression->isIndexExpression()) {
1.1482 + // Disabled until we can make it work.
1.1483 +#if 0
1.1484 + if (actual->isArray()) {
1.1485 + // We special case the ability to pass x[y] into x[], which
1.1486 + // creates an array slice. We only do this if we know the
1.1487 + // assignment would otherwise not type-check.
1.1488 + IndexExpression *index = expression->toIndexExpression();
1.1489 + if (index->left()->type()->levels() == actual->levels())
1.1490 + given = index->left()->type();
1.1491 + } else
1.1492 +#endif
1.1493 + if (actual->isReference()) {
1.1494 + cc_.reportError(expression->pos(), Message_CannotComputeIndexRef);
1.1495 + return;
1.1496 + }
1.1497 + }
1.1498 +
1.1499 + if (!typeCheckParameter(expression, given, actual))
1.1500 + return;
1.1501 + mustComputeReference = actual->isReference() && !given->isReference();
1.1502 + }
1.1503 +
1.1504 + // If the actual is a reference, and the given is not, we'll need to
1.1505 + // compute a reference, which may be allocated on the stack.
1.1506 + if (mustComputeReference)
1.1507 + scope_->setUsesLifoHeap();
1.1508 + }
1.1509 +
1.1510 + node->setType(type->returnType());
1.1511 +}
1.1512 +
1.1513 +void
1.1514 +SemanticAnalysis::ControlScope::inherit(const ControlStatus &other)
1.1515 +{
1.1516 + if (other.returns() < status().returns())
1.1517 + return;
1.1518 +
1.1519 + if (other.terminates())
1.1520 + terminate(other.returns());
1.1521 + else
1.1522 + returns(other.returns());
1.1523 +}
1.1524 +
1.1525 +void
1.1526 +SemanticAnalysis::ControlScope::merge(const ControlStatus &left, const ControlStatus &right)
1.1527 +{
1.1528 + // If both sides terminate in a return, we consider this a return as well.
1.1529 + if (left.returns() == Returns_Always && right.returns() == Returns_Always) {
1.1530 + terminate(Returns_Always);
1.1531 + return;
1.1532 + }
1.1533 +
1.1534 + ReturnStatus status = (left.returns() == Returns_Never && right.returns() == Returns_Never)
1.1535 + ? Returns_Never
1.1536 + : Returns_Sometimes;
1.1537 +
1.1538 + if (left.terminates() && right.terminates())
1.1539 + terminate(status);
1.1540 + else
1.1541 + returns(status);
1.1542 +}
1.1543 +
1.1544 +void
1.1545 +SemanticAnalysis::visit(IfStatement *node)
1.1546 +{
1.1547 + Local<Type> type(zone_, visitForLoad(node->condition()));
1.1548 + if (!type)
1.1549 + return;
1.1550 +
1.1551 + if (!canTest(node, type))
1.1552 + return;
1.1553 +
1.1554 + ControlStatus trueBranch = visitForControl(node->ifTrue());
1.1555 + ControlStatus falseBranch = ControlStatus(false, Returns_Never);
1.1556 +
1.1557 + if (node->ifFalse())
1.1558 + falseBranch = visitForControl(node->ifFalse());
1.1559 +
1.1560 + control_->merge(trueBranch, falseBranch);
1.1561 +}
1.1562 +
1.1563 +void
1.1564 +SemanticAnalysis::visit(IndexExpression *node)
1.1565 +{
1.1566 + Local<Type> left(zone_, visitForLoad(node->left()));
1.1567 + Local<Type> right(zone_, visitForLoad(node->right()));
1.1568 +
1.1569 + if (!left || !right)
1.1570 + return;
1.1571 +
1.1572 + if (!right->isInt32() && !right->isEnum()) {
1.1573 + cc_.reportError(node->right()->pos(), Message_IndexMustBeInteger);
1.1574 + return;
1.1575 + }
1.1576 + if (!left->isArray()) {
1.1577 + cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
1.1578 + return;
1.1579 + }
1.1580 +
1.1581 + // Note: char arrays are automatically up-casted to return an int32.
1.1582 + if (left->isCharArray())
1.1583 + node->setType(zone_->types()->getPrimitive(PrimitiveType_Int32));
1.1584 + else
1.1585 + node->setType(left->contained());
1.1586 +}
1.1587 +
1.1588 +void
1.1589 +SemanticAnalysis::visit(FieldExpression *node)
1.1590 +{
1.1591 + Local<Type> left(zone_, visitForLoad(node->left()));
1.1592 + if (!left)
1.1593 + return;
1.1594 +
1.1595 + if (!left->isStruct()) {
1.1596 + cc_.reportError(node->pos(), Message_PropertyNotFound, node->field()->chars(),
1.1597 + GetTypeName(left));
1.1598 + return;
1.1599 + }
1.1600 +
1.1601 + Local<String> field(zone_, node->field());
1.1602 +
1.1603 + unsigned offset;
1.1604 + Local<Descriptor> desc(zone_, left->lookupField(field, &offset));
1.1605 + if (!desc) {
1.1606 + cc_.reportError(node->pos(), Message_PropertyNotFound, node->field()->chars(),
1.1607 + GetTypeName(left));
1.1608 + return;
1.1609 + }
1.1610 +
1.1611 + node->setFieldIndex(offset);
1.1612 + node->setType(desc->type());
1.1613 +}
1.1614 +
1.1615 +void
1.1616 +SemanticAnalysis::visit(EnumStatement *node)
1.1617 +{
1.1618 + Local<String> name(zone_, node->name());
1.1619 + Local<Type> type(zone_);
1.1620 + if (name)
1.1621 + type = zone_->types()->newEnum(name);
1.1622 + else
1.1623 + type = zone_->types()->getPrimitive(PrimitiveType_Int32);
1.1624 +
1.1625 + if (!type)
1.1626 + return;
1.1627 +
1.1628 + if (node->decl())
1.1629 + node->decl()->setType(type);
1.1630 +
1.1631 + int value = 0;
1.1632 + for (size_t i = 0; i < node->entries()->length(); i++) {
1.1633 + EnumStatement::Entry &entry = node->entries()->at(i);
1.1634 +
1.1635 + BoxedPrimitive box = BoxedPrimitive::Int(value);
1.1636 + if (entry.expr) {
1.1637 + entry.expr->accept(this);
1.1638 + if (!EvaluateForConstant(entry.expr, &box) || box.type() != PrimitiveType_Int32) {
1.1639 + cc_.reportError(entry.expr->pos(), Message_EnumFieldNotConstant);
1.1640 + return;
1.1641 + }
1.1642 +
1.1643 + assert(box.type() == PrimitiveType_Int32);
1.1644 + value = box.toInt();
1.1645 + }
1.1646 +
1.1647 +#if 0
1.1648 + entry.name->set(type, box);
1.1649 +#endif
1.1650 + value++;
1.1651 + }
1.1652 +}
1.1653 +
1.1654 +static int
1.1655 +SortCaseIntValues(const void *p1, const void *p2)
1.1656 +{
1.1657 + CaseValue *v1 = (CaseValue *)p1;
1.1658 + CaseValue *v2 = (CaseValue *)p2;
1.1659 +
1.1660 + return v1->box.toInt() - v2->box.toInt();
1.1661 +}
1.1662 +
1.1663 +void
1.1664 +SemanticAnalysis::visit(SwitchStatement *node)
1.1665 +{
1.1666 + Local<Type> caseType(zone_, visitForLoad(node->expression()));
1.1667 + if (!caseType)
1.1668 + return;
1.1669 +
1.1670 + if (!caseType->isEnum() && !caseType->isInt32()) {
1.1671 + cc_.reportError(node->pos(), Message_CaseMustBeInteger);
1.1672 + return;
1.1673 + }
1.1674 +
1.1675 + PoolList<CaseValue> *values = new (zone_->pool()) PoolList<CaseValue>();
1.1676 + ControlStatus status = ControlStatus(false, Returns_Never);
1.1677 +
1.1678 + Local<Type> check(zone_);
1.1679 + for (size_t i = 0; i < node->cases()->length(); i++) {
1.1680 + Case *c = node->cases()->at(i);
1.1681 +
1.1682 + check = visitForLoad(c->expression());
1.1683 + if (!check)
1.1684 + return;
1.1685 +
1.1686 + if (!typeCheckAssignment(c->expression()->pos(), check, caseType, false))
1.1687 + return;
1.1688 +
1.1689 + CaseValue v(i);
1.1690 + if (!EvaluateForConstant(c->expression(), &v.box)) {
1.1691 + cc_.reportError(c->expression()->pos(), Message_CaseMustBeConstant);
1.1692 + return;
1.1693 + }
1.1694 + if (!values->append(v))
1.1695 + return;
1.1696 +
1.1697 + if (c->others()) {
1.1698 + for (size_t j = 0; j < c->others()->length(); j++) {
1.1699 + Expression *expr = c->others()->at(j);
1.1700 + check = visitForLoad(expr);
1.1701 + if (!check)
1.1702 + return;
1.1703 +
1.1704 + if (!typeCheckAssignment(expr->pos(), check, caseType, false))
1.1705 + return;
1.1706 +
1.1707 + CaseValue v(i);
1.1708 + if (!EvaluateForConstant(expr, &v.box)) {
1.1709 + cc_.reportError(expr->pos(), Message_CaseMustBeConstant);
1.1710 + return;
1.1711 + }
1.1712 + if (!values->append(v))
1.1713 + return;
1.1714 + }
1.1715 + }
1.1716 +
1.1717 + ControlStatus latest = visitForControl(c->statement());
1.1718 +
1.1719 + if (i != 0)
1.1720 + control_->merge(status, latest);
1.1721 +
1.1722 + status = latest;
1.1723 + }
1.1724 +
1.1725 + if (node->defaultCase()) {
1.1726 + ControlStatus latest = visitForControl(node->defaultCase());
1.1727 +
1.1728 + if (node->cases()->length()) {
1.1729 + // If we had any other cases, we must merge.
1.1730 + control_->merge(status, latest);
1.1731 + } else {
1.1732 + // Otherwise, control-flow always flows through here.
1.1733 + control_->inherit(latest);
1.1734 + }
1.1735 + } else if (node->cases()->length()) {
1.1736 + control_->merge(status, ControlStatus(false, Returns_Never));
1.1737 + }
1.1738 +
1.1739 + if (values->length() > 1) {
1.1740 + qsort(values->buffer(), values->length(), sizeof(CaseValue), SortCaseIntValues);
1.1741 +
1.1742 + for (size_t i = 1; i < values->length(); i++) {
1.1743 + CaseValue &prev = values->at(i - 1);
1.1744 + CaseValue &cur = values->at(i);
1.1745 + if (prev.box.toInt() == cur.box.toInt()) {
1.1746 + cc_.reportError(node->cases()->at(cur.statement)->expression()->pos(), Message_CaseHasSameValue);
1.1747 + return;
1.1748 + }
1.1749 + }
1.1750 + }
1.1751 +
1.1752 + node->setCaseValueList(values);
1.1753 +}
1.1754 +
1.1755 +void
1.1756 +SemanticAnalysis::visit(StructureStatement *node)
1.1757 +{
1.1758 +#if 0
1.1759 + // If this node already has a type, it was pre-analyzed, so skip it.
1.1760 + if (node->decl()->type())
1.1761 + return;
1.1762 +
1.1763 + FieldList *fields = node->fields();
1.1764 + Local<FixedArray> desctable(zone_, FixedArray::New(zone_, fields->length(), Heap::Tenure_Old));
1.1765 + if (!desctable)
1.1766 + return;
1.1767 +
1.1768 + Vector<unsigned> composedList;
1.1769 + StructureBufferBuilder builder;
1.1770 +
1.1771 + Local<Type> type(zone_);
1.1772 + Local<String> name(zone_);
1.1773 + Local<Descriptor> desc(zone_);
1.1774 + for (size_t i = 0; i < fields->length(); i++) {
1.1775 + StructureStatement::Field *field = fields->at(i);
1.1776 +
1.1777 + type = bindType(field->pos(), field->type());
1.1778 + if (!type)
1.1779 + return;
1.1780 +
1.1781 + if (field->dimensions()) {
1.1782 + type = buildArrayType(type, field->dimensions(), false);
1.1783 + if (!type)
1.1784 + return;
1.1785 +
1.1786 + if (!ArrayMap::Attach(zone_, type))
1.1787 + return;
1.1788 + }
1.1789 +
1.1790 + if (IsScalarString(type)) {
1.1791 + cc_.reportError(field->pos(), Message_CannotDeclareStringCell);
1.1792 + return;
1.1793 + }
1.1794 +
1.1795 + unsigned offset;
1.1796 + if (!builder.add(type, &offset))
1.1797 + return;
1.1798 +
1.1799 + name = field->name();
1.1800 + desc = Descriptor::New(zone_, name, type, offset);
1.1801 + if (!desc)
1.1802 + return;
1.1803 +
1.1804 + desctable->set(zone_, i, desc);
1.1805 +
1.1806 + if (type->isStruct() || type->isArray()) {
1.1807 + if (!composedList.append(i))
1.1808 + return;
1.1809 + }
1.1810 + }
1.1811 +
1.1812 + Local<FixedArray> composed(zone_);
1.1813 + if (composedList.length()) {
1.1814 + composed = FixedArray::New(zone_, composedList.length(), Heap::Tenure_Old);
1.1815 + if (!composed)
1.1816 + return;
1.1817 +
1.1818 + for (unsigned i = 0; i < composedList.length(); i++)
1.1819 + composed->set(zone_, i, desctable->at(i));
1.1820 + }
1.1821 +
1.1822 + Local<StructMap> map(zone_, StructMap::New(zone_, builder, composed));
1.1823 + if (!map)
1.1824 + return;
1.1825 +
1.1826 + name = node->decl()->name();
1.1827 + type = zone_->types()->newStruct(name, desctable, map);
1.1828 + if (!type)
1.1829 + return;
1.1830 +
1.1831 + map->setType(type);
1.1832 + node->decl()->setType(type);
1.1833 +#endif
1.1834 +}
1.1835 +
1.1836 +void
1.1837 +SemanticAnalysis::visit(StringLiteral *node)
1.1838 +{
1.1839 + Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Char));
1.1840 + if (!type)
1.1841 + return;
1.1842 +
1.1843 + type = Type::NewArray(zone_, type, node->string()->length() + 1, true);
1.1844 + if (!type)
1.1845 + return;
1.1846 +
1.1847 + node->setType(type);
1.1848 +}
1.1849 +
1.1850 +void
1.1851 +SemanticAnalysis::visit(FloatLiteral *node)
1.1852 +{
1.1853 + Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
1.1854 + if (!type)
1.1855 + return;
1.1856 +
1.1857 + node->setType(type);
1.1858 +}
1.1859 +
1.1860 +void
1.1861 +SemanticAnalysis::visit(BreakStatement *node)
1.1862 +{
1.1863 + if (!loop_) {
1.1864 + cc_.reportError(node->pos(), Message_BreakOutsideLoop);
1.1865 + return;
1.1866 + }
1.1867 +
1.1868 + // Note: ignore breaks that occur in unreachable control-flow.
1.1869 + if (!control_->status().terminates())
1.1870 + loop_->addBreak();
1.1871 +
1.1872 + control_->terminate(Returns_Never);
1.1873 +}
1.1874 +
1.1875 +void
1.1876 +SemanticAnalysis::visit(ContinueStatement *node)
1.1877 +{
1.1878 + if (!loop_) {
1.1879 + cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
1.1880 + return;
1.1881 + }
1.1882 +
1.1883 + // Note: ignore continues that occur in unreachable control-flow.
1.1884 + if (!control_->status().terminates())
1.1885 + loop_->addContinue();
1.1886 +
1.1887 + control_->terminate(Returns_Never);
1.1888 +}
1.1889 +
1.1890 +void
1.1891 +SemanticAnalysis::visit(ArrayLiteral *node)
1.1892 +{
1.1893 + // We should never visit this.
1.1894 + cc_.reportError(node->pos(), Message_UnexpectedArrayLiteral);
1.1895 +}
1.1896 +
1.1897 +void
1.1898 +SemanticAnalysis::visit(ImportStatement *node)
1.1899 +{
1.1900 +}
1.1901 +
1.1902 +#endif
1.1903 \ No newline at end of file