1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/jitcraft/Scopes.cpp Mon Jun 25 02:57:28 2012 -0700
1.3 @@ -0,0 +1,172 @@
1.4 +/*
1.5 + * Copyright (C) 2012 David Anderson
1.6 + *
1.7 + * This file is part of JITCraft.
1.8 + *
1.9 + * JITCraft is free software: you can redistribute it and/or modify it under
1.10 + * the terms of the GNU General Public License as published by the Free
1.11 + * Software Foundation, either version 3 of the License, or (at your option)
1.12 + * any later version.
1.13 + *
1.14 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
1.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.17 + *
1.18 + * You should have received a copy of the GNU General Public License along with
1.19 + * JITCraft. If not, see http://www.gnu.org/licenses/.
1.20 + */
1.21 +#include "Scopes.h"
1.22 +
1.23 +using namespace jc;
1.24 +
1.25 +Scope::Scope(PoolAllocator &pool, Kind kind, Scope *enclosing)
1.26 + : pool_(pool),
1.27 + kind_(kind),
1.28 + enclosing_(enclosing),
1.29 + locals_(0),
1.30 + maxContainedLocals_(0),
1.31 + numFunctions_(0)
1.32 +{
1.33 +}
1.34 +
1.35 +bool
1.36 +Scope::initialize()
1.37 +{
1.38 + if (enclosing_)
1.39 + enclosing_->children_.push_back(this);
1.40 + return true;
1.41 +}
1.42 +
1.43 +void
1.44 +Scope::unlink()
1.45 +{
1.46 + assert(empty());
1.47 +
1.48 + assert(enclosing_->children_[enclosing_->children_.size() - 1] == this);
1.49 + enclosing_->children_.pop_back();
1.50 +
1.51 + for (size_t i = 0; i < children_.size(); i++)
1.52 + enclosing_->children_.push_back(children_[i]);
1.53 +}
1.54 +
1.55 +Scope *
1.56 +Scope::unlinkIfEmpty()
1.57 +{
1.58 + if (empty()) {
1.59 + unlink();
1.60 + return NULL;
1.61 + }
1.62 + return this;
1.63 +}
1.64 +
1.65 +BoundName *
1.66 +Scope::localLookup(Name *name)
1.67 +{
1.68 + for (size_t i = 0; i < names_.size(); i++) {
1.69 + if (names_[i]->name() == name)
1.70 + return names_[i];
1.71 + }
1.72 + return NULL;
1.73 +}
1.74 +
1.75 +BoundName *
1.76 +Scope::lookup(Name *name)
1.77 +{
1.78 + for (Scope *scope = this; scope; scope = scope->enclosing()) {
1.79 + if (BoundName *bound = scope->localLookup(name))
1.80 + return bound;
1.81 + }
1.82 + return NULL;
1.83 +}
1.84 +
1.85 +Variable *
1.86 +Scope::declareVariable(Name *name)
1.87 +{
1.88 + assert(!localLookup(name));
1.89 +
1.90 + Variable *var = new (pool_) Variable(this, name);
1.91 + names_.push_back(var);
1.92 + return var;
1.93 +}
1.94 +
1.95 +Variable *
1.96 +Scope::declareArgument(Name *name)
1.97 +{
1.98 + assert(kind() == FUNCTION);
1.99 + Variable *var = declareVariable(name);
1.100 + names_.push_back(var);
1.101 + parameters_.push_back(var);
1.102 + return var;
1.103 +}
1.104 +
1.105 +NamedFunction *
1.106 +Scope::declareFunction(Name *name)
1.107 +{
1.108 + assert(!localLookup(name));
1.109 +
1.110 + NamedFunction *fun = new (pool_) NamedFunction(this, name);
1.111 + names_.push_back(fun);
1.112 + return fun;
1.113 +}
1.114 +
1.115 +void
1.116 +Scope::allocateGlobals()
1.117 +{
1.118 + assert(kind() == GLOBAL);
1.119 +
1.120 + for (size_t i = 0; i < children_.size(); i++) {
1.121 + assert(children_[i]->kind() == FUNCTION);
1.122 + children_[i]->allocate();
1.123 + }
1.124 +
1.125 + for (size_t i = 0; i < names_.size(); i++) {
1.126 + BoundName *name = names_[i];
1.127 +
1.128 + NamedFunction *fun = name->toNamedFunction();
1.129 + fun->allocate(numFunctions_++);
1.130 + }
1.131 +}
1.132 +
1.133 +void
1.134 +Scope::allocate()
1.135 +{
1.136 + maxContainedLocals_ = 0;
1.137 + for (size_t i = 0; i < children_.size(); i++) {
1.138 + Scope *scope = children_[i];
1.139 + scope->allocate();
1.140 + if (scope->maxContainedLocals() > maxContainedLocals_)
1.141 + maxContainedLocals_ = scope->maxContainedLocals();
1.142 + }
1.143 +
1.144 + for (size_t i = 0; i < parameters_.size(); i++)
1.145 + parameters_[i]->allocate(Variable::PARAMETER, i);
1.146 +
1.147 + locals_ = 0;
1.148 + for (size_t i = 0; i < names_.size(); i++) {
1.149 + assert(names_[i]->kind() == BoundName::VARIABLE);
1.150 +
1.151 + Variable *var = names_[i]->toVariable();
1.152 + if (var->unallocated()) {
1.153 + var->allocate(Variable::STACK, maxContainedLocals_ + locals_);
1.154 + locals_++;
1.155 + }
1.156 + }
1.157 +
1.158 + maxContainedLocals_ += locals_;
1.159 +}
1.160 +
1.161 +bool
1.162 +Scope::BindAndAllocate(ParseTree *tree)
1.163 +{
1.164 + for (size_t i = 0; i < tree->unbound()->size(); i++) {
1.165 + NameProxy *proxy = tree->unbound()->at(i);
1.166 + BoundName *name = tree->scope()->lookup(proxy->name());
1.167 + if (!name)
1.168 + return false;
1.169 +
1.170 + proxy->bind(name);
1.171 + }
1.172 +
1.173 + tree->scope()->allocateGlobals();
1.174 + return true;
1.175 +}