dvander@0: /* dvander@0: * Copyright (C) 2012 David Anderson dvander@0: * dvander@0: * This file is part of JITCraft. dvander@0: * dvander@0: * JITCraft is free software: you can redistribute it and/or modify it under dvander@0: * the terms of the GNU General Public License as published by the Free dvander@0: * Software Foundation, either version 3 of the License, or (at your option) dvander@0: * any later version. dvander@0: * dvander@0: * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY dvander@0: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@0: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@0: * dvander@0: * You should have received a copy of the GNU General Public License along with dvander@0: * JITCraft. If not, see http://www.gnu.org/licenses/. dvander@0: */ dvander@0: #include "Scopes.h" dvander@0: dvander@0: using namespace jc; dvander@0: dvander@0: Scope::Scope(PoolAllocator &pool, Kind kind, Scope *enclosing) dvander@0: : pool_(pool), dvander@0: kind_(kind), dvander@0: enclosing_(enclosing), dvander@0: locals_(0), dvander@0: maxContainedLocals_(0), dvander@0: numFunctions_(0) dvander@0: { dvander@0: } dvander@0: dvander@0: bool dvander@0: Scope::initialize() dvander@0: { dvander@0: if (enclosing_) dvander@0: enclosing_->children_.push_back(this); dvander@0: return true; dvander@0: } dvander@0: dvander@0: void dvander@0: Scope::unlink() dvander@0: { dvander@0: assert(empty()); dvander@0: dvander@0: assert(enclosing_->children_[enclosing_->children_.size() - 1] == this); dvander@0: enclosing_->children_.pop_back(); dvander@0: dvander@0: for (size_t i = 0; i < children_.size(); i++) dvander@0: enclosing_->children_.push_back(children_[i]); dvander@0: } dvander@0: dvander@0: Scope * dvander@0: Scope::unlinkIfEmpty() dvander@0: { dvander@0: if (empty()) { dvander@0: unlink(); dvander@0: return NULL; dvander@0: } dvander@0: return this; dvander@0: } dvander@0: dvander@0: BoundName * dvander@0: Scope::localLookup(Name *name) dvander@0: { dvander@0: for (size_t i = 0; i < names_.size(); i++) { dvander@0: if (names_[i]->name() == name) dvander@0: return names_[i]; dvander@0: } dvander@0: return NULL; dvander@0: } dvander@0: dvander@0: BoundName * dvander@0: Scope::lookup(Name *name) dvander@0: { dvander@0: for (Scope *scope = this; scope; scope = scope->enclosing()) { dvander@0: if (BoundName *bound = scope->localLookup(name)) dvander@0: return bound; dvander@0: } dvander@0: return NULL; dvander@0: } dvander@0: dvander@0: Variable * dvander@0: Scope::declareVariable(Name *name) dvander@0: { dvander@0: assert(!localLookup(name)); dvander@0: dvander@0: Variable *var = new (pool_) Variable(this, name); dvander@0: names_.push_back(var); dvander@0: return var; dvander@0: } dvander@0: dvander@0: Variable * dvander@0: Scope::declareArgument(Name *name) dvander@0: { dvander@0: assert(kind() == FUNCTION); dvander@0: Variable *var = declareVariable(name); dvander@0: names_.push_back(var); dvander@0: parameters_.push_back(var); dvander@0: return var; dvander@0: } dvander@0: dvander@0: NamedFunction * dvander@0: Scope::declareFunction(Name *name) dvander@0: { dvander@0: assert(!localLookup(name)); dvander@0: dvander@0: NamedFunction *fun = new (pool_) NamedFunction(this, name); dvander@0: names_.push_back(fun); dvander@0: return fun; dvander@0: } dvander@0: dvander@0: void dvander@0: Scope::allocateGlobals() dvander@0: { dvander@0: assert(kind() == GLOBAL); dvander@0: dvander@0: for (size_t i = 0; i < children_.size(); i++) { dvander@0: assert(children_[i]->kind() == FUNCTION); dvander@0: children_[i]->allocate(); dvander@0: } dvander@0: dvander@0: for (size_t i = 0; i < names_.size(); i++) { dvander@0: BoundName *name = names_[i]; dvander@0: dvander@0: NamedFunction *fun = name->toNamedFunction(); dvander@0: fun->allocate(numFunctions_++); dvander@0: } dvander@0: } dvander@0: dvander@0: void dvander@0: Scope::allocate() dvander@0: { dvander@0: maxContainedLocals_ = 0; dvander@0: for (size_t i = 0; i < children_.size(); i++) { dvander@0: Scope *scope = children_[i]; dvander@0: scope->allocate(); dvander@0: if (scope->maxContainedLocals() > maxContainedLocals_) dvander@0: maxContainedLocals_ = scope->maxContainedLocals(); dvander@0: } dvander@0: dvander@0: for (size_t i = 0; i < parameters_.size(); i++) dvander@0: parameters_[i]->allocate(Variable::PARAMETER, i); dvander@0: dvander@0: locals_ = 0; dvander@0: for (size_t i = 0; i < names_.size(); i++) { dvander@0: assert(names_[i]->kind() == BoundName::VARIABLE); dvander@0: dvander@0: Variable *var = names_[i]->toVariable(); dvander@0: if (var->unallocated()) { dvander@0: var->allocate(Variable::STACK, maxContainedLocals_ + locals_); dvander@0: locals_++; dvander@0: } dvander@0: } dvander@0: dvander@0: maxContainedLocals_ += locals_; dvander@0: } dvander@0: dvander@0: bool dvander@0: Scope::BindAndAllocate(ParseTree *tree) dvander@0: { dvander@0: for (size_t i = 0; i < tree->unbound()->size(); i++) { dvander@0: NameProxy *proxy = tree->unbound()->at(i); dvander@0: BoundName *name = tree->scope()->lookup(proxy->name()); dvander@0: if (!name) dvander@0: return false; dvander@0: dvander@0: proxy->bind(name); dvander@0: } dvander@0: dvander@0: tree->scope()->allocateGlobals(); dvander@0: return true; dvander@0: }