jitcraft/Scopes.cpp
author David Anderson <dvander@alliedmods.net>
Wed Jun 27 22:02:40 2012 -0700 (2012-06-27)
changeset 7 0478c27ba82c
parent 2 46fc53b8fd2f
child 12 75e385f68b7e
permissions -rw-r--r--
Added support for arrays of Floats.
     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 "Types.h"
    20 
    21 using namespace jc;
    22 
    23 Scope::Scope(PoolAllocator &pool, Kind kind, Scope *enclosing)
    24   : pool_(pool),
    25     kind_(kind),
    26     enclosing_(enclosing),
    27     locals_(0),
    28     maxContainedLocals_(0),
    29     numFunctions_(0)
    30 {
    31 }
    32 
    33 bool
    34 Scope::initialize()
    35 {
    36     if (enclosing_)
    37         enclosing_->children_.push_back(this);
    38     return true;
    39 }
    40 
    41 void
    42 Scope::unlink()
    43 {
    44     assert(empty());
    45 
    46     assert(enclosing_->children_[enclosing_->children_.size() - 1] == this);
    47     enclosing_->children_.pop_back();
    48 
    49     for (size_t i = 0; i < children_.size(); i++)
    50         enclosing_->children_.push_back(children_[i]);
    51 }
    52 
    53 Scope *
    54 Scope::unlinkIfEmpty()
    55 {
    56     if (empty()) {
    57         unlink();
    58         return NULL;
    59     }
    60     return this;
    61 }
    62 
    63 BoundName *
    64 Scope::localLookup(Name *name)
    65 {
    66     for (size_t i = 0; i < names_.size(); i++) {
    67         if (names_[i]->name() == name)
    68             return names_[i];
    69     }
    70     return NULL;
    71 }
    72 
    73 BoundName *
    74 Scope::lookup(Name *name)
    75 {
    76     for (Scope *scope = this; scope; scope = scope->enclosing()) {
    77         if (BoundName *bound = scope->localLookup(name))
    78             return bound;
    79     }
    80     return NULL;
    81 }
    82 
    83 Variable *
    84 Scope::declareVariable(Name *name)
    85 {
    86     assert(!localLookup(name));
    87     
    88     Variable *var = new (pool_) Variable(this, name);
    89     names_.push_back(var);
    90     return var;
    91 }
    92 
    93 Variable *
    94 Scope::declareArgument(Name *name)
    95 {
    96     assert(kind() == FUNCTION);
    97     Variable *var = declareVariable(name);
    98     names_.push_back(var);
    99     parameters_.push_back(var);
   100     return var;
   101 }
   102 
   103 NamedFunction *
   104 Scope::declareFunction(Name *name)
   105 {
   106     assert(!localLookup(name));
   107     assert(kind() == GLOBAL);
   108 
   109     NamedFunction *fun = new (pool_) NamedFunction(this, name);
   110     names_.push_back(fun);
   111     return fun;
   112 }
   113 
   114 NamedEnum *
   115 Scope::declareEnum(Name *name)
   116 {
   117     NamedEnum *e = new (pool_) NamedEnum(this, name);
   118     names_.push_back(e);
   119     return e;
   120 }
   121 
   122 NamedConstant *
   123 Scope::declareConstant(Name *name)
   124 {
   125     NamedConstant *constant = new (pool_) NamedConstant(this, name);
   126     names_.push_back(constant);
   127     return constant;
   128 }
   129 
   130 void
   131 Scope::allocateGlobals()
   132 {
   133     assert(kind() == GLOBAL);
   134 
   135     for (size_t i = 0; i < children_.size(); i++) {
   136         assert(children_[i]->kind() == FUNCTION);
   137         children_[i]->allocate();
   138     }
   139 
   140     for (size_t i = 0; i < names_.size(); i++) {
   141         BoundName *name = names_[i];
   142         
   143         if (name->kind() == FUNCTION) {
   144             NamedFunction *fun = name->toNamedFunction();
   145             fun->allocate(numFunctions_++);
   146         }
   147     }
   148 }
   149 
   150 void
   151 Scope::allocate()
   152 {
   153     maxContainedLocals_ = 0;
   154     for (size_t i = 0; i < children_.size(); i++) {
   155         Scope *scope = children_[i];
   156         scope->allocate();
   157         if (scope->maxContainedLocals() > maxContainedLocals_)
   158             maxContainedLocals_ = scope->maxContainedLocals();
   159     }
   160 
   161     for (size_t i = 0; i < parameters_.size(); i++)
   162         parameters_[i]->allocate(Variable::PARAMETER, i);
   163 
   164     locals_ = 0;
   165     for (size_t i = 0; i < names_.size(); i++) {
   166         if (names_[i]->kind() != BoundName::VARIABLE)
   167             continue;
   168 
   169         Variable *var = names_[i]->toVariable();
   170         if (var->unallocated()) {
   171             var->allocate(Variable::STACK, maxContainedLocals_ + locals_);
   172             locals_++;
   173         }
   174     }
   175 
   176     maxContainedLocals_ += locals_;
   177 }
   178 
   179 bool
   180 Scope::BindAndAllocate(ParseTree *tree)
   181 {
   182     for (size_t i = 0; i < tree->unbound()->size(); i++) {
   183         NameProxy *proxy = tree->unbound()->at(i);
   184         BoundName *name = tree->scope()->lookup(proxy->name());
   185         if (!name) {
   186             assert(false);
   187             return false;
   188         }
   189 
   190         proxy->bind(name);
   191     }
   192 
   193     tree->scope()->allocateGlobals();
   194     return true;
   195 }
   196 
   197 Variable *
   198 Scope::firstUnsafeArray()
   199 {
   200     for (size_t i = 0; i < names_.size(); i++) {
   201         if (names_[i]->kind() != BoundName::VARIABLE)
   202             continue;
   203         if (names_[i]->toVariable()->type()->isUnsafeArray())
   204             return names_[i]->toVariable();
   205     }
   206     return NULL;
   207 }