jitcraft/Scopes.cpp
author David Anderson <dvander@alliedmods.net>
Sat Jun 30 19:38:53 2012 -0700 (2012-06-30)
changeset 12 75e385f68b7e
parent 2 46fc53b8fd2f
child 16 23627f8bc421
permissions -rw-r--r--
Refactored Array, Code to be Objects. Removed Object tagging.
     1 /*
     2  * Copyright (C) 2012 David Anderson
     3  *
     4  * This file is part of JITCraft.
     5  *
     6  * JITCraft is free software: you can redistribute it and/or modify it under
     7  * the terms of the GNU General Public License as published by the Free
     8  * Software Foundation, either version 3 of the License, or (at your option)
     9  * any later version.
    10  * 
    11  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along with
    16  * JITCraft. If not, see http://www.gnu.org/licenses/.
    17  */
    18 #include "Scopes.h"
    19 #include "Zone.h"
    20 #include "Types.h"
    21 #include "TypeManager.h"
    22 
    23 using namespace jc;
    24 
    25 Scope::Scope(PoolAllocator &pool, Kind kind, Scope *enclosing)
    26   : pool_(pool),
    27     kind_(kind),
    28     enclosing_(enclosing),
    29     locals_(0),
    30     maxContainedLocals_(0),
    31     numFunctions_(0),
    32     lifoSlot_(NULL)
    33 {
    34 }
    35 
    36 bool
    37 Scope::initialize()
    38 {
    39     if (enclosing_)
    40         enclosing_->children_.push_back(this);
    41     return true;
    42 }
    43 
    44 void
    45 Scope::unlink()
    46 {
    47     assert(empty());
    48 
    49     assert(enclosing_->children_[enclosing_->children_.size() - 1] == this);
    50     enclosing_->children_.pop_back();
    51 
    52     for (size_t i = 0; i < children_.size(); i++)
    53         enclosing_->children_.push_back(children_[i]);
    54 }
    55 
    56 Scope *
    57 Scope::unlinkIfEmpty()
    58 {
    59     if (empty()) {
    60         unlink();
    61         return NULL;
    62     }
    63     return this;
    64 }
    65 
    66 BoundName *
    67 Scope::localLookup(Name *name)
    68 {
    69     for (size_t i = 0; i < names_.size(); i++) {
    70         if (names_[i]->name() == name)
    71             return names_[i];
    72     }
    73     return NULL;
    74 }
    75 
    76 BoundName *
    77 Scope::lookup(Name *name)
    78 {
    79     for (Scope *scope = this; scope; scope = scope->enclosing()) {
    80         if (BoundName *bound = scope->localLookup(name))
    81             return bound;
    82     }
    83     return NULL;
    84 }
    85 
    86 Variable *
    87 Scope::declareVariable(Name *name)
    88 {
    89     assert(!localLookup(name));
    90     
    91     Variable *var = new (pool_) Variable(this, name);
    92     names_.push_back(var);
    93     return var;
    94 }
    95 
    96 Variable *
    97 Scope::declareArgument(Name *name)
    98 {
    99     assert(kind() == FUNCTION);
   100     Variable *var = declareVariable(name);
   101     names_.push_back(var);
   102     parameters_.push_back(var);
   103     return var;
   104 }
   105 
   106 NamedFunction *
   107 Scope::declareFunction(Name *name)
   108 {
   109     assert(!localLookup(name));
   110     assert(kind() == GLOBAL);
   111 
   112     NamedFunction *fun = new (pool_) NamedFunction(this, name);
   113     names_.push_back(fun);
   114     return fun;
   115 }
   116 
   117 NamedEnum *
   118 Scope::declareEnum(Name *name)
   119 {
   120     NamedEnum *e = new (pool_) NamedEnum(this, name);
   121     names_.push_back(e);
   122     return e;
   123 }
   124 
   125 NamedConstant *
   126 Scope::declareConstant(Name *name)
   127 {
   128     NamedConstant *constant = new (pool_) NamedConstant(this, name);
   129     names_.push_back(constant);
   130     return constant;
   131 }
   132 
   133 void
   134 Scope::allocateGlobals()
   135 {
   136     assert(kind() == GLOBAL);
   137 
   138     for (size_t i = 0; i < children_.size(); i++) {
   139         assert(children_[i]->kind() == FUNCTION);
   140         children_[i]->allocate();
   141     }
   142 
   143     for (size_t i = 0; i < names_.size(); i++) {
   144         BoundName *name = names_[i];
   145         
   146         if (name->kind() == FUNCTION) {
   147             NamedFunction *fun = name->toNamedFunction();
   148             fun->allocate(numFunctions_++);
   149         }
   150     }
   151 }
   152 
   153 void
   154 Scope::allocate(Variable *var)
   155 {
   156     if (!var->unallocated())
   157         return;
   158 
   159     var->allocate(Variable::STACK, maxContainedLocals_ + locals_);
   160     locals_++;
   161 }
   162 
   163 void
   164 Scope::allocate()
   165 {
   166     maxContainedLocals_ = 0;
   167     for (size_t i = 0; i < children_.size(); i++) {
   168         Scope *scope = children_[i];
   169         scope->allocate();
   170         if (scope->maxContainedLocals() > maxContainedLocals_)
   171             maxContainedLocals_ = scope->maxContainedLocals();
   172     }
   173 
   174     for (size_t i = 0; i < parameters_.size(); i++)
   175         parameters_[i]->allocate(Variable::PARAMETER, i);
   176 
   177     if (lifoSlot_)
   178         allocate(lifoSlot_);
   179     for (size_t i = 0; i < names_.size(); i++) {
   180         if (names_[i]->kind() != BoundName::VARIABLE)
   181             continue;
   182 
   183         allocate(names_[i]->toVariable());
   184     }
   185 
   186     maxContainedLocals_ += locals_;
   187 }
   188 
   189 bool
   190 Scope::Bind(ParseTree *tree)
   191 {
   192     for (size_t i = 0; i < tree->unbound()->size(); i++) {
   193         NameProxy *proxy = tree->unbound()->at(i);
   194         BoundName *name = tree->scope()->lookup(proxy->name());
   195         if (!name) {
   196             assert(false);
   197             return false;
   198         }
   199 
   200         proxy->bind(name);
   201     }
   202     return true;
   203 }
   204 
   205 void
   206 Scope::Allocate(ParseTree *tree)
   207 {
   208     tree->scope()->allocateGlobals();
   209 }
   210 
   211 void
   212 Scope::setUsesLifoHeap()
   213 {
   214     // Only one lifo slot is needed per scope.
   215     if (lifoSlot_)
   216         return;
   217 
   218     // If the parent of this scope is the function scope, then this is the
   219     // function's block scope, and the lifo slot is part of the Frame instead.
   220     assert(kind() != FUNCTION);
   221     if (enclosing()->kind() == FUNCTION)
   222         return;
   223 
   224     lifoSlot_ = new (pool_) Variable(this, NULL);
   225     lifoSlot_->setType(ZONE()->types()->getPrimitive(PrimitiveType_Native));
   226 }