diff -r b029d63565a2 -r c1ba166f3fc4 src/Scopes.cpp --- a/src/Scopes.cpp Mon Sep 17 00:10:01 2012 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,289 +0,0 @@ -/* vim: set ts=4 sw=4 tw=99 et: - * - * Copyright (C) 2012 David Anderson - * - * This file is part of JITCraft. - * - * JITCraft is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) - * any later version. - * - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * JITCraft. If not, see http://www.gnu.org/licenses/. - */ -#include "Scopes.h" -#include "Zone.h" -#include "Types.h" -#include "TypeManager.h" -#include "Strings.h" -#include "CompileContext.h" -#include "Environments.h" -#include "Spaces-inl.h" -#include "Heap-inl.h" - -using namespace ke; - -Scope::Scope(PoolAllocator &pool, Kind kind, Scope *enclosing) - : pool_(pool), - locals_(0), - maxContainedLocals_(0), - numFunctions_(0), - numNatives_(0), - lifoSlot_(NULL), - kind_(kind), - enclosing_(enclosing) -{ -} - -bool -Scope::initialize() -{ - if (enclosing_ && !enclosing_->children_.append(this)) - return false; - return true; -} - -void -Scope::unlink() -{ - assert(empty()); - - assert(enclosing_->children_[enclosing_->children_.length() - 1] == this); - enclosing_->children_.pop(); - - // OOM here is swallowed and checked after compilation. - // :TODO: make the above true. - for (size_t i = 0; i < children_.length(); i++) - enclosing_->children_.append(children_[i]); -} - -Scope * -Scope::unlinkIfEmpty() -{ - if (empty()) { - unlink(); - return NULL; - } - return this; -} - -BoundName * -Scope::localLookup(Handle name) -{ - for (size_t i = 0; i < names_.length(); i++) { - if (names_[i]->name() == name) - return names_[i]; - } - return NULL; -} - -BoundName * -Scope::lookup(Handle name) -{ - for (Scope *scope = this; scope; scope = scope->enclosing()) { - if (BoundName *bound = scope->localLookup(name)) - return bound; - } - return NULL; -} - -Variable * -Scope::declareVariable(Handle name, const SourcePosition &pos) -{ - assert(!localLookup(name)); - - Variable *var = new (pool_) Variable(this, name, pos); - if (!names_.append(var)) - return NULL; - return var; -} - -Variable * -Scope::declareArgument(Handle name, const SourcePosition &pos) -{ - assert(kind() == FUNCTION); - Variable *var = declareVariable(name, pos); - if (!names_.append(var)) - return NULL; - if (!parameters_.append(var)) - return NULL; - return var; -} - -NamedFunction * -Scope::declareFunction(Handle name, const SourcePosition &pos, TokenKind token) -{ - assert(!localLookup(name)); - assert(kind() == GLOBAL); - - NamedFunction *fun = new (pool_) NamedFunction(this, name, pos, token); - if (!names_.append(fun)) - return NULL; - return fun; -} - -NamedConstant * -Scope::declareConstant(Handle name, const SourcePosition &pos) -{ - NamedConstant *constant = new (pool_) NamedConstant(this, name, pos); - if (!names_.append(constant)) - return NULL; - return constant; -} - -NamedType * -Scope::declareType(Handle name, const SourcePosition &pos) -{ - NamedType *decl = new (pool_) NamedType(this, name, pos); - if (!names_.append(decl)) - return NULL; - return decl; -} - -NamedType * -Scope::declareType(Handle name, Handle type) -{ - NamedType *decl = new (pool_) NamedType(this, name, type); - if (!names_.append(decl)) - return NULL; - return decl; -} - -void -Scope::allocateGlobals() -{ - assert(kind() == GLOBAL); - - for (size_t i = 0; i < children_.length(); i++) { - assert(children_[i]->kind() == FUNCTION); - children_[i]->allocate(); - } - - Local type(ZONE()); - for (size_t i = 0; i < names_.length(); i++) { - BoundName *name = names_[i]; - - if (name->kind() == BoundName::FUNCTION) { - NamedFunction *fun = name->toNamedFunction(); - if (!fun->used()) - continue; - - if (fun->isNative()) - fun->allocate(numNatives_++); - else - fun->allocate(numFunctions_++); - } else if (name->kind() == BoundName::VARIABLE) { - allocate(name->toVariable()); - } - } -} - -void -Scope::allocate(Variable *var) -{ - if (!var->unallocated()) - return; - - if (kind() == GLOBAL) { - var->allocate(Variable::ENVIRONMENT, envVars_.length()); - envVars_.append(var); - } else { - var->allocate(Variable::STACK, maxContainedLocals_ + locals_); - locals_++; - } -} - -void -Scope::allocate() -{ - maxContainedLocals_ = 0; - for (size_t i = 0; i < children_.length(); i++) { - Scope *scope = children_[i]; - scope->allocate(); - if (scope->maxContainedLocals() > maxContainedLocals_) - maxContainedLocals_ = scope->maxContainedLocals(); - } - - for (size_t i = 0; i < parameters_.length(); i++) - parameters_[i]->allocate(Variable::PARAMETER, i); - - if (lifoSlot_) - allocate(lifoSlot_); - for (size_t i = 0; i < names_.length(); i++) { - if (names_[i]->kind() != BoundName::VARIABLE) - continue; - - allocate(names_[i]->toVariable()); - } - - maxContainedLocals_ += locals_; -} - -bool -Scope::Bind(CompileContext &cc, ParseTree *tree) -{ - Local name(ZONE()); - for (size_t i = 0; i < tree->unbound()->length(); i++) { - NameProxy *proxy = tree->unbound()->at(i); - name = proxy->name(); - BoundName *binding = tree->scope()->lookup(name); - - if (!binding) { - cc.reportError(proxy->pos(), Message_IdentifierNotFound, name->chars()); - return false; - } - - // We only allow global functions to be late-bound. - if (binding->kind() != BoundName::FUNCTION || - binding->scope()->kind() != Scope::GLOBAL) - { - cc.reportError(proxy->pos(), Message_IdentifierNotFound, name->chars()); - return false; - } - - proxy->bind(binding); - - // Find the function the proxy is defined in. - } - return true; -} - -void -Scope::Allocate(ParseTree *tree) -{ - tree->scope()->allocateGlobals(); -} - -void -Scope::setUsesLifoHeap() -{ - // Only one lifo slot is needed per scope. - if (lifoSlot_) - return; - - // If the parent of this scope is the function scope, then this is the - // function's block scope, and the lifo slot is part of the Frame instead. - // Note we can get a function scope here if we're making a temporary in a - // function with no local variables. - if (kind() == FUNCTION || enclosing()->kind() == FUNCTION) - return; - - Local type(ZONE(), ZONE()->types()->getPrimitive(PrimitiveType_Native)); - if (!type) - return; - - Local name(ZONE()); - lifoSlot_ = new (pool_) Variable(this, name, SourcePosition()); - lifoSlot_->setType(type); -} - -EnvironmentMap * -Scope::createEnvironmentMap(Zone *zone) -{ - return EnvironmentMap::New(zone, envVars_.length(), envVars_.buffer()); -}