src/compiler/SemanticAnalysis.cpp
changeset 263 ba85a47ee414
parent 262 c4b1341297e5
     1.1 --- a/src/compiler/SemanticAnalysis.cpp	Mon Jun 10 00:46:29 2013 +0100
     1.2 +++ b/src/compiler/SemanticAnalysis.cpp	Mon Jun 10 01:04:43 2013 +0100
     1.3 @@ -1,1423 +1,1423 @@
     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 SourcePawn.
     1.9 - *
    1.10 - * SourcePawn 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 - * SourcePawn 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 - * SourcePawn. If not, see http://www.gnu.org/licenses/.
    1.21 - */
    1.22 -#include <assert.h>
    1.23 -#include "../Zone.h"
    1.24 -#include "../Strings.h"
    1.25 -#include "../NativeTable.h"
    1.26 -#include "../TypeManager.h"
    1.27 -#include "../Modules.h"
    1.28 -#include "../Code.h"
    1.29 -#include "SemanticAnalysis.h"
    1.30 -#include "../Heap-inl.h"
    1.31 -
    1.32 -using namespace ke;
    1.33 -
    1.34 -#define __ emitter_.
    1.35 -
    1.36 -typedef BytecodeEmitter::Label Label;
    1.37 -
    1.38 -class AutoEnterScope
    1.39 -{
    1.40 -  public:
    1.41 -    AutoEnterScope(Scope **prevp, Scope *scope)
    1.42 -      : prevp_(prevp),
    1.43 -        prev_(*prevp),
    1.44 -        scope_(scope)
    1.45 -    {
    1.46 -        if (!scope_)
    1.47 -            return;
    1.48 -        prev_ = *prevp_;
    1.49 -        *prevp_ = scope;
    1.50 -        assert(prev_ == scope->enclosing());
    1.51 -    }
    1.52 -    ~AutoEnterScope()
    1.53 -    {
    1.54 -        if (scope_)
    1.55 -            *prevp_ = prev_;
    1.56 -    }
    1.57 -  private:
    1.58 -    Scope **prevp_;
    1.59 -    Scope *prev_;
    1.60 -    Scope *scope_;
    1.61 -};
    1.62 -
    1.63 -SemanticAnalysis::SemanticAnalysis(Zone *zone, CompileContext &cc, TranslationUnit *unit)
    1.64 -  : zone_(zone),
    1.65 -    pool_(zone->pool()),
    1.66 -    cc_(cc),
    1.67 -    unit_(unit),
    1.68 -    hir_(NULL),
    1.69 -    loop_(NULL)
    1.70 -{
    1.71 -}
    1.72 -
    1.73 -SemanticAnalysis::SemanticAnalysis(SemanticAnalysis *parent, Handle<FunctionType> fun)
    1.74 -  : zone_(parent->zone_),
    1.75 -    pool_(parent->pool_),
    1.76 -    cc_(parent->cc_),
    1.77 -    unit_(parent->unit_),
    1.78 -    hir_(NULL),
    1.79 -    scope_(parent->scope_),
    1.80 -    fun_(fun),
    1.81 -    loop_(NULL),
    1.82 -    control_(NULL)
    1.83 -{
    1.84 -
    1.85 -}
    1.86 -
    1.87 -void
    1.88 -SemanticAnalysis::analyze()
    1.89 -{
    1.90 -    scope_ = unit_->globalScope();
    1.91 -
    1.92 -    for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
    1.93 -        Statement *stmt = unit_->tree()->statements()->at(i);
    1.94 -        stmt->accept(this);
    1.95 -    }
    1.96 -
    1.97 -    Local<Code> code(zone_, __ finish());
    1.98 -    if (!code)
    1.99 -        return;
   1.100 -    code->setModule(unit_->module());
   1.101 -    unit_->module()->setCode(code);
   1.102 -
   1.103 -#ifndef NDEBUG
   1.104 -//    Disassemble(code, stdout);
   1.105 -#endif
   1.106 -}
   1.107 -
   1.108 -void
   1.109 -SemanticAnalysis::visitFunctionStatement(FunctionStatement *stmt)
   1.110 -{
   1.111 -    FunctionSymbol *sym = stmt->sym();
   1.112 -    Local<FunctionType> type(zone_, sym->type());
   1.113 -
   1.114 -    assert(scope_->kind() == Scope::GLOBAL);
   1.115 -
   1.116 -    if (stmt->token() == TOK_NATIVE) {
   1.117 -        // Define the native now.
   1.118 -        size_t index;
   1.119 -        if (!zone_->nativeTable()->add(stmt->name(), &index))
   1.120 -            return;
   1.121 -
   1.122 -        Local<Native> native(zone_, Native::New(zone_, type, index));
   1.123 -        if (!native)
   1.124 -            return;
   1.125 -
   1.126 -        __ object(native);
   1.127 -        __ setglobal(sym);
   1.128 -        __ pop();
   1.129 -    }
   1.130 -
   1.131 -    // If the function is a forward or native, we don't have to do anything.
   1.132 -    if (stmt->token() == TOK_NATIVE || stmt->token() == TOK_FORWARD)
   1.133 -        return;
   1.134 -
   1.135 -    SemanticAnalysis child(this, type);
   1.136 -    Local<Function> funobj(zone_, child.compile(stmt));
   1.137 -    if (!funobj)
   1.138 -        return;
   1.139 -
   1.140 -    __ object(funobj);
   1.141 -    __ setglobal(sym);
   1.142 -    if (stmt->token() == TOK_PUBLIC)
   1.143 -        __ public_();
   1.144 -    else
   1.145 -        __ pop();
   1.146 -}
   1.147 -
   1.148 -Function *
   1.149 -SemanticAnalysis::compile(FunctionStatement *stmt)
   1.150 -{
   1.151 -    __ setFirstLine(stmt->pos().line);
   1.152 -
   1.153 -    AutoEnterScope argScope(&scope_, stmt->argScope());
   1.154 -
   1.155 -    for (size_t i = 0; i < stmt->signature().parameters()->length(); i++) {
   1.156 -        Parameter *param = stmt->signature().parameters()->at(i);
   1.157 -        param->sym()->allocate(VariableSymbol::Arg, i);
   1.158 -    }
   1.159 -
   1.160 -    AutoEnterScope varScope(&scope_, stmt->varScope());
   1.161 -    ControlStatus status = visitForControl(stmt->body());
   1.162 -
   1.163 -    if (!fun_->returnType()->isVoid()) {
   1.164 -        // If the function is not void, report if not all paths return a value.
   1.165 -        // All other incorrect return cases have been caught already.
   1.166 -        if (status.returns() == Returns_Sometimes) {
   1.167 -            cc_.reportError(stmt->pos(), Message_NotAllPathsReturnValue);
   1.168 -            return NULL;
   1.169 -        }
   1.170 -
   1.171 -        if (status.returns() == Returns_Never) {
   1.172 -            cc_.reportError(stmt->pos(), Message_MissingReturnValue);
   1.173 -            return NULL;
   1.174 -        }
   1.175 -    }
   1.176 -
   1.177 -    Local<Code> code(zone_, __ finish());
   1.178 -    if (!code)
   1.179 -        return NULL;
   1.180 -    code->setModule(unit_->module());
   1.181 -
   1.182 -    Local<Function> fun(zone_, Function::New(zone_, code, fun_, stmt->name(), stmt->pos()));
   1.183 -    if (!fun)
   1.184 -        return NULL;
   1.185 -
   1.186 -#ifndef NDEBUG
   1.187 -//    Disassemble(code, stdout);
   1.188 -#endif
   1.189 -
   1.190 -    return fun;
   1.191 -}
   1.192 -
   1.193 -void 
   1.194 -SemanticAnalysis::visitBlockStatement(BlockStatement *node)
   1.195 -{
   1.196 -    AutoEnterScope scope(&scope_, node->scope());
   1.197 -
   1.198 -    for (size_t i = 0; i < node->statements()->length(); i++) {
   1.199 -        Statement *stmt = node->statements()->at(i);
   1.200 -        __ note_position(stmt->pos());
   1.201 -        stmt->accept(this);
   1.202 -        assert(__ stackDepth() == 0);
   1.203 -    }
   1.204 -}
   1.205 -
   1.206 -void
   1.207 -SemanticAnalysis::visitEnumStatement(EnumStatement *node)
   1.208 -{
   1.209 -}
   1.210 -
   1.211 -void
   1.212 -SemanticAnalysis::visitExpressionStatement(ExpressionStatement *node)
   1.213 -{
   1.214 -    // While building HIR, we enter new pool and root scopes, since HIR
   1.215 -    // creation is purely temporary.
   1.216 -    PoolScope poolScope(zone_->pool());
   1.217 -    RootScope rootScope(zone_);
   1.218 -
   1.219 -    HIR *hir = eval(node->expression());
   1.220 -    if (!hir)
   1.221 -        return;
   1.222 -
   1.223 -    discharge(hir);
   1.224 -    if (!hir->type()->isVoid())
   1.225 -        __ pop();
   1.226 -}
   1.227 -
   1.228 -void
   1.229 -SemanticAnalysis::ControlScope::merge(const ControlStatus &left, const ControlStatus &right)
   1.230 -{
   1.231 -    // If both sides terminate in a return, we consider this a return as well.
   1.232 -    if (left.returns() == Returns_Always && right.returns() == Returns_Always) {
   1.233 -        terminate(Returns_Always);
   1.234 -        return;
   1.235 -    }
   1.236 -
   1.237 -    ReturnStatus status = (left.returns() == Returns_Never && right.returns() == Returns_Never)
   1.238 -                          ? Returns_Never
   1.239 -                          : Returns_Sometimes;
   1.240 -
   1.241 -    if (left.terminates() && right.terminates())
   1.242 -        terminate(status);
   1.243 -    else
   1.244 -        returns(status);
   1.245 -}
   1.246 -
   1.247 -SemanticAnalysis::ControlStatus
   1.248 -SemanticAnalysis::visitForControl(Statement *statement)
   1.249 -{
   1.250 -    ControlScope scope(&control_);
   1.251 -    statement->accept(this);
   1.252 -    return scope.status();
   1.253 -}
   1.254 -
   1.255 -void
   1.256 -SemanticAnalysis::visitIfStatement(IfStatement *node)
   1.257 -{
   1.258 -    Label join;
   1.259 -
   1.260 -    ControlStatus trueBranch;
   1.261 -    ControlStatus falseBranch(false, Returns_Never);
   1.262 -
   1.263 -    if (!node->ifFalse()) {
   1.264 -        Label success;
   1.265 -
   1.266 -        visitForTest(node->condition(), &success, &join, &success);
   1.267 -        __ bind(&success);
   1.268 -        trueBranch = visitForControl(node->ifTrue());
   1.269 -    } else {
   1.270 -        Label success, next;
   1.271 -
   1.272 -        visitForTest(node->condition(), &success, &next, &success);
   1.273 -        __ bind(&success);
   1.274 -        trueBranch = visitForControl(node->ifTrue());
   1.275 -        __ jump(&join);
   1.276 -        __ bind(&next);
   1.277 -        falseBranch = visitForControl(node->ifFalse());
   1.278 -    }
   1.279 -
   1.280 -    __ bind(&join);
   1.281 -
   1.282 -    control_->merge(trueBranch, falseBranch);
   1.283 -}
   1.284 -
   1.285 -void
   1.286 -SemanticAnalysis::requireLifoStack()
   1.287 -{
   1.288 -    if (!loop_)
   1.289 -        return;
   1.290 -
   1.291 -    loop_->setUsesLifoStack();
   1.292 -}
   1.293 -
   1.294 -SemanticAnalysis::ControlStatus
   1.295 -SemanticAnalysis::visitLoopBody(Statement *stmt)
   1.296 -{
   1.297 -    // We always mark off a loop body, so on each edge, we can balance the
   1.298 -    // LIFO stack. Right now, we don't have the ability to budget the LIFO
   1.299 -    // stack ahead of time. If we turn out to never need the LIFO stack, we
   1.300 -    // mark it as unnecessary. (The interpreter can't really make use of this,
   1.301 -    // but the JIT can).
   1.302 -    //
   1.303 -    // Note that balancing the LIFO stack isn't even necessary, so this
   1.304 -    // feature may be removed. All this mechanism does is mitigate the
   1.305 -    // possibility that a long-running loop will overflow the LIFO region
   1.306 -    // and therefore start requiring nursery allocations.
   1.307 -    int pos = __ enterloop();
   1.308 -    ControlStatus status = visitForControl(stmt);
   1.309 -    __ leaveloop();
   1.310 -
   1.311 -    if (loop_->usesLifoStack())
   1.312 -        __ setLoopUsesLifoStack(pos);
   1.313 -
   1.314 -    return status;
   1.315 -}
   1.316 -
   1.317 -void
   1.318 -SemanticAnalysis::visitForStatement(ForStatement *node)
   1.319 -{
   1.320 -    AutoEnterScope scope(&scope_, node->scope());
   1.321 -    PoolScope poolScope(zone_->pool());
   1.322 -    RootScope rootScope(zone_);
   1.323 -
   1.324 -    Label join, update;
   1.325 -    LoopScope loop(scope_, &join, &update, &loop_);
   1.326 -
   1.327 -    if (node->initialization())
   1.328 -        node->initialization()->accept(this);
   1.329 -
   1.330 -    Label header, test;
   1.331 -    if (node->condition())
   1.332 -        __ jump(&test);
   1.333 -
   1.334 -    __ bind(&header);
   1.335 -    ControlStatus status = visitLoopBody(node->body());
   1.336 -
   1.337 -    __ bind(&update);
   1.338 -    if (node->update())
   1.339 -        node->update()->accept(this);
   1.340 -
   1.341 -    if (node->condition()) {
   1.342 -        __ bind(&test);
   1.343 -        visitForTest(node->condition(), &header, &join, &join);
   1.344 -    } else {
   1.345 -        __ jump(&header);
   1.346 -    }
   1.347 -
   1.348 -    __ bind(&join);
   1.349 -    
   1.350 -    // If there was a condition, we treat this like a while loop. Otherwise,
   1.351 -    // the join point is only reachable if the loop contains a break. The
   1.352 -    // termination status doesn't tell us anything yet.
   1.353 -    if (node->condition() || loop.breaks())
   1.354 -        control_->merge(status, ControlStatus(false, Returns_Never));
   1.355 -    else
   1.356 -        control_->terminate(status.returns());
   1.357 -
   1.358 -    assert(__ stackDepth() == 0);
   1.359 -}
   1.360 -
   1.361 -void
   1.362 -SemanticAnalysis::visitWhileStatement(WhileStatement *node)
   1.363 -{
   1.364 -    PoolScope poolScope(zone_->pool());
   1.365 -    RootScope rootScope(zone_);
   1.366 -
   1.367 -    Label header, join;
   1.368 -
   1.369 -    __ bind(&header);
   1.370 -
   1.371 -    ControlStatus status;
   1.372 -
   1.373 -    LoopScope loop(scope_, &join, &header, &loop_);
   1.374 -    if (node->token() == TOK_WHILE) {
   1.375 -        Label body;
   1.376 -        visitForTest(node->condition(), &body, &join, &body);
   1.377 -        status = visitLoopBody(node->body());
   1.378 -        __ jump(&header);
   1.379 -    } else {
   1.380 -        status = visitLoopBody(node->body());
   1.381 -        visitForTest(node->condition(), &header, &join, &join);
   1.382 -    }
   1.383 -
   1.384 -    __ bind(&join);
   1.385 -
   1.386 -    // Detect loops that will always have a fork in the contro-flow graph.
   1.387 -    // This will be a |while| loop, or a |do-while| loop whose body does
   1.388 -    // not terminate. For now, we treat these as an |if| regardless of the
   1.389 -    // direction the branch can take. That means the control-flow is always
   1.390 -    // conditional.
   1.391 -    if (node->token() == TOK_WHILE || status.terminates() || loop.breaks()) {
   1.392 -        control_->merge(status, ControlStatus(false, Returns_Never));
   1.393 -    } else {
   1.394 -        // At this point, we've got a do-while loop with a |return| or
   1.395 -        // |continue|, meaning that the rest of the block is unreachable.
   1.396 -        control_->terminate(status.returns());
   1.397 -    }
   1.398 -
   1.399 -    assert(__ stackDepth() == 0);
   1.400 -}
   1.401 -
   1.402 -static inline Heap::Tenure
   1.403 -InferTenure(Symbol *sym)
   1.404 -{
   1.405 -    if (sym->scope()->kind() == Scope::GLOBAL)
   1.406 -        return Heap::Tenure_Old;
   1.407 -
   1.408 -    // SP2's array semantics allow any array kind to escape, so we must use
   1.409 -    // the normal heap. (Hopefully escape analysis can ease this pain later).
   1.410 -    if (sym->type()->isArray())
   1.411 -        return Heap::Tenure_Default;
   1.412 -
   1.413 -    return Heap::Tenure_Default;
   1.414 -}
   1.415 -
   1.416 -void
   1.417 -SemanticAnalysis::visitVariableDeclaration(VariableDeclaration *node)
   1.418 -{
   1.419 -    PoolScope poolScope(zone_->pool());
   1.420 -    RootScope rootScope(zone_);
   1.421 -
   1.422 -    Local<Type> type(zone_, node->sym()->type());
   1.423 -
   1.424 -    if (node->sym()->type()->isVoid()) {
   1.425 -        cc_.reportError(node->type()->pos(), Message_CannotDeclareVoid);
   1.426 -        return;
   1.427 -    }
   1.428 -
   1.429 -    if (node->initialization()) {
   1.430 -        HIR *hir = NULL;
   1.431 -
   1.432 -        if ((hir = eval(node->initialization())) == NULL)
   1.433 -            return;
   1.434 -        if ((hir = coerce(hir, type, Coerce_Decl)) == NULL)
   1.435 -            return;
   1.436 -
   1.437 -        discharge(hir);
   1.438 -    } else {
   1.439 -        if (type->isInt32() || type->isEnum() ||
   1.440 -            type->isChar() || type->isBool())
   1.441 -        {
   1.442 -            __ int_(0);
   1.443 -        } else if (type->isFloat()) {
   1.444 -            __ float_(0);
   1.445 -        } else if (type->isArray()) {
   1.446 -            Local<ArrayType> atype(zone_, ArrayType::cast(type));
   1.447 -            Local<ArrayMap> map(zone_, atype->newMap());
   1.448 -            if (!map)
   1.449 -                return;
   1.450 -
   1.451 -            if (atype->isFixedLength()) {
   1.452 -                __ newarray(OP_NEWFIXED, map, InferTenure(node->sym()));
   1.453 -            } else if (node->dims()->at(0)) {
   1.454 -                // This may not be true if we allow typedefing, so :TODO:
   1.455 -                // figure out proper semantics.
   1.456 -                assert(node->dims()->length() == atype->levels());
   1.457 -
   1.458 -                Local<Type> i32(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
   1.459 -                for (size_t i = 0; i < node->dims()->length(); i++) {
   1.460 -                    Expression *expr = node->dims()->at(i);
   1.461 -                    if (expr) {
   1.462 -                        HIR *hir = eval(expr);
   1.463 -                        if (!hir || ((hir = coerce(hir, i32, Coerce_Arg)) == NULL))
   1.464 -                            return;
   1.465 -                        discharge(hir);
   1.466 -                    } else {
   1.467 -                        __ int_(0);
   1.468 -                    }
   1.469 -                }
   1.470 -                __ newarray(OP_NEWSIZED, map, InferTenure(node->sym()));
   1.471 -            } else {
   1.472 -                __ newarray(OP_NEWEMPTY, map, InferTenure(node->sym()));
   1.473 -            }
   1.474 -        } else {
   1.475 -            assert(false);
   1.476 -        }
   1.477 -    }
   1.478 -
   1.479 -    if (node->sym()->scope()->kind() != Scope::GLOBAL) {
   1.480 -        if (!__ allocate(node->sym()))
   1.481 -            return;
   1.482 -    }
   1.483 -
   1.484 -    set(node->sym());
   1.485 -    __ pop();
   1.486 -}
   1.487 -
   1.488 -void
   1.489 -SemanticAnalysis::visitReturnStatement(ReturnStatement *node)
   1.490 -{
   1.491 -    control_->returns(Returns_Always);
   1.492 -
   1.493 -    if (!node->expression()) {
   1.494 -        if (!fun_->returnType()->isVoid()) {
   1.495 -            cc_.reportError(node->pos(), Message_MissingReturnValue);
   1.496 -            return;
   1.497 -        }
   1.498 -
   1.499 -        __ returnvoid();
   1.500 -        return;
   1.501 -    }
   1.502 -
   1.503 -    if (fun_->returnType()->isVoid()) {
   1.504 -        cc_.reportError(node->pos(), Message_UsedVoidReturn);
   1.505 -        return;
   1.506 -    }
   1.507 -
   1.508 -    PoolScope poolScope(zone_->pool());
   1.509 -    RootScope rootScope(zone_);
   1.510 -
   1.511 -    HIR *hir = eval(node->expression());
   1.512 -    if (!hir)
   1.513 -        return;
   1.514 -
   1.515 -    Local<Type> returnType(zone_, fun_->returnType());
   1.516 -    if ((hir = coerce(hir, returnType, Coerce_Return)) == NULL)
   1.517 -        return;
   1.518 -
   1.519 -    discharge(hir);
   1.520 -
   1.521 -    if (hir->type()->isVoid())
   1.522 -        __ returnvoid();
   1.523 -    else
   1.524 -        __ return_();
   1.525 -}
   1.526 -
   1.527 -void
   1.528 -SemanticAnalysis::visitBinaryExpression(BinaryExpression *node)
   1.529 -{
   1.530 -    HIR *left = eval(node->left());
   1.531 -    HIR *right = eval(node->right());
   1.532 -    if (!left || !right)
   1.533 -        return;
   1.534 -
   1.535 -    hir_ = binary(node, node->token(), left, right);
   1.536 -}
   1.537 -
   1.538 -bool
   1.539 -SemanticAnalysis::checkArgumentCount(Handle<FunctionType> type, unsigned actual)
   1.540 -{
   1.541 -    if (type->parameters()->length() == actual)
   1.542 -        return true;
   1.543 -
   1.544 -    if (actual > type->parameters()->length()) {
   1.545 -        if (!type->isNative() || !type->isNativeVariadic())
   1.546 -            return false;
   1.547 -        return true;
   1.548 -    }
   1.549 -
   1.550 -    if (!type->defaults())
   1.551 -        return false;
   1.552 -
   1.553 -    // Missing arguments. See if there's a default argument for each missing
   1.554 -    // actual.
   1.555 -    for (unsigned i = actual; i < type->parameters()->length(); i++) {
   1.556 -        if (!type->defaults()->at(i))
   1.557 -            return false;
   1.558 -    }
   1.559 -
   1.560 -    return true;
   1.561 -}
   1.562 -
   1.563 -static unsigned
   1.564 -BindImplicitName(Module *from, ImplicitSymbol *sym)
   1.565 -{
   1.566 -    if (sym->bound())
   1.567 -        return sym->fieldIndex();
   1.568 -
   1.569 -    Module *module = Module::cast(from->getImportAt(sym->index()));
   1.570 -    StructMap *map = module->globals()->map();
   1.571 -
   1.572 -    unsigned fieldIndex;
   1.573 -    Descriptor *desc = map->type()->lookupField(sym->name(), &fieldIndex);
   1.574 -    assert(desc && desc->type() == sym->type());
   1.575 -
   1.576 -    sym->bind(fieldIndex);
   1.577 -    return fieldIndex;
   1.578 -}
   1.579 -
   1.580 -void
   1.581 -SemanticAnalysis::visitNameProxy(NameProxy *proxy)
   1.582 -{
   1.583 -    Symbol *sym = proxy->sym();
   1.584 -
   1.585 -    switch (sym->kind()) {
   1.586 -      case Symbol::kImport:
   1.587 -      {
   1.588 -        ImportSymbol *import = sym->toImport();
   1.589 -        hir_ = new (pool_) HImport(proxy, sym->type(), import->index());
   1.590 -        break;
   1.591 -      }
   1.592 -
   1.593 -      case Symbol::kImplicit:
   1.594 -      {
   1.595 -        ImplicitSymbol *import = sym->toImplicit();
   1.596 -        unsigned fieldIndex = BindImplicitName(unit_->module(), import);
   1.597 -
   1.598 -        hir_ = new (pool_) HImport(proxy, zone_->types()->getImportable(), import->index());
   1.599 -        hir_ = new (pool_) HField(proxy, hir_, sym->type(), fieldIndex);
   1.600 -        break;
   1.601 -      }
   1.602 -
   1.603 -      case Symbol::kConstant:
   1.604 -      {
   1.605 -        ConstantSymbol *val = sym->toConstant();
   1.606 -        hir_ = new (pool_) HInteger(proxy, sym->type(), val->value().toInt());
   1.607 -        break;
   1.608 -      }
   1.609 -      
   1.610 -      // This is kind of screwy. Symbol::kFunction is like a constant we can't
   1.611 -      // evaluate yet. Maybe we should extract the GLOBAL case and say that
   1.612 -      // kFunction is only used for global functions (and use const vars for
   1.613 -      // local functions).
   1.614 -      case Symbol::kFunction:
   1.615 -      case Symbol::kVariable:
   1.616 -      {
   1.617 -        Scope *in = sym->scope();
   1.618 -        switch (in->kind()) {
   1.619 -          case Scope::GLOBAL:
   1.620 -            hir_ = new (pool_) HGlobal(proxy, sym);
   1.621 -            break;
   1.622 -
   1.623 -          case Scope::FUNCTION:
   1.624 -          {
   1.625 -            VariableSymbol *var = sym->toVariable();
   1.626 -            assert(var->storage() == VariableSymbol::Arg);
   1.627 -            hir_ = new (pool_) HLocal(proxy, var);
   1.628 -            break;
   1.629 -          }
   1.630 -
   1.631 -          default:
   1.632 -          {
   1.633 -            VariableSymbol *var = sym->toVariable();
   1.634 -            assert(in->kind() == Scope::BLOCK);
   1.635 -            assert(var->storage() == VariableSymbol::Local);
   1.636 -            hir_ = new (pool_) HLocal(proxy, var);
   1.637 -            break;
   1.638 -          }
   1.639 -        }
   1.640 -        break;
   1.641 -      }
   1.642 -
   1.643 -      default:
   1.644 -        // :TODO:
   1.645 -        assert(false);
   1.646 -    }
   1.647 -}
   1.648 -
   1.649 -void
   1.650 -SemanticAnalysis::visitBooleanLiteral(BooleanLiteral *node)
   1.651 -{
   1.652 -    Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
   1.653 -    hir_ = new (pool_) HBoolean(node, type, node->token() == TOK_TRUE);
   1.654 -}
   1.655 -
   1.656 -void
   1.657 -SemanticAnalysis::visitIntegerLiteral(IntegerLiteral *lit)
   1.658 -{
   1.659 -    Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
   1.660 -    hir_ = new (pool_) HInteger(lit, type, lit->value());
   1.661 -}
   1.662 -
   1.663 -void
   1.664 -SemanticAnalysis::visitFloatLiteral(FloatLiteral *node)
   1.665 -{
   1.666 -    Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
   1.667 -    hir_ = new (pool_) HFloat(node, type, (float)node->value());
   1.668 -}
   1.669 -
   1.670 -void
   1.671 -SemanticAnalysis::visitStringLiteral(StringLiteral *node)
   1.672 -{
   1.673 -    Type *type = zone_->types()->getString();
   1.674 -    hir_ = new (pool_) HString(node, type, node->string());
   1.675 -}
   1.676 -
   1.677 -void
   1.678 -SemanticAnalysis::visitCallExpression(CallExpression *node)
   1.679 -{
   1.680 -    HIR *callee = eval(node->callee());
   1.681 -    if (!callee)
   1.682 -        return;
   1.683 -
   1.684 -    if (!callee->type()->isFunction()) {
   1.685 -        cc_.reportError(node->pos(), Message_CalleeNotFunction);
   1.686 -        return;
   1.687 -    }
   1.688 -
   1.689 -    Local<FunctionType> fun(zone_, FunctionType::cast(callee->type()));
   1.690 -    
   1.691 -    if (!checkArgumentCount(fun, node->arguments()->length())) {
   1.692 -        cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
   1.693 -        return;
   1.694 -    }
   1.695 -
   1.696 -    if (fun->isForward()) {
   1.697 -        cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
   1.698 -        return;
   1.699 -    }
   1.700 -
   1.701 -    HIRList *args = new (pool_) HIRList;
   1.702 -    for (unsigned i = 0; i < node->arguments()->length(); i++) {
   1.703 -        Expression *expression = node->arguments()->at(i);
   1.704 -        HIR *arg = eval(expression);
   1.705 -        if (!arg)
   1.706 -            return;
   1.707 -
   1.708 -        Handle<Type> given = arg->type();
   1.709 -        
   1.710 -        bool mustComputeReference;
   1.711 -        if (i >= fun->parameters()->length()) {
   1.712 -            // Special handling for natives. Arguments past the formal must
   1.713 -            // always have references computed. However, arrays are already
   1.714 -            // references for natives.
   1.715 -            assert(fun->isNative() && fun->isNativeVariadic());
   1.716 -            mustComputeReference = !given->isReference() &&
   1.717 -                                   !given->isArray();
   1.718 -        } else {
   1.719 -            Local<Type> actual(zone_, fun->parameterAt(i));
   1.720 -
   1.721 -            if (expression->isIndexExpression() && arg->isIndex()) {
   1.722 -                // If the expression is the form x[y], and this produced a
   1.723 -                // normal array indexing operation, then we apply some 
   1.724 -                // special rules.
   1.725 -
   1.726 -                if (actual->isReference()) {
   1.727 -                    // Disabled, since this doesn't have easily definable or
   1.728 -                    // sensible semantics with SP2 arrays, but we don't want
   1.729 -                    // to silently break SP1 semantics.
   1.730 -                    cc_.reportError(expression->pos(), Message_CannotComputeIndexRef);
   1.731 -                    return;
   1.732 -                }
   1.733 -
   1.734 -                // As a special rule to account for SP1 semantics, we allow x[y]
   1.735 -                // to automatically compute a sliced, read-only array view if
   1.736 -                // the desired type is an array of one more dimension than x[y]
   1.737 -                // would return.
   1.738 -                //
   1.739 -                // As an additional restriction, this is only allowed for
   1.740 -                // one-level char arrays, to minimize potential issues until
   1.741 -                // we determine whether more compatibility is needed.
   1.742 -                //
   1.743 -                // Internally, for sanity, the dependent array operation does
   1.744 -                // not necessarily create a dependent array. For extensible
   1.745 -                // arrays, we instead create a duplicate arrary of just the
   1.746 -                // sliced portion, rather than deal with the complexity of the
   1.747 -                // source array being resized.
   1.748 -                //
   1.749 -                // Note that we don't really know whether a dependent array
   1.750 -                // will be dependent at compile-time, so the dependent type's
   1.751 -                // just inherits from the source.
   1.752 -                if (actual->isArray()) {
   1.753 -                    HIndex *index = arg->toIndex();
   1.754 -                    Local<ArrayType> basetype(zone_, ArrayType::cast(index->base()->type()));
   1.755 -                    Local<ArrayType> atype(zone_, ArrayType::cast(actual));
   1.756 -
   1.757 -                    if (atype->isCharArray() && basetype->isCharArray()) {
   1.758 -                        // There is no possible way this will type check, so
   1.759 -                        // it's safe to just try something completely
   1.760 -                        // different.
   1.761 -                        Local<Type> slicetype(zone_);
   1.762 -                        if (basetype->isFixedLength()) {
   1.763 -                            // If the base type is fixed length, we need to
   1.764 -                            // compute a new dynamic array type based on the
   1.765 -                            // fixed array's contents and qualifiers.
   1.766 -                            Local<Type> contained(zone_, basetype->contained());
   1.767 -                            slicetype = zone_->types()->newArray(contained, ArrayType::DYNAMIC_ARRAY_SIZE);
   1.768 -                            if (!slicetype)
   1.769 -                                return;
   1.770 -                            slicetype = zone_->types()->qualify(slicetype, basetype->quals());
   1.771 -                            if (!slicetype)
   1.772 -                                return;
   1.773 -                        } else {
   1.774 -                            slicetype = basetype;
   1.775 -                        }
   1.776 -                        arg = new (pool_) HNewDependentArray(expression, slicetype, index->base(), index->index());
   1.777 -                        given = arg->type();
   1.778 -                    }
   1.779 -                }
   1.780 -            }
   1.781 -
   1.782 -            if (actual->isReference()) {
   1.783 -                // If the actual is a reference, the coercion rules are much
   1.784 -                // stricter; the contained types must be identical.
   1.785 -                // :TODO: make this not an assert
   1.786 -                assert(ReferenceType::cast(actual)->contained() == arg->type());
   1.787 -            } else {
   1.788 -                // When we start overloading, coercion will have to happen later.
   1.789 -                arg = coerce(arg, actual, Coerce_Arg);
   1.790 -                if (!arg)
   1.791 -                    return;
   1.792 -            }
   1.793 -
   1.794 -            mustComputeReference = actual->isReference() && !given->isReference();
   1.795 -        }
   1.796 -
   1.797 -        if (mustComputeReference) {
   1.798 -            // Refs always use the LIFO stack if they can.
   1.799 -            arg = new (pool_) HToRef(arg->node(), arg->type(), arg);
   1.800 -            requireLifoStack();
   1.801 -        }
   1.802 -
   1.803 -        if (!args->append(arg))
   1.804 -            return;
   1.805 -    }
   1.806 -
   1.807 -    hir_ = new (pool_) HCall(node, fun->returnType(), callee, args);
   1.808 -}
   1.809 -
   1.810 -void
   1.811 -SemanticAnalysis::visitAssignment(Assignment *node)
   1.812 -{
   1.813 -    HLValue *lval = lvalue(node->lvalue());
   1.814 -    if (!lval)
   1.815 -        return;
   1.816 -
   1.817 -    if (lval->type()->quals() & TypeQual_Const) {
   1.818 -        cc_.reportError(node->pos(), Message_CannotModifyConst);
   1.819 -        return;
   1.820 -    }
   1.821 -
   1.822 -    HIR *hir = eval(node->expression());
   1.823 -    if (!hir)
   1.824 -        return;
   1.825 -    if ((hir = coerce(hir, lval->type(), Coerce_Assign)) == NULL)
   1.826 -        return;
   1.827 -
   1.828 -    hir_ = new (pool_) HStore(node, node->token(), lval, hir);
   1.829 -}
   1.830 -
   1.831 -void
   1.832 -SemanticAnalysis::visitBreakStatement(BreakStatement *node)
   1.833 -{
   1.834 -    if (!loop_) {
   1.835 -        cc_.reportError(node->pos(), Message_BreakOutsideLoop);
   1.836 -        return;
   1.837 -    }
   1.838 -
   1.839 -    loop_->setBreaks();
   1.840 -    __ j(OP_BREAK, loop_->break_());
   1.841 -}
   1.842 -
   1.843 -void
   1.844 -SemanticAnalysis::visitContinueStatement(ContinueStatement *node)
   1.845 -{
   1.846 -    if (!loop_) {
   1.847 -        cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
   1.848 -        return;
   1.849 -    }
   1.850 -
   1.851 -    __ j(OP_CONTINUE, loop_->continue_());
   1.852 -}
   1.853 -
   1.854 -void
   1.855 -SemanticAnalysis::visitIndexExpression(IndexExpression *node)
   1.856 -{
   1.857 -    HIR *left = eval(node->left());
   1.858 -    if (!left)
   1.859 -        return;
   1.860 -
   1.861 -    HIR *right = eval(node->right());
   1.862 -    if (!right)
   1.863 -        return;
   1.864 -
   1.865 -    // Hrm... yes, for now, let's coerce here.
   1.866 -    Local<Type> i32(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
   1.867 -    if ((right = coerce(right, i32, Coerce_Arg)) == NULL)
   1.868 -        return;
   1.869 -    
   1.870 -    // Do not coerce here, there's no reason to yet.
   1.871 -    if (!left->type()->isArray()) {
   1.872 -        cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
   1.873 -        return;
   1.874 -    }
   1.875 -
   1.876 -    hir_ = new (pool_) HIndex(node,
   1.877 -                              ArrayType::cast(left->type())->contained(),
   1.878 -                              left,
   1.879 -                              right);
   1.880 -}
   1.881 -
   1.882 -void
   1.883 -SemanticAnalysis::visitIncDecExpression(IncDecExpression *node)
   1.884 -{
   1.885 -    HLValue *lval = lvalue(node->expression());
   1.886 -    if (!lval)
   1.887 -        return;
   1.888 -
   1.889 -    if (!lval->type()->isInt32() && !lval->type()->isFloat()) {
   1.890 -        assert(false);
   1.891 -        return;
   1.892 -    }
   1.893 -
   1.894 -    HIR *rval;
   1.895 -    if (lval->type()->isInt32())
   1.896 -        rval = new (pool_) HInteger(node, lval->type(), 1);
   1.897 -    else
   1.898 -        rval = new (pool_) HFloat(node, lval->type(), 1.0);
   1.899 -
   1.900 -    if (node->postfix())
   1.901 -        hir_ = new (pool_) HPostIncDec(node, node->token(), lval, rval);
   1.902 -    else
   1.903 -        hir_ = new (pool_) HStore(node, node->token(), lval, rval);
   1.904 -}
   1.905 -
   1.906 -Type *
   1.907 -SemanticAnalysis::coercionType(TokenKind token, HIR *left, HIR *right)
   1.908 -{
   1.909 -    Local<Type> l(zone_, left->type());
   1.910 -    Local<Type> r(zone_, right->type());
   1.911 -
   1.912 -    if (l->isPod())
   1.913 -        l = l->unqualified();
   1.914 -    if (r->isPod())
   1.915 -        r = r->unqualified();
   1.916 -
   1.917 -    if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
   1.918 -        (token >= TOK_EQUALS && token <= TOK_GE))
   1.919 -    {
   1.920 -        // We allow: [float|int32] + [float|int32]
   1.921 -        if (l->isFloat() && r->isInt32())
   1.922 -            return l;
   1.923 -        if (l->isInt32() && r->isFloat())
   1.924 -            return r;
   1.925 -        if (l->isInt32() && r->isInt32())
   1.926 -            return l;
   1.927 -
   1.928 -        if (l->isChar() && r->isInt32())
   1.929 -             return r;
   1.930 -        if (l->isInt32() && r->isChar())
   1.931 -            return l;
   1.932 -    }
   1.933 -
   1.934 -    // :TODO: remove
   1.935 -    assert(*l == *r);
   1.936 -
   1.937 -    return left->type();
   1.938 -}
   1.939 -
   1.940 -HIR *
   1.941 -SemanticAnalysis::typeCheckArray(const SourcePosition &pos,
   1.942 -                                 HIR *from,
   1.943 -                                 Handle<ArrayType> argActual,
   1.944 -                                 CoercionKind kind)
   1.945 -{
   1.946 -    Local<Type> argGiven(zone_, from->type());
   1.947 -
   1.948 -    // Special case: if we receive a string literal, and this is a char array,
   1.949 -    // we allow a coercion.
   1.950 -    if (from->isString() &&
   1.951 -        argGiven->isString() &&
   1.952 -        argActual->isArray() &&
   1.953 -        ArrayType::cast(argActual)->isCharArray())
   1.954 -    {
   1.955 -        HString *hir = from->toString();
   1.956 -        Local<ArrayType> actual(zone_, ArrayType::cast(argActual));
   1.957 -
   1.958 -        if (actual->isFixedLength()) {
   1.959 -            if (hir->string()->length() + 1 > actual->fixedLength()) {
   1.960 -                cc_.reportError(pos, Message_ArrayAssignmentTooBig);
   1.961 -                return NULL;
   1.962 -            }
   1.963 -        }
   1.964 -
   1.965 -        // Transform the string literal into an array literal. We give it the
   1.966 -        // type of the left-hand side. The constness of the destination type
   1.967 -        // will determine whether HArray duplicates it or not.
   1.968 -        Local<ArrayMap> map(zone_, actual->newMap());
   1.969 -        if (!map)
   1.970 -            return NULL;
   1.971 -
   1.972 -        Local<Array> array(zone_);
   1.973 -        array = Array::NewString(zone_,
   1.974 -                                 map,
   1.975 -                                 hir->string()->chars(),
   1.976 -                                 hir->string()->length(),
   1.977 -                                 Heap::Tenure_Old);
   1.978 -        if (!array)
   1.979 -            return NULL;
   1.980 -
   1.981 -        // Since we're creating a canonical copy of the char array, we have to
   1.982 -        // be careful that it doesn't get mutated. There are two cases where
   1.983 -        // we know it can't be mutated, and therefore don't need to specify
   1.984 -        // that it be cloned after pushing it onto the stack.
   1.985 -        //
   1.986 -        //  (1) The array type is const.
   1.987 -        //  (2) The array type is fixed-length, and the coercion is for
   1.988 -        //      assignment, meaning it will be immediately copied.
   1.989 -        //
   1.990 -        // We treat declaration separately from assignment, since for
   1.991 -        // declaration we can just immediately use the cloned version.
   1.992 -        bool shouldDuplicate = true;
   1.993 -        if ((actual->quals() & TypeQual_Const) ||
   1.994 -            (actual->isFixedLength() && kind == Coerce_Assign))
   1.995 -        {
   1.996 -            shouldDuplicate = false;
   1.997 -        }
   1.998 -
   1.999 -        return new (pool_) HArray(hir->node(), actual, array, shouldDuplicate);
  1.1000 -    }
  1.1001 -
  1.1002 -    if (!argGiven->isArray()) {
  1.1003 -        cc_.reportError(pos, Message_ExpectedArray);
  1.1004 -        return NULL;
  1.1005 -    }
  1.1006 -
  1.1007 -    Local<ArrayType> actual(zone_, ArrayType::cast(argActual));
  1.1008 -    Local<ArrayType> given(zone_, ArrayType::cast(argGiven));
  1.1009 -
  1.1010 -    if (actual->levels() != given->levels()) {
  1.1011 -        cc_.reportError(pos, Message_ArrayDimensionsMismatch);
  1.1012 -        return NULL;
  1.1013 -    }
  1.1014 -
  1.1015 -    unsigned level = 1;
  1.1016 -    while (true) {
  1.1017 -        if (actual->isFixedLength()) {
  1.1018 -            if (!given->isFixedLength()) {
  1.1019 -                cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
  1.1020 -                return NULL;
  1.1021 -            }
  1.1022 -
  1.1023 -            if (actual->isCharArray()) {
  1.1024 -                // String assignment can have a truncated |given|.
  1.1025 -                if (given->fixedLength() > actual->fixedLength()) {
  1.1026 -                    cc_.reportError(pos, Message_ArrayAssignmentTooBig);
  1.1027 -                    return NULL;
  1.1028 -                }
  1.1029 -            } else {
  1.1030 -                if (given->fixedLength() != actual->fixedLength()) {
  1.1031 -                    cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
  1.1032 -                    return NULL;
  1.1033 -                }
  1.1034 -            }
  1.1035 -        } else if (given->isFixedLength()) {
  1.1036 -            // We do not allow assignments in the form:
  1.1037 -            //  [][] = [][Y]
  1.1038 -            //
  1.1039 -            // Otherwise, the following code could break the size guarantees
  1.1040 -            // of the right-hand side:
  1.1041 -            //
  1.1042 -            //  new x[][5];
  1.1043 -            //  new y[][];
  1.1044 -            //  new z[3];
  1.1045 -            //
  1.1046 -            //
  1.1047 -            //  y = x;
  1.1048 -            //  y[0] = z;
  1.1049 -            //
  1.1050 -            // Now |x[0]| contains a 3-length array.
  1.1051 -            if (level > 1) {
  1.1052 -                cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
  1.1053 -                return NULL;
  1.1054 -            }
  1.1055 -        }
  1.1056 -
  1.1057 -        if (!given->contained()->isArray() || !actual->contained()->isArray())
  1.1058 -            break;
  1.1059 -
  1.1060 -        given = ArrayType::cast(given->contained());
  1.1061 -        actual = ArrayType::cast(actual->contained());
  1.1062 -    }
  1.1063 -
  1.1064 -    bool givenConst = !!(given->contained()->quals() & TypeQual_Const);
  1.1065 -    bool actualConst = !!(actual->contained()->quals() & TypeQual_Const);
  1.1066 -
  1.1067 -    // These arrays must contain the same innermost type.
  1.1068 -    if (given->contained()->unqualified() != actual->contained()->unqualified() ||
  1.1069 -        (givenConst && !actualConst))
  1.1070 -    {
  1.1071 -        char aname[255];
  1.1072 -        char gname[255];
  1.1073 -        cc_.reportError(pos, Message_TypeMismatch,
  1.1074 -                        GetTypeName(argActual, aname, sizeof(aname)),
  1.1075 -                        GetTypeName(argGiven, gname, sizeof(gname)));
  1.1076 -        return NULL;
  1.1077 -    }
  1.1078 -
  1.1079 -    return from;
  1.1080 -}
  1.1081 -
  1.1082 -HIR *
  1.1083 -SemanticAnalysis::typeFailure(const SourcePosition &pos, Handle<Type> from, Handle<Type> to)
  1.1084 -{
  1.1085 -    char fname[255];
  1.1086 -    char tname[255];
  1.1087 -    cc_.reportError(pos, Message_InvalidCoercion,
  1.1088 -                    GetTypeName(from, fname, sizeof(fname)),
  1.1089 -                    GetTypeName(to, tname, sizeof(tname)));
  1.1090 -    return NULL;
  1.1091 -}
  1.1092 -
  1.1093 -HIR *
  1.1094 -SemanticAnalysis::coerce(HIR *hir, Handle<Type> to, CoercionKind kind)
  1.1095 -{
  1.1096 -    Local<Type> from(zone_, hir->type());
  1.1097 -
  1.1098 -    // If the source is *ever* an importable, we just fail.
  1.1099 -    if (from->isImportable())
  1.1100 -        return typeFailure(hir->node()->pos(), from, to);
  1.1101 -
  1.1102 -    if (from->isInt32() && to->isFloat())
  1.1103 -        return new (pool_) HConvert(hir->node(), to, OP_CVT_I2F, hir);
  1.1104 -    if (from->isInt32() && to->isBool())
  1.1105 -        return new (pool_) HConvert(hir->node(), to, OP_CVT_I2B, hir);
  1.1106 -
  1.1107 -    if (to->isEnum() && from->unqualified() != to->unqualified())
  1.1108 -        return typeFailure(hir->node()->pos(), from, to);
  1.1109 -    
  1.1110 -    if (to->isArray()) {
  1.1111 -        Local<ArrayType> atype(zone_, ArrayType::cast(to));
  1.1112 -        return typeCheckArray(hir->node()->pos(), hir, atype, kind);
  1.1113 -    }
  1.1114 -    
  1.1115 -    return hir;
  1.1116 -}
  1.1117 -
  1.1118 -void
  1.1119 -SemanticAnalysis::set(VariableSymbol *sym)
  1.1120 -{
  1.1121 -    if (sym->scope()->kind() == Scope::GLOBAL) {
  1.1122 -        __ setglobal(sym);
  1.1123 -    } else {
  1.1124 -        assert(sym->storage() == VariableSymbol::Local);
  1.1125 -        __ setlocal(sym);
  1.1126 -    }
  1.1127 -}
  1.1128 -
  1.1129 -HIR *
  1.1130 -SemanticAnalysis::binary(AstNode *node, TokenKind token, HIR *left, HIR *right)
  1.1131 -{
  1.1132 -    Local<Type> coercion(zone_, coercionType(token, left, right));
  1.1133 -    if (!coercion)
  1.1134 -        return NULL;
  1.1135 -    if ((left = coerce(left, coercion, Coerce_Arg)) == NULL)
  1.1136 -        return NULL;
  1.1137 -    if ((right = coerce(right, coercion, Coerce_Arg)) == NULL)
  1.1138 -        return NULL;
  1.1139 -    
  1.1140 -    switch (token) {
  1.1141 -     case TOK_PLUS:
  1.1142 -      case TOK_MINUS:
  1.1143 -      case TOK_STAR:
  1.1144 -      case TOK_SLASH:
  1.1145 -      case TOK_PERCENT:
  1.1146 -      case TOK_AMPERSAND:
  1.1147 -      case TOK_BITOR:
  1.1148 -      case TOK_BITXOR:
  1.1149 -      case TOK_SHR:
  1.1150 -      case TOK_USHR:
  1.1151 -      case TOK_SHL:
  1.1152 -        return new (pool_) HBinary(node, left->type(), token, left, right);
  1.1153 -
  1.1154 -      case TOK_EQUALS:
  1.1155 -      case TOK_NOTEQUALS:
  1.1156 -      case TOK_LT:
  1.1157 -      case TOK_LE:
  1.1158 -      case TOK_GT:
  1.1159 -      case TOK_GE:
  1.1160 -      case TOK_AND:
  1.1161 -      case TOK_OR:
  1.1162 -      {
  1.1163 -        Local<Type> result(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
  1.1164 -        return new (pool_) HBinary(node, result, token, left, right);
  1.1165 -      }
  1.1166 -
  1.1167 -      default:
  1.1168 -        assert(false);
  1.1169 -        return NULL;
  1.1170 -    }
  1.1171 -}
  1.1172 -
  1.1173 -static inline bool
  1.1174 -IsValidUncheckedType(Type *type)
  1.1175 -{
  1.1176 -    return type->isEnum() ||
  1.1177 -           type->isFloat() ||
  1.1178 -           type->isInt32() ||
  1.1179 -           type->isChar() ||
  1.1180 -           type->isUnchecked() ||
  1.1181 -           type->isBool();
  1.1182 -}
  1.1183 -
  1.1184 -void
  1.1185 -SemanticAnalysis::visitUnaryExpression(UnaryExpression *node)
  1.1186 -{
  1.1187 -    HIR *hir = eval(node->expression());
  1.1188 -    if (!hir)
  1.1189 -        return;
  1.1190 -
  1.1191 -    switch (node->token()) {
  1.1192 -      case TOK_TILDE:
  1.1193 -      {
  1.1194 -        if (!hir->type()->isInt32() && !hir->type()->isEnum()) {
  1.1195 -            char name[255];
  1.1196 -            cc_.reportError(node->pos(), Message_InvalidUnaryType,
  1.1197 -                            "~",
  1.1198 -                            GetTypeName(hir->type(), name, sizeof(name)));
  1.1199 -        }
  1.1200 -        Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
  1.1201 -        hir_ = new (pool_) HUnary(node, hir->type(), TOK_TILDE, hir);
  1.1202 -        return;
  1.1203 -      }
  1.1204 -
  1.1205 -      case TOK_MINUS:
  1.1206 -      {
  1.1207 -        if (hir->type()->isInt32() || hir->type()->isEnum()) {
  1.1208 -            Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
  1.1209 -            hir_ = new (pool_) HUnary(node, type, TOK_MINUS, hir);
  1.1210 -            return;
  1.1211 -        }
  1.1212 -        if (hir->type()->isFloat()) {
  1.1213 -            hir_ = new (pool_) HUnary(node, hir->type(), TOK_MINUS, hir);
  1.1214 -            return;
  1.1215 -        }
  1.1216 -
  1.1217 -        char name[255];
  1.1218 -        cc_.reportError(node->pos(), Message_InvalidUnaryType,
  1.1219 -                        "-",
  1.1220 -                        GetTypeName(hir->type(), name, sizeof(name)));
  1.1221 -        break;
  1.1222 -      }
  1.1223 -
  1.1224 -      default:
  1.1225 -      {
  1.1226 -        assert(node->token() == TOK_LABEL);
  1.1227 -
  1.1228 -        TypeSymbol *sym = node->tag()->sym()->asType();
  1.1229 -        if (!sym) {
  1.1230 -            cc_.reportError(node->pos(), Message_IdentifierIsNotAType,
  1.1231 -                            sym->name()->chars());
  1.1232 -            return;
  1.1233 -        }
  1.1234 -
  1.1235 -        if (!IsValidUncheckedType(sym->effective())) {
  1.1236 -            char name[255];
  1.1237 -            cc_.reportError(node->pos(), Message_InvalidUncheckedCastTo,
  1.1238 -                            GetTypeName(sym->type(), name, sizeof(name)));
  1.1239 -            return;
  1.1240 -        }
  1.1241 -        if (!IsValidUncheckedType(hir->type())) {
  1.1242 -            char name[255];
  1.1243 -            cc_.reportError(node->pos(), Message_InvalidUncheckedCastFrom,
  1.1244 -                            GetTypeName(hir->type(), name, sizeof(name)));
  1.1245 -            return;
  1.1246 -        }
  1.1247 -
  1.1248 -        hir_ = new (pool_) HUnary(node, sym->effective(), TOK_LABEL, hir);
  1.1249 -        break;
  1.1250 -      }
  1.1251 -    }
  1.1252 -}
  1.1253 -
  1.1254 -void
  1.1255 -SemanticAnalysis::import(HIR *hir, FieldExpression *node)
  1.1256 -{
  1.1257 -    // Note that we don't care if the hir type is "importable", since we
  1.1258 -    // can only do anything if the important has a constant binding.
  1.1259 -    unsigned index = hir->toImport()->index();
  1.1260 -    Local<Importable> importable(zone_, unit_->module()->getImportAt(index));
  1.1261 -
  1.1262 -    if (importable->isPackage()) {
  1.1263 -        // Look at what's already loaded and see if anything exists. We
  1.1264 -        // can't create stuff on-demand here since it's too late to add
  1.1265 -        // new translation units to the CompileContext.
  1.1266 -        Local<Package> package(zone_, Package::cast(importable));
  1.1267 -        Local<Importable> found(zone_, package->import(node->field()));
  1.1268 -        if (!found) {
  1.1269 -            cc_.reportError(node->pos(), Message_PackageDoesNotHaveMember, node->field()->chars());
  1.1270 -            return;
  1.1271 -        }
  1.1272 -
  1.1273 -        // If we did find something, make sure it is in our import list.
  1.1274 -        // If we didn't explicitly import it, we have no right to use it.
  1.1275 -        for (index = 0; index < unit_->module()->imports(); index++) {
  1.1276 -            if (unit_->module()->getImportAt(index) == importable)
  1.1277 -                break;
  1.1278 -        }
  1.1279 -
  1.1280 -        if (index == unit_->module()->imports()) {
  1.1281 -            cc_.reportError(node->pos(), Message_ImportWasNeverImported, node->field()->chars());
  1.1282 -            return;
  1.1283 -        }
  1.1284 -
  1.1285 -        // Just create a new HImport.
  1.1286 -        hir_ = new (pool_) HImport(node, hir->type(), index);
  1.1287 -    } else {
  1.1288 -        // Modules can never have sub-modules or sub-packages.
  1.1289 -        unsigned index;
  1.1290 -        Local<Module> module(zone_, Module::cast(importable));
  1.1291 -        Local<StructMap> map(zone_, module->globals()->map());
  1.1292 -        Local<Descriptor> desc(zone_, map->type()->lookupField(node->field(), &index));
  1.1293 -        if (!desc) {
  1.1294 -            cc_.reportError(node->pos(), Message_FieldNotFound, node->field()->chars());
  1.1295 -            return;
  1.1296 -        }
  1.1297 -        hir_ = new (pool_) HField(node, hir, desc->type(), index);
  1.1298 -    }
  1.1299 -}
  1.1300 -
  1.1301 -void
  1.1302 -SemanticAnalysis::visitFieldExpression(FieldExpression *node)
  1.1303 -{
  1.1304 -    HIR *hir = eval(node->left());
  1.1305 -    if (!hir)
  1.1306 -        return;
  1.1307 -
  1.1308 -    if (hir->isImport()) {
  1.1309 -        import(hir, node);
  1.1310 -        return;
  1.1311 -    }
  1.1312 -
  1.1313 -    char name[255];
  1.1314 -    cc_.reportError(node->pos(), Message_InvalidFieldExpression,
  1.1315 -                    GetTypeName(hir->type(), name, sizeof(name)));
  1.1316 -}
  1.1317 -
  1.1318 -static inline TokenKind
  1.1319 -ToCompare(Expression *expr)
  1.1320 -{
  1.1321 -    if (expr->isBinaryExpression()) {
  1.1322 -        BinaryExpression *b = expr->toBinaryExpression();
  1.1323 -        if (b->token() >= TOK_EQUALS && b->token() <= TOK_OR)
  1.1324 -            return b->token();
  1.1325 -    } else if (expr->isUnaryExpression()) {
  1.1326 -        UnaryExpression *u = expr->toUnaryExpression();
  1.1327 -        if (u->token() == TOK_NOT)
  1.1328 -            return TOK_NOT;
  1.1329 -    }
  1.1330 -    return TOK_EOF;
  1.1331 -}
  1.1332 -
  1.1333 -void
  1.1334 -SemanticAnalysis::visitForTest(Expression *expr,
  1.1335 -                               Label *trueBranch,
  1.1336 -                               Label *falseBranch,
  1.1337 -                               Label *fallthrough)
  1.1338 -{
  1.1339 -    Local<Type> boolType(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
  1.1340 -
  1.1341 -    TokenKind token = ToCompare(expr);
  1.1342 -    if (token == TOK_EOF || token == TOK_NOT) {
  1.1343 -        HIR *hir;
  1.1344 -        if (token == TOK_EOF)
  1.1345 -            hir = eval(expr);
  1.1346 -        else
  1.1347 -            hir = eval(expr->toUnaryExpression()->expression());
  1.1348 -        if (!hir)
  1.1349 -            return;
  1.1350 -        if ((hir = coerce(hir, boolType, Coerce_Arg)) == NULL)
  1.1351 -            return;
  1.1352 -
  1.1353 -        discharge(hir);
  1.1354 -
  1.1355 -        bool jumpOnTrue = (fallthrough == falseBranch) ^ (token == TOK_NOT);
  1.1356 -        Opcode op = jumpOnTrue ? OP_JT : OP_JF;
  1.1357 -        
  1.1358 -        if (fallthrough == falseBranch)
  1.1359 -            __ j(op, trueBranch);
  1.1360 -        else
  1.1361 -            __ j(op, falseBranch);
  1.1362 -        return;
  1.1363 -    }
  1.1364 -
  1.1365 -    BinaryExpression *bin = expr->toBinaryExpression();
  1.1366 -    if (token == TOK_AND || token == TOK_OR) {
  1.1367 -        Label next;
  1.1368 -        if (token == TOK_AND)
  1.1369 -            visitForTest(bin->left(), &next, falseBranch, &next);
  1.1370 -        else
  1.1371 -            visitForTest(bin->left(), trueBranch, &next, &next);
  1.1372 -        __ bind(&next);
  1.1373 -        visitForTest(bin->right(), trueBranch, falseBranch, fallthrough);
  1.1374 -        return;
  1.1375 -    }
  1.1376 -
  1.1377 -    HIR *left = eval(bin->left());
  1.1378 -    HIR *right = eval(bin->right());
  1.1379 -    if (!left || !right)
  1.1380 -        return;
  1.1381 -
  1.1382 -    HIR *hir = binary(bin, bin->token(), left, right);
  1.1383 -    if (!hir)
  1.1384 -        return;
  1.1385 -    if ((hir = coerce(hir, boolType, Coerce_Arg)) == NULL)
  1.1386 -        return;
  1.1387 -
  1.1388 -    discharge(hir);
  1.1389 -    if (fallthrough == trueBranch)
  1.1390 -        __ j(OP_JF, falseBranch);
  1.1391 -    else
  1.1392 -        __ j(OP_JT, trueBranch);
  1.1393 -}
  1.1394 -
  1.1395 -HLValue *
  1.1396 -SemanticAnalysis::lvalue(Expression *expr)
  1.1397 -{
  1.1398 -    HIR *hir = eval(expr);
  1.1399 -    if (!hir)
  1.1400 -        return NULL;
  1.1401 -    
  1.1402 -    if (!hir->isLValue()) {
  1.1403 -        cc_.reportError(expr->pos(), Message_ExpectedLValue);
  1.1404 -        return NULL;
  1.1405 -    }
  1.1406 -
  1.1407 -    return static_cast<HLValue *>(hir);
  1.1408 -}
  1.1409 -
  1.1410 -HIR *
  1.1411 -SemanticAnalysis::eval(Expression *expr)
  1.1412 -{
  1.1413 -    assert(!hir_);
  1.1414 -    expr->accept(this);
  1.1415 -
  1.1416 -    HIR *hir = hir_;
  1.1417 -    hir_ = NULL;
  1.1418 -
  1.1419 -    return hir;
  1.1420 -}
  1.1421 -
  1.1422 -void
  1.1423 -SemanticAnalysis::discharge(HIR *hir)
  1.1424 -{
  1.1425 -    EmitHIR(zone_, emitter_, hir);
  1.1426 -}
  1.1427 +/* vim: set ts=4 sw=4 tw=99 et:
  1.1428 + *
  1.1429 + * Copyright (C) 2012 David Anderson
  1.1430 + *
  1.1431 + * This file is part of SourcePawn.
  1.1432 + *
  1.1433 + * SourcePawn is free software: you can redistribute it and/or modify it under
  1.1434 + * the terms of the GNU General Public License as published by the Free
  1.1435 + * Software Foundation, either version 3 of the License, or (at your option)
  1.1436 + * any later version.
  1.1437 + * 
  1.1438 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
  1.1439 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  1.1440 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  1.1441 + *
  1.1442 + * You should have received a copy of the GNU General Public License along with
  1.1443 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
  1.1444 + */
  1.1445 +#include <assert.h>
  1.1446 +#include "../Zone.h"
  1.1447 +#include "../Strings.h"
  1.1448 +#include "../NativeTable.h"
  1.1449 +#include "../TypeManager.h"
  1.1450 +#include "../Modules.h"
  1.1451 +#include "../Code.h"
  1.1452 +#include "SemanticAnalysis.h"
  1.1453 +#include "../Heap-inl.h"
  1.1454 +
  1.1455 +using namespace ke;
  1.1456 +
  1.1457 +#define __ emitter_.
  1.1458 +
  1.1459 +typedef BytecodeEmitter::Label Label;
  1.1460 +
  1.1461 +class AutoEnterScope
  1.1462 +{
  1.1463 +  public:
  1.1464 +    AutoEnterScope(Scope **prevp, Scope *scope)
  1.1465 +      : prevp_(prevp),
  1.1466 +        prev_(*prevp),
  1.1467 +        scope_(scope)
  1.1468 +    {
  1.1469 +        if (!scope_)
  1.1470 +            return;
  1.1471 +        prev_ = *prevp_;
  1.1472 +        *prevp_ = scope;
  1.1473 +        assert(prev_ == scope->enclosing());
  1.1474 +    }
  1.1475 +    ~AutoEnterScope()
  1.1476 +    {
  1.1477 +        if (scope_)
  1.1478 +            *prevp_ = prev_;
  1.1479 +    }
  1.1480 +  private:
  1.1481 +    Scope **prevp_;
  1.1482 +    Scope *prev_;
  1.1483 +    Scope *scope_;
  1.1484 +};
  1.1485 +
  1.1486 +SemanticAnalysis::SemanticAnalysis(Zone *zone, CompileContext &cc, TranslationUnit *unit)
  1.1487 +  : zone_(zone),
  1.1488 +    pool_(zone->pool()),
  1.1489 +    cc_(cc),
  1.1490 +    unit_(unit),
  1.1491 +    hir_(NULL),
  1.1492 +    loop_(NULL)
  1.1493 +{
  1.1494 +}
  1.1495 +
  1.1496 +SemanticAnalysis::SemanticAnalysis(SemanticAnalysis *parent, Handle<FunctionType> fun)
  1.1497 +  : zone_(parent->zone_),
  1.1498 +    pool_(parent->pool_),
  1.1499 +    cc_(parent->cc_),
  1.1500 +    unit_(parent->unit_),
  1.1501 +    hir_(NULL),
  1.1502 +    scope_(parent->scope_),
  1.1503 +    fun_(fun),
  1.1504 +    loop_(NULL),
  1.1505 +    control_(NULL)
  1.1506 +{
  1.1507 +
  1.1508 +}
  1.1509 +
  1.1510 +void
  1.1511 +SemanticAnalysis::analyze()
  1.1512 +{
  1.1513 +    scope_ = unit_->globalScope();
  1.1514 +
  1.1515 +    for (size_t i = 0; i < unit_->tree()->statements()->length(); i++) {
  1.1516 +        Statement *stmt = unit_->tree()->statements()->at(i);
  1.1517 +        stmt->accept(this);
  1.1518 +    }
  1.1519 +
  1.1520 +    Local<Code> code(zone_, __ finish());
  1.1521 +    if (!code)
  1.1522 +        return;
  1.1523 +    code->setModule(unit_->module());
  1.1524 +    unit_->module()->setCode(code);
  1.1525 +
  1.1526 +#ifndef NDEBUG
  1.1527 +//    Disassemble(code, stdout);
  1.1528 +#endif
  1.1529 +}
  1.1530 +
  1.1531 +void
  1.1532 +SemanticAnalysis::visitFunctionStatement(FunctionStatement *stmt)
  1.1533 +{
  1.1534 +    FunctionSymbol *sym = stmt->sym();
  1.1535 +    Local<FunctionType> type(zone_, sym->type());
  1.1536 +
  1.1537 +    assert(scope_->kind() == Scope::GLOBAL);
  1.1538 +
  1.1539 +    if (stmt->token() == TOK_NATIVE) {
  1.1540 +        // Define the native now.
  1.1541 +        size_t index;
  1.1542 +        if (!zone_->nativeTable()->add(stmt->name(), &index))
  1.1543 +            return;
  1.1544 +
  1.1545 +        Local<Native> native(zone_, Native::New(zone_, type, index));
  1.1546 +        if (!native)
  1.1547 +            return;
  1.1548 +
  1.1549 +        __ object(native);
  1.1550 +        __ setglobal(sym);
  1.1551 +        __ pop();
  1.1552 +    }
  1.1553 +
  1.1554 +    // If the function is a forward or native, we don't have to do anything.
  1.1555 +    if (stmt->token() == TOK_NATIVE || stmt->token() == TOK_FORWARD)
  1.1556 +        return;
  1.1557 +
  1.1558 +    SemanticAnalysis child(this, type);
  1.1559 +    Local<Function> funobj(zone_, child.compile(stmt));
  1.1560 +    if (!funobj)
  1.1561 +        return;
  1.1562 +
  1.1563 +    __ object(funobj);
  1.1564 +    __ setglobal(sym);
  1.1565 +    if (stmt->token() == TOK_PUBLIC)
  1.1566 +        __ public_();
  1.1567 +    else
  1.1568 +        __ pop();
  1.1569 +}
  1.1570 +
  1.1571 +Function *
  1.1572 +SemanticAnalysis::compile(FunctionStatement *stmt)
  1.1573 +{
  1.1574 +    __ setFirstLine(stmt->pos().line);
  1.1575 +
  1.1576 +    AutoEnterScope argScope(&scope_, stmt->argScope());
  1.1577 +
  1.1578 +    for (size_t i = 0; i < stmt->signature().parameters()->length(); i++) {
  1.1579 +        Parameter *param = stmt->signature().parameters()->at(i);
  1.1580 +        param->sym()->allocate(VariableSymbol::Arg, i);
  1.1581 +    }
  1.1582 +
  1.1583 +    AutoEnterScope varScope(&scope_, stmt->varScope());
  1.1584 +    ControlStatus status = visitForControl(stmt->body());
  1.1585 +
  1.1586 +    if (!fun_->returnType()->isVoid()) {
  1.1587 +        // If the function is not void, report if not all paths return a value.
  1.1588 +        // All other incorrect return cases have been caught already.
  1.1589 +        if (status.returns() == Returns_Sometimes) {
  1.1590 +            cc_.reportError(stmt->pos(), Message_NotAllPathsReturnValue);
  1.1591 +            return NULL;
  1.1592 +        }
  1.1593 +
  1.1594 +        if (status.returns() == Returns_Never) {
  1.1595 +            cc_.reportError(stmt->pos(), Message_MissingReturnValue);
  1.1596 +            return NULL;
  1.1597 +        }
  1.1598 +    }
  1.1599 +
  1.1600 +    Local<Code> code(zone_, __ finish());
  1.1601 +    if (!code)
  1.1602 +        return NULL;
  1.1603 +    code->setModule(unit_->module());
  1.1604 +
  1.1605 +    Local<Function> fun(zone_, Function::New(zone_, code, fun_, stmt->name(), stmt->pos()));
  1.1606 +    if (!fun)
  1.1607 +        return NULL;
  1.1608 +
  1.1609 +#ifndef NDEBUG
  1.1610 +//    Disassemble(code, stdout);
  1.1611 +#endif
  1.1612 +
  1.1613 +    return fun;
  1.1614 +}
  1.1615 +
  1.1616 +void 
  1.1617 +SemanticAnalysis::visitBlockStatement(BlockStatement *node)
  1.1618 +{
  1.1619 +    AutoEnterScope scope(&scope_, node->scope());
  1.1620 +
  1.1621 +    for (size_t i = 0; i < node->statements()->length(); i++) {
  1.1622 +        Statement *stmt = node->statements()->at(i);
  1.1623 +        __ note_position(stmt->pos());
  1.1624 +        stmt->accept(this);
  1.1625 +        assert(__ stackDepth() == 0);
  1.1626 +    }
  1.1627 +}
  1.1628 +
  1.1629 +void
  1.1630 +SemanticAnalysis::visitEnumStatement(EnumStatement *node)
  1.1631 +{
  1.1632 +}
  1.1633 +
  1.1634 +void
  1.1635 +SemanticAnalysis::visitExpressionStatement(ExpressionStatement *node)
  1.1636 +{
  1.1637 +    // While building HIR, we enter new pool and root scopes, since HIR
  1.1638 +    // creation is purely temporary.
  1.1639 +    PoolScope poolScope(zone_->pool());
  1.1640 +    RootScope rootScope(zone_);
  1.1641 +
  1.1642 +    HIR *hir = eval(node->expression());
  1.1643 +    if (!hir)
  1.1644 +        return;
  1.1645 +
  1.1646 +    discharge(hir);
  1.1647 +    if (!hir->type()->isVoid())
  1.1648 +        __ pop();
  1.1649 +}
  1.1650 +
  1.1651 +void
  1.1652 +SemanticAnalysis::ControlScope::merge(const ControlStatus &left, const ControlStatus &right)
  1.1653 +{
  1.1654 +    // If both sides terminate in a return, we consider this a return as well.
  1.1655 +    if (left.returns() == Returns_Always && right.returns() == Returns_Always) {
  1.1656 +        terminate(Returns_Always);
  1.1657 +        return;
  1.1658 +    }
  1.1659 +
  1.1660 +    ReturnStatus status = (left.returns() == Returns_Never && right.returns() == Returns_Never)
  1.1661 +                          ? Returns_Never
  1.1662 +                          : Returns_Sometimes;
  1.1663 +
  1.1664 +    if (left.terminates() && right.terminates())
  1.1665 +        terminate(status);
  1.1666 +    else
  1.1667 +        returns(status);
  1.1668 +}
  1.1669 +
  1.1670 +SemanticAnalysis::ControlStatus
  1.1671 +SemanticAnalysis::visitForControl(Statement *statement)
  1.1672 +{
  1.1673 +    ControlScope scope(&control_);
  1.1674 +    statement->accept(this);
  1.1675 +    return scope.status();
  1.1676 +}
  1.1677 +
  1.1678 +void
  1.1679 +SemanticAnalysis::visitIfStatement(IfStatement *node)
  1.1680 +{
  1.1681 +    Label join;
  1.1682 +
  1.1683 +    ControlStatus trueBranch;
  1.1684 +    ControlStatus falseBranch(false, Returns_Never);
  1.1685 +
  1.1686 +    if (!node->ifFalse()) {
  1.1687 +        Label success;
  1.1688 +
  1.1689 +        visitForTest(node->condition(), &success, &join, &success);
  1.1690 +        __ bind(&success);
  1.1691 +        trueBranch = visitForControl(node->ifTrue());
  1.1692 +    } else {
  1.1693 +        Label success, next;
  1.1694 +
  1.1695 +        visitForTest(node->condition(), &success, &next, &success);
  1.1696 +        __ bind(&success);
  1.1697 +        trueBranch = visitForControl(node->ifTrue());
  1.1698 +        __ jump(&join);
  1.1699 +        __ bind(&next);
  1.1700 +        falseBranch = visitForControl(node->ifFalse());
  1.1701 +    }
  1.1702 +
  1.1703 +    __ bind(&join);
  1.1704 +
  1.1705 +    control_->merge(trueBranch, falseBranch);
  1.1706 +}
  1.1707 +
  1.1708 +void
  1.1709 +SemanticAnalysis::requireLifoStack()
  1.1710 +{
  1.1711 +    if (!loop_)
  1.1712 +        return;
  1.1713 +
  1.1714 +    loop_->setUsesLifoStack();
  1.1715 +}
  1.1716 +
  1.1717 +SemanticAnalysis::ControlStatus
  1.1718 +SemanticAnalysis::visitLoopBody(Statement *stmt)
  1.1719 +{
  1.1720 +    // We always mark off a loop body, so on each edge, we can balance the
  1.1721 +    // LIFO stack. Right now, we don't have the ability to budget the LIFO
  1.1722 +    // stack ahead of time. If we turn out to never need the LIFO stack, we
  1.1723 +    // mark it as unnecessary. (The interpreter can't really make use of this,
  1.1724 +    // but the JIT can).
  1.1725 +    //
  1.1726 +    // Note that balancing the LIFO stack isn't even necessary, so this
  1.1727 +    // feature may be removed. All this mechanism does is mitigate the
  1.1728 +    // possibility that a long-running loop will overflow the LIFO region
  1.1729 +    // and therefore start requiring nursery allocations.
  1.1730 +    int pos = __ enterloop();
  1.1731 +    ControlStatus status = visitForControl(stmt);
  1.1732 +    __ leaveloop();
  1.1733 +
  1.1734 +    if (loop_->usesLifoStack())
  1.1735 +        __ setLoopUsesLifoStack(pos);
  1.1736 +
  1.1737 +    return status;
  1.1738 +}
  1.1739 +
  1.1740 +void
  1.1741 +SemanticAnalysis::visitForStatement(ForStatement *node)
  1.1742 +{
  1.1743 +    AutoEnterScope scope(&scope_, node->scope());
  1.1744 +    PoolScope poolScope(zone_->pool());
  1.1745 +    RootScope rootScope(zone_);
  1.1746 +
  1.1747 +    Label join, update;
  1.1748 +    LoopScope loop(scope_, &join, &update, &loop_);
  1.1749 +
  1.1750 +    if (node->initialization())
  1.1751 +        node->initialization()->accept(this);
  1.1752 +
  1.1753 +    Label header, test;
  1.1754 +    if (node->condition())
  1.1755 +        __ jump(&test);
  1.1756 +
  1.1757 +    __ bind(&header);
  1.1758 +    ControlStatus status = visitLoopBody(node->body());
  1.1759 +
  1.1760 +    __ bind(&update);
  1.1761 +    if (node->update())
  1.1762 +        node->update()->accept(this);
  1.1763 +
  1.1764 +    if (node->condition()) {
  1.1765 +        __ bind(&test);
  1.1766 +        visitForTest(node->condition(), &header, &join, &join);
  1.1767 +    } else {
  1.1768 +        __ jump(&header);
  1.1769 +    }
  1.1770 +
  1.1771 +    __ bind(&join);
  1.1772 +    
  1.1773 +    // If there was a condition, we treat this like a while loop. Otherwise,
  1.1774 +    // the join point is only reachable if the loop contains a break. The
  1.1775 +    // termination status doesn't tell us anything yet.
  1.1776 +    if (node->condition() || loop.breaks())
  1.1777 +        control_->merge(status, ControlStatus(false, Returns_Never));
  1.1778 +    else
  1.1779 +        control_->terminate(status.returns());
  1.1780 +
  1.1781 +    assert(__ stackDepth() == 0);
  1.1782 +}
  1.1783 +
  1.1784 +void
  1.1785 +SemanticAnalysis::visitWhileStatement(WhileStatement *node)
  1.1786 +{
  1.1787 +    PoolScope poolScope(zone_->pool());
  1.1788 +    RootScope rootScope(zone_);
  1.1789 +
  1.1790 +    Label header, join;
  1.1791 +
  1.1792 +    __ bind(&header);
  1.1793 +
  1.1794 +    ControlStatus status;
  1.1795 +
  1.1796 +    LoopScope loop(scope_, &join, &header, &loop_);
  1.1797 +    if (node->token() == TOK_WHILE) {
  1.1798 +        Label body;
  1.1799 +        visitForTest(node->condition(), &body, &join, &body);
  1.1800 +        status = visitLoopBody(node->body());
  1.1801 +        __ jump(&header);
  1.1802 +    } else {
  1.1803 +        status = visitLoopBody(node->body());
  1.1804 +        visitForTest(node->condition(), &header, &join, &join);
  1.1805 +    }
  1.1806 +
  1.1807 +    __ bind(&join);
  1.1808 +
  1.1809 +    // Detect loops that will always have a fork in the contro-flow graph.
  1.1810 +    // This will be a |while| loop, or a |do-while| loop whose body does
  1.1811 +    // not terminate. For now, we treat these as an |if| regardless of the
  1.1812 +    // direction the branch can take. That means the control-flow is always
  1.1813 +    // conditional.
  1.1814 +    if (node->token() == TOK_WHILE || status.terminates() || loop.breaks()) {
  1.1815 +        control_->merge(status, ControlStatus(false, Returns_Never));
  1.1816 +    } else {
  1.1817 +        // At this point, we've got a do-while loop with a |return| or
  1.1818 +        // |continue|, meaning that the rest of the block is unreachable.
  1.1819 +        control_->terminate(status.returns());
  1.1820 +    }
  1.1821 +
  1.1822 +    assert(__ stackDepth() == 0);
  1.1823 +}
  1.1824 +
  1.1825 +static inline Heap::Tenure
  1.1826 +InferTenure(Symbol *sym)
  1.1827 +{
  1.1828 +    if (sym->scope()->kind() == Scope::GLOBAL)
  1.1829 +        return Heap::Tenure_Old;
  1.1830 +
  1.1831 +    // SP2's array semantics allow any array kind to escape, so we must use
  1.1832 +    // the normal heap. (Hopefully escape analysis can ease this pain later).
  1.1833 +    if (sym->type()->isArray())
  1.1834 +        return Heap::Tenure_Default;
  1.1835 +
  1.1836 +    return Heap::Tenure_Default;
  1.1837 +}
  1.1838 +
  1.1839 +void
  1.1840 +SemanticAnalysis::visitVariableDeclaration(VariableDeclaration *node)
  1.1841 +{
  1.1842 +    PoolScope poolScope(zone_->pool());
  1.1843 +    RootScope rootScope(zone_);
  1.1844 +
  1.1845 +    Local<Type> type(zone_, node->sym()->type());
  1.1846 +
  1.1847 +    if (node->sym()->type()->isVoid()) {
  1.1848 +        cc_.reportError(node->type()->pos(), Message_CannotDeclareVoid);
  1.1849 +        return;
  1.1850 +    }
  1.1851 +
  1.1852 +    if (node->initialization()) {
  1.1853 +        HIR *hir = NULL;
  1.1854 +
  1.1855 +        if ((hir = eval(node->initialization())) == NULL)
  1.1856 +            return;
  1.1857 +        if ((hir = coerce(hir, type, Coerce_Decl)) == NULL)
  1.1858 +            return;
  1.1859 +
  1.1860 +        discharge(hir);
  1.1861 +    } else {
  1.1862 +        if (type->isInt32() || type->isEnum() ||
  1.1863 +            type->isChar() || type->isBool())
  1.1864 +        {
  1.1865 +            __ int_(0);
  1.1866 +        } else if (type->isFloat()) {
  1.1867 +            __ float_(0);
  1.1868 +        } else if (type->isArray()) {
  1.1869 +            Local<ArrayType> atype(zone_, ArrayType::cast(type));
  1.1870 +            Local<ArrayMap> map(zone_, atype->newMap());
  1.1871 +            if (!map)
  1.1872 +                return;
  1.1873 +
  1.1874 +            if (atype->isFixedLength()) {
  1.1875 +                __ newarray(OP_NEWFIXED, map, InferTenure(node->sym()));
  1.1876 +            } else if (node->dims()->at(0)) {
  1.1877 +                // This may not be true if we allow typedefing, so :TODO:
  1.1878 +                // figure out proper semantics.
  1.1879 +                assert(node->dims()->length() == atype->levels());
  1.1880 +
  1.1881 +                Local<Type> i32(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
  1.1882 +                for (size_t i = 0; i < node->dims()->length(); i++) {
  1.1883 +                    Expression *expr = node->dims()->at(i);
  1.1884 +                    if (expr) {
  1.1885 +                        HIR *hir = eval(expr);
  1.1886 +                        if (!hir || ((hir = coerce(hir, i32, Coerce_Arg)) == NULL))
  1.1887 +                            return;
  1.1888 +                        discharge(hir);
  1.1889 +                    } else {
  1.1890 +                        __ int_(0);
  1.1891 +                    }
  1.1892 +                }
  1.1893 +                __ newarray(OP_NEWSIZED, map, InferTenure(node->sym()));
  1.1894 +            } else {
  1.1895 +                __ newarray(OP_NEWEMPTY, map, InferTenure(node->sym()));
  1.1896 +            }
  1.1897 +        } else {
  1.1898 +            assert(false);
  1.1899 +        }
  1.1900 +    }
  1.1901 +
  1.1902 +    if (node->sym()->scope()->kind() != Scope::GLOBAL) {
  1.1903 +        if (!__ allocate(node->sym()))
  1.1904 +            return;
  1.1905 +    }
  1.1906 +
  1.1907 +    set(node->sym());
  1.1908 +    __ pop();
  1.1909 +}
  1.1910 +
  1.1911 +void
  1.1912 +SemanticAnalysis::visitReturnStatement(ReturnStatement *node)
  1.1913 +{
  1.1914 +    control_->returns(Returns_Always);
  1.1915 +
  1.1916 +    if (!node->expression()) {
  1.1917 +        if (!fun_->returnType()->isVoid()) {
  1.1918 +            cc_.reportError(node->pos(), Message_MissingReturnValue);
  1.1919 +            return;
  1.1920 +        }
  1.1921 +
  1.1922 +        __ returnvoid();
  1.1923 +        return;
  1.1924 +    }
  1.1925 +
  1.1926 +    if (fun_->returnType()->isVoid()) {
  1.1927 +        cc_.reportError(node->pos(), Message_UsedVoidReturn);
  1.1928 +        return;
  1.1929 +    }
  1.1930 +
  1.1931 +    PoolScope poolScope(zone_->pool());
  1.1932 +    RootScope rootScope(zone_);
  1.1933 +
  1.1934 +    HIR *hir = eval(node->expression());
  1.1935 +    if (!hir)
  1.1936 +        return;
  1.1937 +
  1.1938 +    Local<Type> returnType(zone_, fun_->returnType());
  1.1939 +    if ((hir = coerce(hir, returnType, Coerce_Return)) == NULL)
  1.1940 +        return;
  1.1941 +
  1.1942 +    discharge(hir);
  1.1943 +
  1.1944 +    if (hir->type()->isVoid())
  1.1945 +        __ returnvoid();
  1.1946 +    else
  1.1947 +        __ return_();
  1.1948 +}
  1.1949 +
  1.1950 +void
  1.1951 +SemanticAnalysis::visitBinaryExpression(BinaryExpression *node)
  1.1952 +{
  1.1953 +    HIR *left = eval(node->left());
  1.1954 +    HIR *right = eval(node->right());
  1.1955 +    if (!left || !right)
  1.1956 +        return;
  1.1957 +
  1.1958 +    hir_ = binary(node, node->token(), left, right);
  1.1959 +}
  1.1960 +
  1.1961 +bool
  1.1962 +SemanticAnalysis::checkArgumentCount(Handle<FunctionType> type, unsigned actual)
  1.1963 +{
  1.1964 +    if (type->parameters()->length() == actual)
  1.1965 +        return true;
  1.1966 +
  1.1967 +    if (actual > type->parameters()->length()) {
  1.1968 +        if (!type->isNative() || !type->isNativeVariadic())
  1.1969 +            return false;
  1.1970 +        return true;
  1.1971 +    }
  1.1972 +
  1.1973 +    if (!type->defaults())
  1.1974 +        return false;
  1.1975 +
  1.1976 +    // Missing arguments. See if there's a default argument for each missing
  1.1977 +    // actual.
  1.1978 +    for (unsigned i = actual; i < type->parameters()->length(); i++) {
  1.1979 +        if (!type->defaults()->at(i))
  1.1980 +            return false;
  1.1981 +    }
  1.1982 +
  1.1983 +    return true;
  1.1984 +}
  1.1985 +
  1.1986 +static unsigned
  1.1987 +BindImplicitName(Module *from, ImplicitSymbol *sym)
  1.1988 +{
  1.1989 +    if (sym->bound())
  1.1990 +        return sym->fieldIndex();
  1.1991 +
  1.1992 +    Module *module = Module::cast(from->getImportAt(sym->index()));
  1.1993 +    StructMap *map = module->globals()->map();
  1.1994 +
  1.1995 +    unsigned fieldIndex;
  1.1996 +    Descriptor *desc = map->type()->lookupField(sym->name(), &fieldIndex);
  1.1997 +    assert(desc && desc->type() == sym->type());
  1.1998 +
  1.1999 +    sym->bind(fieldIndex);
  1.2000 +    return fieldIndex;
  1.2001 +}
  1.2002 +
  1.2003 +void
  1.2004 +SemanticAnalysis::visitNameProxy(NameProxy *proxy)
  1.2005 +{
  1.2006 +    Symbol *sym = proxy->sym();
  1.2007 +
  1.2008 +    switch (sym->kind()) {
  1.2009 +      case Symbol::kImport:
  1.2010 +      {
  1.2011 +        ImportSymbol *import = sym->toImport();
  1.2012 +        hir_ = new (pool_) HImport(proxy, sym->type(), import->index());
  1.2013 +        break;
  1.2014 +      }
  1.2015 +
  1.2016 +      case Symbol::kImplicit:
  1.2017 +      {
  1.2018 +        ImplicitSymbol *import = sym->toImplicit();
  1.2019 +        unsigned fieldIndex = BindImplicitName(unit_->module(), import);
  1.2020 +
  1.2021 +        hir_ = new (pool_) HImport(proxy, zone_->types()->getImportable(), import->index());
  1.2022 +        hir_ = new (pool_) HField(proxy, hir_, sym->type(), fieldIndex);
  1.2023 +        break;
  1.2024 +      }
  1.2025 +
  1.2026 +      case Symbol::kConstant:
  1.2027 +      {
  1.2028 +        ConstantSymbol *val = sym->toConstant();
  1.2029 +        hir_ = new (pool_) HInteger(proxy, sym->type(), val->value().toInt());
  1.2030 +        break;
  1.2031 +      }
  1.2032 +      
  1.2033 +      // This is kind of screwy. Symbol::kFunction is like a constant we can't
  1.2034 +      // evaluate yet. Maybe we should extract the GLOBAL case and say that
  1.2035 +      // kFunction is only used for global functions (and use const vars for
  1.2036 +      // local functions).
  1.2037 +      case Symbol::kFunction:
  1.2038 +      case Symbol::kVariable:
  1.2039 +      {
  1.2040 +        Scope *in = sym->scope();
  1.2041 +        switch (in->kind()) {
  1.2042 +          case Scope::GLOBAL:
  1.2043 +            hir_ = new (pool_) HGlobal(proxy, sym);
  1.2044 +            break;
  1.2045 +
  1.2046 +          case Scope::FUNCTION:
  1.2047 +          {
  1.2048 +            VariableSymbol *var = sym->toVariable();
  1.2049 +            assert(var->storage() == VariableSymbol::Arg);
  1.2050 +            hir_ = new (pool_) HLocal(proxy, var);
  1.2051 +            break;
  1.2052 +          }
  1.2053 +
  1.2054 +          default:
  1.2055 +          {
  1.2056 +            VariableSymbol *var = sym->toVariable();
  1.2057 +            assert(in->kind() == Scope::BLOCK);
  1.2058 +            assert(var->storage() == VariableSymbol::Local);
  1.2059 +            hir_ = new (pool_) HLocal(proxy, var);
  1.2060 +            break;
  1.2061 +          }
  1.2062 +        }
  1.2063 +        break;
  1.2064 +      }
  1.2065 +
  1.2066 +      default:
  1.2067 +        // :TODO:
  1.2068 +        assert(false);
  1.2069 +    }
  1.2070 +}
  1.2071 +
  1.2072 +void
  1.2073 +SemanticAnalysis::visitBooleanLiteral(BooleanLiteral *node)
  1.2074 +{
  1.2075 +    Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
  1.2076 +    hir_ = new (pool_) HBoolean(node, type, node->token() == TOK_TRUE);
  1.2077 +}
  1.2078 +
  1.2079 +void
  1.2080 +SemanticAnalysis::visitIntegerLiteral(IntegerLiteral *lit)
  1.2081 +{
  1.2082 +    Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
  1.2083 +    hir_ = new (pool_) HInteger(lit, type, lit->value());
  1.2084 +}
  1.2085 +
  1.2086 +void
  1.2087 +SemanticAnalysis::visitFloatLiteral(FloatLiteral *node)
  1.2088 +{
  1.2089 +    Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Float));
  1.2090 +    hir_ = new (pool_) HFloat(node, type, (float)node->value());
  1.2091 +}
  1.2092 +
  1.2093 +void
  1.2094 +SemanticAnalysis::visitStringLiteral(StringLiteral *node)
  1.2095 +{
  1.2096 +    Type *type = zone_->types()->getString();
  1.2097 +    hir_ = new (pool_) HString(node, type, node->string());
  1.2098 +}
  1.2099 +
  1.2100 +void
  1.2101 +SemanticAnalysis::visitCallExpression(CallExpression *node)
  1.2102 +{
  1.2103 +    HIR *callee = eval(node->callee());
  1.2104 +    if (!callee)
  1.2105 +        return;
  1.2106 +
  1.2107 +    if (!callee->type()->isFunction()) {
  1.2108 +        cc_.reportError(node->pos(), Message_CalleeNotFunction);
  1.2109 +        return;
  1.2110 +    }
  1.2111 +
  1.2112 +    Local<FunctionType> fun(zone_, FunctionType::cast(callee->type()));
  1.2113 +    
  1.2114 +    if (!checkArgumentCount(fun, node->arguments()->length())) {
  1.2115 +        cc_.reportError(node->pos(), Message_ArgumentCountMismatch);
  1.2116 +        return;
  1.2117 +    }
  1.2118 +
  1.2119 +    if (fun->isForward()) {
  1.2120 +        cc_.reportError(node->pos(), Message_ForwardNotImplemented, fun->name()->chars());
  1.2121 +        return;
  1.2122 +    }
  1.2123 +
  1.2124 +    HIRList *args = new (pool_) HIRList;
  1.2125 +    for (unsigned i = 0; i < node->arguments()->length(); i++) {
  1.2126 +        Expression *expression = node->arguments()->at(i);
  1.2127 +        HIR *arg = eval(expression);
  1.2128 +        if (!arg)
  1.2129 +            return;
  1.2130 +
  1.2131 +        Handle<Type> given = arg->type();
  1.2132 +        
  1.2133 +        bool mustComputeReference;
  1.2134 +        if (i >= fun->parameters()->length()) {
  1.2135 +            // Special handling for natives. Arguments past the formal must
  1.2136 +            // always have references computed. However, arrays are already
  1.2137 +            // references for natives.
  1.2138 +            assert(fun->isNative() && fun->isNativeVariadic());
  1.2139 +            mustComputeReference = !given->isReference() &&
  1.2140 +                                   !given->isArray();
  1.2141 +        } else {
  1.2142 +            Local<Type> actual(zone_, fun->parameterAt(i));
  1.2143 +
  1.2144 +            if (expression->isIndexExpression() && arg->isIndex()) {
  1.2145 +                // If the expression is the form x[y], and this produced a
  1.2146 +                // normal array indexing operation, then we apply some 
  1.2147 +                // special rules.
  1.2148 +
  1.2149 +                if (actual->isReference()) {
  1.2150 +                    // Disabled, since this doesn't have easily definable or
  1.2151 +                    // sensible semantics with SP2 arrays, but we don't want
  1.2152 +                    // to silently break SP1 semantics.
  1.2153 +                    cc_.reportError(expression->pos(), Message_CannotComputeIndexRef);
  1.2154 +                    return;
  1.2155 +                }
  1.2156 +
  1.2157 +                // As a special rule to account for SP1 semantics, we allow x[y]
  1.2158 +                // to automatically compute a sliced, read-only array view if
  1.2159 +                // the desired type is an array of one more dimension than x[y]
  1.2160 +                // would return.
  1.2161 +                //
  1.2162 +                // As an additional restriction, this is only allowed for
  1.2163 +                // one-level char arrays, to minimize potential issues until
  1.2164 +                // we determine whether more compatibility is needed.
  1.2165 +                //
  1.2166 +                // Internally, for sanity, the dependent array operation does
  1.2167 +                // not necessarily create a dependent array. For extensible
  1.2168 +                // arrays, we instead create a duplicate arrary of just the
  1.2169 +                // sliced portion, rather than deal with the complexity of the
  1.2170 +                // source array being resized.
  1.2171 +                //
  1.2172 +                // Note that we don't really know whether a dependent array
  1.2173 +                // will be dependent at compile-time, so the dependent type's
  1.2174 +                // just inherits from the source.
  1.2175 +                if (actual->isArray()) {
  1.2176 +                    HIndex *index = arg->toIndex();
  1.2177 +                    Local<ArrayType> basetype(zone_, ArrayType::cast(index->base()->type()));
  1.2178 +                    Local<ArrayType> atype(zone_, ArrayType::cast(actual));
  1.2179 +
  1.2180 +                    if (atype->isCharArray() && basetype->isCharArray()) {
  1.2181 +                        // There is no possible way this will type check, so
  1.2182 +                        // it's safe to just try something completely
  1.2183 +                        // different.
  1.2184 +                        Local<Type> slicetype(zone_);
  1.2185 +                        if (basetype->isFixedLength()) {
  1.2186 +                            // If the base type is fixed length, we need to
  1.2187 +                            // compute a new dynamic array type based on the
  1.2188 +                            // fixed array's contents and qualifiers.
  1.2189 +                            Local<Type> contained(zone_, basetype->contained());
  1.2190 +                            slicetype = zone_->types()->newArray(contained, ArrayType::DYNAMIC_ARRAY_SIZE);
  1.2191 +                            if (!slicetype)
  1.2192 +                                return;
  1.2193 +                            slicetype = zone_->types()->qualify(slicetype, basetype->quals());
  1.2194 +                            if (!slicetype)
  1.2195 +                                return;
  1.2196 +                        } else {
  1.2197 +                            slicetype = basetype;
  1.2198 +                        }
  1.2199 +                        arg = new (pool_) HNewDependentArray(expression, slicetype, index->base(), index->index());
  1.2200 +                        given = arg->type();
  1.2201 +                    }
  1.2202 +                }
  1.2203 +            }
  1.2204 +
  1.2205 +            if (actual->isReference()) {
  1.2206 +                // If the actual is a reference, the coercion rules are much
  1.2207 +                // stricter; the contained types must be identical.
  1.2208 +                // :TODO: make this not an assert
  1.2209 +                assert(ReferenceType::cast(actual)->contained() == arg->type());
  1.2210 +            } else {
  1.2211 +                // When we start overloading, coercion will have to happen later.
  1.2212 +                arg = coerce(arg, actual, Coerce_Arg);
  1.2213 +                if (!arg)
  1.2214 +                    return;
  1.2215 +            }
  1.2216 +
  1.2217 +            mustComputeReference = actual->isReference() && !given->isReference();
  1.2218 +        }
  1.2219 +
  1.2220 +        if (mustComputeReference) {
  1.2221 +            // Refs always use the LIFO stack if they can.
  1.2222 +            arg = new (pool_) HToRef(arg->node(), arg->type(), arg);
  1.2223 +            requireLifoStack();
  1.2224 +        }
  1.2225 +
  1.2226 +        if (!args->append(arg))
  1.2227 +            return;
  1.2228 +    }
  1.2229 +
  1.2230 +    hir_ = new (pool_) HCall(node, fun->returnType(), callee, args);
  1.2231 +}
  1.2232 +
  1.2233 +void
  1.2234 +SemanticAnalysis::visitAssignment(Assignment *node)
  1.2235 +{
  1.2236 +    HLValue *lval = lvalue(node->lvalue());
  1.2237 +    if (!lval)
  1.2238 +        return;
  1.2239 +
  1.2240 +    if (lval->type()->quals() & TypeQual_Const) {
  1.2241 +        cc_.reportError(node->pos(), Message_CannotModifyConst);
  1.2242 +        return;
  1.2243 +    }
  1.2244 +
  1.2245 +    HIR *hir = eval(node->expression());
  1.2246 +    if (!hir)
  1.2247 +        return;
  1.2248 +    if ((hir = coerce(hir, lval->type(), Coerce_Assign)) == NULL)
  1.2249 +        return;
  1.2250 +
  1.2251 +    hir_ = new (pool_) HStore(node, node->token(), lval, hir);
  1.2252 +}
  1.2253 +
  1.2254 +void
  1.2255 +SemanticAnalysis::visitBreakStatement(BreakStatement *node)
  1.2256 +{
  1.2257 +    if (!loop_) {
  1.2258 +        cc_.reportError(node->pos(), Message_BreakOutsideLoop);
  1.2259 +        return;
  1.2260 +    }
  1.2261 +
  1.2262 +    loop_->setBreaks();
  1.2263 +    __ j(OP_BREAK, loop_->break_());
  1.2264 +}
  1.2265 +
  1.2266 +void
  1.2267 +SemanticAnalysis::visitContinueStatement(ContinueStatement *node)
  1.2268 +{
  1.2269 +    if (!loop_) {
  1.2270 +        cc_.reportError(node->pos(), Message_ContinueOutsideLoop);
  1.2271 +        return;
  1.2272 +    }
  1.2273 +
  1.2274 +    __ j(OP_CONTINUE, loop_->continue_());
  1.2275 +}
  1.2276 +
  1.2277 +void
  1.2278 +SemanticAnalysis::visitIndexExpression(IndexExpression *node)
  1.2279 +{
  1.2280 +    HIR *left = eval(node->left());
  1.2281 +    if (!left)
  1.2282 +        return;
  1.2283 +
  1.2284 +    HIR *right = eval(node->right());
  1.2285 +    if (!right)
  1.2286 +        return;
  1.2287 +
  1.2288 +    // Hrm... yes, for now, let's coerce here.
  1.2289 +    Local<Type> i32(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
  1.2290 +    if ((right = coerce(right, i32, Coerce_Arg)) == NULL)
  1.2291 +        return;
  1.2292 +    
  1.2293 +    // Do not coerce here, there's no reason to yet.
  1.2294 +    if (!left->type()->isArray()) {
  1.2295 +        cc_.reportError(node->left()->pos(), Message_IndexBaseMustBeArray);
  1.2296 +        return;
  1.2297 +    }
  1.2298 +
  1.2299 +    hir_ = new (pool_) HIndex(node,
  1.2300 +                              ArrayType::cast(left->type())->contained(),
  1.2301 +                              left,
  1.2302 +                              right);
  1.2303 +}
  1.2304 +
  1.2305 +void
  1.2306 +SemanticAnalysis::visitIncDecExpression(IncDecExpression *node)
  1.2307 +{
  1.2308 +    HLValue *lval = lvalue(node->expression());
  1.2309 +    if (!lval)
  1.2310 +        return;
  1.2311 +
  1.2312 +    if (!lval->type()->isInt32() && !lval->type()->isFloat()) {
  1.2313 +        assert(false);
  1.2314 +        return;
  1.2315 +    }
  1.2316 +
  1.2317 +    HIR *rval;
  1.2318 +    if (lval->type()->isInt32())
  1.2319 +        rval = new (pool_) HInteger(node, lval->type(), 1);
  1.2320 +    else
  1.2321 +        rval = new (pool_) HFloat(node, lval->type(), 1.0);
  1.2322 +
  1.2323 +    if (node->postfix())
  1.2324 +        hir_ = new (pool_) HPostIncDec(node, node->token(), lval, rval);
  1.2325 +    else
  1.2326 +        hir_ = new (pool_) HStore(node, node->token(), lval, rval);
  1.2327 +}
  1.2328 +
  1.2329 +Type *
  1.2330 +SemanticAnalysis::coercionType(TokenKind token, HIR *left, HIR *right)
  1.2331 +{
  1.2332 +    Local<Type> l(zone_, left->type());
  1.2333 +    Local<Type> r(zone_, right->type());
  1.2334 +
  1.2335 +    if (l->isPod())
  1.2336 +        l = l->unqualified();
  1.2337 +    if (r->isPod())
  1.2338 +        r = r->unqualified();
  1.2339 +
  1.2340 +    if ((token >= TOK_PLUS && token <= TOK_SLASH) ||
  1.2341 +        (token >= TOK_EQUALS && token <= TOK_GE))
  1.2342 +    {
  1.2343 +        // We allow: [float|int32] + [float|int32]
  1.2344 +        if (l->isFloat() && r->isInt32())
  1.2345 +            return l;
  1.2346 +        if (l->isInt32() && r->isFloat())
  1.2347 +            return r;
  1.2348 +        if (l->isInt32() && r->isInt32())
  1.2349 +            return l;
  1.2350 +
  1.2351 +        if (l->isChar() && r->isInt32())
  1.2352 +             return r;
  1.2353 +        if (l->isInt32() && r->isChar())
  1.2354 +            return l;
  1.2355 +    }
  1.2356 +
  1.2357 +    // :TODO: remove
  1.2358 +    assert(*l == *r);
  1.2359 +
  1.2360 +    return left->type();
  1.2361 +}
  1.2362 +
  1.2363 +HIR *
  1.2364 +SemanticAnalysis::typeCheckArray(const SourcePosition &pos,
  1.2365 +                                 HIR *from,
  1.2366 +                                 Handle<ArrayType> argActual,
  1.2367 +                                 CoercionKind kind)
  1.2368 +{
  1.2369 +    Local<Type> argGiven(zone_, from->type());
  1.2370 +
  1.2371 +    // Special case: if we receive a string literal, and this is a char array,
  1.2372 +    // we allow a coercion.
  1.2373 +    if (from->isString() &&
  1.2374 +        argGiven->isString() &&
  1.2375 +        argActual->isArray() &&
  1.2376 +        ArrayType::cast(argActual)->isCharArray())
  1.2377 +    {
  1.2378 +        HString *hir = from->toString();
  1.2379 +        Local<ArrayType> actual(zone_, ArrayType::cast(argActual));
  1.2380 +
  1.2381 +        if (actual->isFixedLength()) {
  1.2382 +            if (hir->string()->length() + 1 > actual->fixedLength()) {
  1.2383 +                cc_.reportError(pos, Message_ArrayAssignmentTooBig);
  1.2384 +                return NULL;
  1.2385 +            }
  1.2386 +        }
  1.2387 +
  1.2388 +        // Transform the string literal into an array literal. We give it the
  1.2389 +        // type of the left-hand side. The constness of the destination type
  1.2390 +        // will determine whether HArray duplicates it or not.
  1.2391 +        Local<ArrayMap> map(zone_, actual->newMap());
  1.2392 +        if (!map)
  1.2393 +            return NULL;
  1.2394 +
  1.2395 +        Local<Array> array(zone_);
  1.2396 +        array = Array::NewString(zone_,
  1.2397 +                                 map,
  1.2398 +                                 hir->string()->chars(),
  1.2399 +                                 hir->string()->length(),
  1.2400 +                                 Heap::Tenure_Old);
  1.2401 +        if (!array)
  1.2402 +            return NULL;
  1.2403 +
  1.2404 +        // Since we're creating a canonical copy of the char array, we have to
  1.2405 +        // be careful that it doesn't get mutated. There are two cases where
  1.2406 +        // we know it can't be mutated, and therefore don't need to specify
  1.2407 +        // that it be cloned after pushing it onto the stack.
  1.2408 +        //
  1.2409 +        //  (1) The array type is const.
  1.2410 +        //  (2) The array type is fixed-length, and the coercion is for
  1.2411 +        //      assignment, meaning it will be immediately copied.
  1.2412 +        //
  1.2413 +        // We treat declaration separately from assignment, since for
  1.2414 +        // declaration we can just immediately use the cloned version.
  1.2415 +        bool shouldDuplicate = true;
  1.2416 +        if ((actual->quals() & TypeQual_Const) ||
  1.2417 +            (actual->isFixedLength() && kind == Coerce_Assign))
  1.2418 +        {
  1.2419 +            shouldDuplicate = false;
  1.2420 +        }
  1.2421 +
  1.2422 +        return new (pool_) HArray(hir->node(), actual, array, shouldDuplicate);
  1.2423 +    }
  1.2424 +
  1.2425 +    if (!argGiven->isArray()) {
  1.2426 +        cc_.reportError(pos, Message_ExpectedArray);
  1.2427 +        return NULL;
  1.2428 +    }
  1.2429 +
  1.2430 +    Local<ArrayType> actual(zone_, ArrayType::cast(argActual));
  1.2431 +    Local<ArrayType> given(zone_, ArrayType::cast(argGiven));
  1.2432 +
  1.2433 +    if (actual->levels() != given->levels()) {
  1.2434 +        cc_.reportError(pos, Message_ArrayDimensionsMismatch);
  1.2435 +        return NULL;
  1.2436 +    }
  1.2437 +
  1.2438 +    unsigned level = 1;
  1.2439 +    while (true) {
  1.2440 +        if (actual->isFixedLength()) {
  1.2441 +            if (!given->isFixedLength()) {
  1.2442 +                cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
  1.2443 +                return NULL;
  1.2444 +            }
  1.2445 +
  1.2446 +            if (actual->isCharArray()) {
  1.2447 +                // String assignment can have a truncated |given|.
  1.2448 +                if (given->fixedLength() > actual->fixedLength()) {
  1.2449 +                    cc_.reportError(pos, Message_ArrayAssignmentTooBig);
  1.2450 +                    return NULL;
  1.2451 +                }
  1.2452 +            } else {
  1.2453 +                if (given->fixedLength() != actual->fixedLength()) {
  1.2454 +                    cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
  1.2455 +                    return NULL;
  1.2456 +                }
  1.2457 +            }
  1.2458 +        } else if (given->isFixedLength()) {
  1.2459 +            // We do not allow assignments in the form:
  1.2460 +            //  [][] = [][Y]
  1.2461 +            //
  1.2462 +            // Otherwise, the following code could break the size guarantees
  1.2463 +            // of the right-hand side:
  1.2464 +            //
  1.2465 +            //  new x[][5];
  1.2466 +            //  new y[][];
  1.2467 +            //  new z[3];
  1.2468 +            //
  1.2469 +            //
  1.2470 +            //  y = x;
  1.2471 +            //  y[0] = z;
  1.2472 +            //
  1.2473 +            // Now |x[0]| contains a 3-length array.
  1.2474 +            if (level > 1) {
  1.2475 +                cc_.reportError(pos, Message_ArrayDimensionSizeMismatch, level);
  1.2476 +                return NULL;
  1.2477 +            }
  1.2478 +        }
  1.2479 +
  1.2480 +        if (!given->contained()->isArray() || !actual->contained()->isArray())
  1.2481 +            break;
  1.2482 +
  1.2483 +        given = ArrayType::cast(given->contained());
  1.2484 +        actual = ArrayType::cast(actual->contained());
  1.2485 +    }
  1.2486 +
  1.2487 +    bool givenConst = !!(given->contained()->quals() & TypeQual_Const);
  1.2488 +    bool actualConst = !!(actual->contained()->quals() & TypeQual_Const);
  1.2489 +
  1.2490 +    // These arrays must contain the same innermost type.
  1.2491 +    if (given->contained()->unqualified() != actual->contained()->unqualified() ||
  1.2492 +        (givenConst && !actualConst))
  1.2493 +    {
  1.2494 +        char aname[255];
  1.2495 +        char gname[255];
  1.2496 +        cc_.reportError(pos, Message_TypeMismatch,
  1.2497 +                        GetTypeName(argActual, aname, sizeof(aname)),
  1.2498 +                        GetTypeName(argGiven, gname, sizeof(gname)));
  1.2499 +        return NULL;
  1.2500 +    }
  1.2501 +
  1.2502 +    return from;
  1.2503 +}
  1.2504 +
  1.2505 +HIR *
  1.2506 +SemanticAnalysis::typeFailure(const SourcePosition &pos, Handle<Type> from, Handle<Type> to)
  1.2507 +{
  1.2508 +    char fname[255];
  1.2509 +    char tname[255];
  1.2510 +    cc_.reportError(pos, Message_InvalidCoercion,
  1.2511 +                    GetTypeName(from, fname, sizeof(fname)),
  1.2512 +                    GetTypeName(to, tname, sizeof(tname)));
  1.2513 +    return NULL;
  1.2514 +}
  1.2515 +
  1.2516 +HIR *
  1.2517 +SemanticAnalysis::coerce(HIR *hir, Handle<Type> to, CoercionKind kind)
  1.2518 +{
  1.2519 +    Local<Type> from(zone_, hir->type());
  1.2520 +
  1.2521 +    // If the source is *ever* an importable, we just fail.
  1.2522 +    if (from->isImportable())
  1.2523 +        return typeFailure(hir->node()->pos(), from, to);
  1.2524 +
  1.2525 +    if (from->isInt32() && to->isFloat())
  1.2526 +        return new (pool_) HConvert(hir->node(), to, OP_CVT_I2F, hir);
  1.2527 +    if (from->isInt32() && to->isBool())
  1.2528 +        return new (pool_) HConvert(hir->node(), to, OP_CVT_I2B, hir);
  1.2529 +
  1.2530 +    if (to->isEnum() && from->unqualified() != to->unqualified())
  1.2531 +        return typeFailure(hir->node()->pos(), from, to);
  1.2532 +    
  1.2533 +    if (to->isArray()) {
  1.2534 +        Local<ArrayType> atype(zone_, ArrayType::cast(to));
  1.2535 +        return typeCheckArray(hir->node()->pos(), hir, atype, kind);
  1.2536 +    }
  1.2537 +    
  1.2538 +    return hir;
  1.2539 +}
  1.2540 +
  1.2541 +void
  1.2542 +SemanticAnalysis::set(VariableSymbol *sym)
  1.2543 +{
  1.2544 +    if (sym->scope()->kind() == Scope::GLOBAL) {
  1.2545 +        __ setglobal(sym);
  1.2546 +    } else {
  1.2547 +        assert(sym->storage() == VariableSymbol::Local);
  1.2548 +        __ setlocal(sym);
  1.2549 +    }
  1.2550 +}
  1.2551 +
  1.2552 +HIR *
  1.2553 +SemanticAnalysis::binary(AstNode *node, TokenKind token, HIR *left, HIR *right)
  1.2554 +{
  1.2555 +    Local<Type> coercion(zone_, coercionType(token, left, right));
  1.2556 +    if (!coercion)
  1.2557 +        return NULL;
  1.2558 +    if ((left = coerce(left, coercion, Coerce_Arg)) == NULL)
  1.2559 +        return NULL;
  1.2560 +    if ((right = coerce(right, coercion, Coerce_Arg)) == NULL)
  1.2561 +        return NULL;
  1.2562 +    
  1.2563 +    switch (token) {
  1.2564 +     case TOK_PLUS:
  1.2565 +      case TOK_MINUS:
  1.2566 +      case TOK_STAR:
  1.2567 +      case TOK_SLASH:
  1.2568 +      case TOK_PERCENT:
  1.2569 +      case TOK_AMPERSAND:
  1.2570 +      case TOK_BITOR:
  1.2571 +      case TOK_BITXOR:
  1.2572 +      case TOK_SHR:
  1.2573 +      case TOK_USHR:
  1.2574 +      case TOK_SHL:
  1.2575 +        return new (pool_) HBinary(node, left->type(), token, left, right);
  1.2576 +
  1.2577 +      case TOK_EQUALS:
  1.2578 +      case TOK_NOTEQUALS:
  1.2579 +      case TOK_LT:
  1.2580 +      case TOK_LE:
  1.2581 +      case TOK_GT:
  1.2582 +      case TOK_GE:
  1.2583 +      case TOK_AND:
  1.2584 +      case TOK_OR:
  1.2585 +      {
  1.2586 +        Local<Type> result(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
  1.2587 +        return new (pool_) HBinary(node, result, token, left, right);
  1.2588 +      }
  1.2589 +
  1.2590 +      default:
  1.2591 +        assert(false);
  1.2592 +        return NULL;
  1.2593 +    }
  1.2594 +}
  1.2595 +
  1.2596 +static inline bool
  1.2597 +IsValidUncheckedType(Type *type)
  1.2598 +{
  1.2599 +    return type->isEnum() ||
  1.2600 +           type->isFloat() ||
  1.2601 +           type->isInt32() ||
  1.2602 +           type->isChar() ||
  1.2603 +           type->isUnchecked() ||
  1.2604 +           type->isBool();
  1.2605 +}
  1.2606 +
  1.2607 +void
  1.2608 +SemanticAnalysis::visitUnaryExpression(UnaryExpression *node)
  1.2609 +{
  1.2610 +    HIR *hir = eval(node->expression());
  1.2611 +    if (!hir)
  1.2612 +        return;
  1.2613 +
  1.2614 +    switch (node->token()) {
  1.2615 +      case TOK_TILDE:
  1.2616 +      {
  1.2617 +        if (!hir->type()->isInt32() && !hir->type()->isEnum()) {
  1.2618 +            char name[255];
  1.2619 +            cc_.reportError(node->pos(), Message_InvalidUnaryType,
  1.2620 +                            "~",
  1.2621 +                            GetTypeName(hir->type(), name, sizeof(name)));
  1.2622 +        }
  1.2623 +        Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
  1.2624 +        hir_ = new (pool_) HUnary(node, hir->type(), TOK_TILDE, hir);
  1.2625 +        return;
  1.2626 +      }
  1.2627 +
  1.2628 +      case TOK_MINUS:
  1.2629 +      {
  1.2630 +        if (hir->type()->isInt32() || hir->type()->isEnum()) {
  1.2631 +            Local<Type> type(zone_, zone_->types()->getPrimitive(PrimitiveType_Int32));
  1.2632 +            hir_ = new (pool_) HUnary(node, type, TOK_MINUS, hir);
  1.2633 +            return;
  1.2634 +        }
  1.2635 +        if (hir->type()->isFloat()) {
  1.2636 +            hir_ = new (pool_) HUnary(node, hir->type(), TOK_MINUS, hir);
  1.2637 +            return;
  1.2638 +        }
  1.2639 +
  1.2640 +        char name[255];
  1.2641 +        cc_.reportError(node->pos(), Message_InvalidUnaryType,
  1.2642 +                        "-",
  1.2643 +                        GetTypeName(hir->type(), name, sizeof(name)));
  1.2644 +        break;
  1.2645 +      }
  1.2646 +
  1.2647 +      default:
  1.2648 +      {
  1.2649 +        assert(node->token() == TOK_LABEL);
  1.2650 +
  1.2651 +        TypeSymbol *sym = node->tag()->sym()->asType();
  1.2652 +        if (!sym) {
  1.2653 +            cc_.reportError(node->pos(), Message_IdentifierIsNotAType,
  1.2654 +                            sym->name()->chars());
  1.2655 +            return;
  1.2656 +        }
  1.2657 +
  1.2658 +        if (!IsValidUncheckedType(sym->effective())) {
  1.2659 +            char name[255];
  1.2660 +            cc_.reportError(node->pos(), Message_InvalidUncheckedCastTo,
  1.2661 +                            GetTypeName(sym->type(), name, sizeof(name)));
  1.2662 +            return;
  1.2663 +        }
  1.2664 +        if (!IsValidUncheckedType(hir->type())) {
  1.2665 +            char name[255];
  1.2666 +            cc_.reportError(node->pos(), Message_InvalidUncheckedCastFrom,
  1.2667 +                            GetTypeName(hir->type(), name, sizeof(name)));
  1.2668 +            return;
  1.2669 +        }
  1.2670 +
  1.2671 +        hir_ = new (pool_) HUnary(node, sym->effective(), TOK_LABEL, hir);
  1.2672 +        break;
  1.2673 +      }
  1.2674 +    }
  1.2675 +}
  1.2676 +
  1.2677 +void
  1.2678 +SemanticAnalysis::import(HIR *hir, FieldExpression *node)
  1.2679 +{
  1.2680 +    // Note that we don't care if the hir type is "importable", since we
  1.2681 +    // can only do anything if the important has a constant binding.
  1.2682 +    unsigned index = hir->toImport()->index();
  1.2683 +    Local<Importable> importable(zone_, unit_->module()->getImportAt(index));
  1.2684 +
  1.2685 +    if (importable->isPackage()) {
  1.2686 +        // Look at what's already loaded and see if anything exists. We
  1.2687 +        // can't create stuff on-demand here since it's too late to add
  1.2688 +        // new translation units to the CompileContext.
  1.2689 +        Local<Package> package(zone_, Package::cast(importable));
  1.2690 +        Local<Importable> found(zone_, package->import(node->field()));
  1.2691 +        if (!found) {
  1.2692 +            cc_.reportError(node->pos(), Message_PackageDoesNotHaveMember, node->field()->chars());
  1.2693 +            return;
  1.2694 +        }
  1.2695 +
  1.2696 +        // If we did find something, make sure it is in our import list.
  1.2697 +        // If we didn't explicitly import it, we have no right to use it.
  1.2698 +        for (index = 0; index < unit_->module()->imports(); index++) {
  1.2699 +            if (unit_->module()->getImportAt(index) == importable)
  1.2700 +                break;
  1.2701 +        }
  1.2702 +
  1.2703 +        if (index == unit_->module()->imports()) {
  1.2704 +            cc_.reportError(node->pos(), Message_ImportWasNeverImported, node->field()->chars());
  1.2705 +            return;
  1.2706 +        }
  1.2707 +
  1.2708 +        // Just create a new HImport.
  1.2709 +        hir_ = new (pool_) HImport(node, hir->type(), index);
  1.2710 +    } else {
  1.2711 +        // Modules can never have sub-modules or sub-packages.
  1.2712 +        unsigned index;
  1.2713 +        Local<Module> module(zone_, Module::cast(importable));
  1.2714 +        Local<StructMap> map(zone_, module->globals()->map());
  1.2715 +        Local<Descriptor> desc(zone_, map->type()->lookupField(node->field(), &index));
  1.2716 +        if (!desc) {
  1.2717 +            cc_.reportError(node->pos(), Message_FieldNotFound, node->field()->chars());
  1.2718 +            return;
  1.2719 +        }
  1.2720 +        hir_ = new (pool_) HField(node, hir, desc->type(), index);
  1.2721 +    }
  1.2722 +}
  1.2723 +
  1.2724 +void
  1.2725 +SemanticAnalysis::visitFieldExpression(FieldExpression *node)
  1.2726 +{
  1.2727 +    HIR *hir = eval(node->left());
  1.2728 +    if (!hir)
  1.2729 +        return;
  1.2730 +
  1.2731 +    if (hir->isImport()) {
  1.2732 +        import(hir, node);
  1.2733 +        return;
  1.2734 +    }
  1.2735 +
  1.2736 +    char name[255];
  1.2737 +    cc_.reportError(node->pos(), Message_InvalidFieldExpression,
  1.2738 +                    GetTypeName(hir->type(), name, sizeof(name)));
  1.2739 +}
  1.2740 +
  1.2741 +static inline TokenKind
  1.2742 +ToCompare(Expression *expr)
  1.2743 +{
  1.2744 +    if (expr->isBinaryExpression()) {
  1.2745 +        BinaryExpression *b = expr->toBinaryExpression();
  1.2746 +        if (b->token() >= TOK_EQUALS && b->token() <= TOK_OR)
  1.2747 +            return b->token();
  1.2748 +    } else if (expr->isUnaryExpression()) {
  1.2749 +        UnaryExpression *u = expr->toUnaryExpression();
  1.2750 +        if (u->token() == TOK_NOT)
  1.2751 +            return TOK_NOT;
  1.2752 +    }
  1.2753 +    return TOK_EOF;
  1.2754 +}
  1.2755 +
  1.2756 +void
  1.2757 +SemanticAnalysis::visitForTest(Expression *expr,
  1.2758 +                               Label *trueBranch,
  1.2759 +                               Label *falseBranch,
  1.2760 +                               Label *fallthrough)
  1.2761 +{
  1.2762 +    Local<Type> boolType(zone_, zone_->types()->getPrimitive(PrimitiveType_Bool));
  1.2763 +
  1.2764 +    TokenKind token = ToCompare(expr);
  1.2765 +    if (token == TOK_EOF || token == TOK_NOT) {
  1.2766 +        HIR *hir;
  1.2767 +        if (token == TOK_EOF)
  1.2768 +            hir = eval(expr);
  1.2769 +        else
  1.2770 +            hir = eval(expr->toUnaryExpression()->expression());
  1.2771 +        if (!hir)
  1.2772 +            return;
  1.2773 +        if ((hir = coerce(hir, boolType, Coerce_Arg)) == NULL)
  1.2774 +            return;
  1.2775 +
  1.2776 +        discharge(hir);
  1.2777 +
  1.2778 +        bool jumpOnTrue = (fallthrough == falseBranch) ^ (token == TOK_NOT);
  1.2779 +        Opcode op = jumpOnTrue ? OP_JT : OP_JF;
  1.2780 +        
  1.2781 +        if (fallthrough == falseBranch)
  1.2782 +            __ j(op, trueBranch);
  1.2783 +        else
  1.2784 +            __ j(op, falseBranch);
  1.2785 +        return;
  1.2786 +    }
  1.2787 +
  1.2788 +    BinaryExpression *bin = expr->toBinaryExpression();
  1.2789 +    if (token == TOK_AND || token == TOK_OR) {
  1.2790 +        Label next;
  1.2791 +        if (token == TOK_AND)
  1.2792 +            visitForTest(bin->left(), &next, falseBranch, &next);
  1.2793 +        else
  1.2794 +            visitForTest(bin->left(), trueBranch, &next, &next);
  1.2795 +        __ bind(&next);
  1.2796 +        visitForTest(bin->right(), trueBranch, falseBranch, fallthrough);
  1.2797 +        return;
  1.2798 +    }
  1.2799 +
  1.2800 +    HIR *left = eval(bin->left());
  1.2801 +    HIR *right = eval(bin->right());
  1.2802 +    if (!left || !right)
  1.2803 +        return;
  1.2804 +
  1.2805 +    HIR *hir = binary(bin, bin->token(), left, right);
  1.2806 +    if (!hir)
  1.2807 +        return;
  1.2808 +    if ((hir = coerce(hir, boolType, Coerce_Arg)) == NULL)
  1.2809 +        return;
  1.2810 +
  1.2811 +    discharge(hir);
  1.2812 +    if (fallthrough == trueBranch)
  1.2813 +        __ j(OP_JF, falseBranch);
  1.2814 +    else
  1.2815 +        __ j(OP_JT, trueBranch);
  1.2816 +}
  1.2817 +
  1.2818 +HLValue *
  1.2819 +SemanticAnalysis::lvalue(Expression *expr)
  1.2820 +{
  1.2821 +    HIR *hir = eval(expr);
  1.2822 +    if (!hir)
  1.2823 +        return NULL;
  1.2824 +    
  1.2825 +    if (!hir->isLValue()) {
  1.2826 +        cc_.reportError(expr->pos(), Message_ExpectedLValue);
  1.2827 +        return NULL;
  1.2828 +    }
  1.2829 +
  1.2830 +    return static_cast<HLValue *>(hir);
  1.2831 +}
  1.2832 +
  1.2833 +HIR *
  1.2834 +SemanticAnalysis::eval(Expression *expr)
  1.2835 +{
  1.2836 +    assert(!hir_);
  1.2837 +    expr->accept(this);
  1.2838 +
  1.2839 +    HIR *hir = hir_;
  1.2840 +    hir_ = NULL;
  1.2841 +
  1.2842 +    return hir;
  1.2843 +}
  1.2844 +
  1.2845 +void
  1.2846 +SemanticAnalysis::discharge(HIR *hir)
  1.2847 +{
  1.2848 +    EmitHIR(zone_, emitter_, hir);
  1.2849 +}