jitcraft/Scopes.cpp
author David Anderson <dvander@alliedmods.net>
Mon Jun 25 02:57:28 2012 -0700 (2012-06-25)
changeset 0 c455ebb9a5dc
child 1 27f12e2fc369
permissions -rw-r--r--
Initial import of prototype.
dvander@0
     1
/*
dvander@0
     2
 * Copyright (C) 2012 David Anderson
dvander@0
     3
 *
dvander@0
     4
 * This file is part of JITCraft.
dvander@0
     5
 *
dvander@0
     6
 * JITCraft is free software: you can redistribute it and/or modify it under
dvander@0
     7
 * the terms of the GNU General Public License as published by the Free
dvander@0
     8
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@0
     9
 * any later version.
dvander@0
    10
 * 
dvander@0
    11
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@0
    12
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@0
    13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@0
    14
 *
dvander@0
    15
 * You should have received a copy of the GNU General Public License along with
dvander@0
    16
 * JITCraft. If not, see http://www.gnu.org/licenses/.
dvander@0
    17
 */
dvander@0
    18
#include "Scopes.h"
dvander@0
    19
dvander@0
    20
using namespace jc;
dvander@0
    21
dvander@0
    22
Scope::Scope(PoolAllocator &pool, Kind kind, Scope *enclosing)
dvander@0
    23
  : pool_(pool),
dvander@0
    24
    kind_(kind),
dvander@0
    25
    enclosing_(enclosing),
dvander@0
    26
    locals_(0),
dvander@0
    27
    maxContainedLocals_(0),
dvander@0
    28
    numFunctions_(0)
dvander@0
    29
{
dvander@0
    30
}
dvander@0
    31
dvander@0
    32
bool
dvander@0
    33
Scope::initialize()
dvander@0
    34
{
dvander@0
    35
    if (enclosing_)
dvander@0
    36
        enclosing_->children_.push_back(this);
dvander@0
    37
    return true;
dvander@0
    38
}
dvander@0
    39
dvander@0
    40
void
dvander@0
    41
Scope::unlink()
dvander@0
    42
{
dvander@0
    43
    assert(empty());
dvander@0
    44
dvander@0
    45
    assert(enclosing_->children_[enclosing_->children_.size() - 1] == this);
dvander@0
    46
    enclosing_->children_.pop_back();
dvander@0
    47
dvander@0
    48
    for (size_t i = 0; i < children_.size(); i++)
dvander@0
    49
        enclosing_->children_.push_back(children_[i]);
dvander@0
    50
}
dvander@0
    51
dvander@0
    52
Scope *
dvander@0
    53
Scope::unlinkIfEmpty()
dvander@0
    54
{
dvander@0
    55
    if (empty()) {
dvander@0
    56
        unlink();
dvander@0
    57
        return NULL;
dvander@0
    58
    }
dvander@0
    59
    return this;
dvander@0
    60
}
dvander@0
    61
dvander@0
    62
BoundName *
dvander@0
    63
Scope::localLookup(Name *name)
dvander@0
    64
{
dvander@0
    65
    for (size_t i = 0; i < names_.size(); i++) {
dvander@0
    66
        if (names_[i]->name() == name)
dvander@0
    67
            return names_[i];
dvander@0
    68
    }
dvander@0
    69
    return NULL;
dvander@0
    70
}
dvander@0
    71
dvander@0
    72
BoundName *
dvander@0
    73
Scope::lookup(Name *name)
dvander@0
    74
{
dvander@0
    75
    for (Scope *scope = this; scope; scope = scope->enclosing()) {
dvander@0
    76
        if (BoundName *bound = scope->localLookup(name))
dvander@0
    77
            return bound;
dvander@0
    78
    }
dvander@0
    79
    return NULL;
dvander@0
    80
}
dvander@0
    81
dvander@0
    82
Variable *
dvander@0
    83
Scope::declareVariable(Name *name)
dvander@0
    84
{
dvander@0
    85
    assert(!localLookup(name));
dvander@0
    86
    
dvander@0
    87
    Variable *var = new (pool_) Variable(this, name);
dvander@0
    88
    names_.push_back(var);
dvander@0
    89
    return var;
dvander@0
    90
}
dvander@0
    91
dvander@0
    92
Variable *
dvander@0
    93
Scope::declareArgument(Name *name)
dvander@0
    94
{
dvander@0
    95
    assert(kind() == FUNCTION);
dvander@0
    96
    Variable *var = declareVariable(name);
dvander@0
    97
    names_.push_back(var);
dvander@0
    98
    parameters_.push_back(var);
dvander@0
    99
    return var;
dvander@0
   100
}
dvander@0
   101
dvander@0
   102
NamedFunction *
dvander@0
   103
Scope::declareFunction(Name *name)
dvander@0
   104
{
dvander@0
   105
    assert(!localLookup(name));
dvander@0
   106
dvander@0
   107
    NamedFunction *fun = new (pool_) NamedFunction(this, name);
dvander@0
   108
    names_.push_back(fun);
dvander@0
   109
    return fun;
dvander@0
   110
}
dvander@0
   111
dvander@0
   112
void
dvander@0
   113
Scope::allocateGlobals()
dvander@0
   114
{
dvander@0
   115
    assert(kind() == GLOBAL);
dvander@0
   116
dvander@0
   117
    for (size_t i = 0; i < children_.size(); i++) {
dvander@0
   118
        assert(children_[i]->kind() == FUNCTION);
dvander@0
   119
        children_[i]->allocate();
dvander@0
   120
    }
dvander@0
   121
dvander@0
   122
    for (size_t i = 0; i < names_.size(); i++) {
dvander@0
   123
        BoundName *name = names_[i];
dvander@0
   124
        
dvander@0
   125
        NamedFunction *fun = name->toNamedFunction();
dvander@0
   126
        fun->allocate(numFunctions_++);
dvander@0
   127
    }
dvander@0
   128
}
dvander@0
   129
dvander@0
   130
void
dvander@0
   131
Scope::allocate()
dvander@0
   132
{
dvander@0
   133
    maxContainedLocals_ = 0;
dvander@0
   134
    for (size_t i = 0; i < children_.size(); i++) {
dvander@0
   135
        Scope *scope = children_[i];
dvander@0
   136
        scope->allocate();
dvander@0
   137
        if (scope->maxContainedLocals() > maxContainedLocals_)
dvander@0
   138
            maxContainedLocals_ = scope->maxContainedLocals();
dvander@0
   139
    }
dvander@0
   140
dvander@0
   141
    for (size_t i = 0; i < parameters_.size(); i++)
dvander@0
   142
        parameters_[i]->allocate(Variable::PARAMETER, i);
dvander@0
   143
dvander@0
   144
    locals_ = 0;
dvander@0
   145
    for (size_t i = 0; i < names_.size(); i++) {
dvander@0
   146
        assert(names_[i]->kind() == BoundName::VARIABLE);
dvander@0
   147
dvander@0
   148
        Variable *var = names_[i]->toVariable();
dvander@0
   149
        if (var->unallocated()) {
dvander@0
   150
            var->allocate(Variable::STACK, maxContainedLocals_ + locals_);
dvander@0
   151
            locals_++;
dvander@0
   152
        }
dvander@0
   153
    }
dvander@0
   154
dvander@0
   155
    maxContainedLocals_ += locals_;
dvander@0
   156
}
dvander@0
   157
dvander@0
   158
bool
dvander@0
   159
Scope::BindAndAllocate(ParseTree *tree)
dvander@0
   160
{
dvander@0
   161
    for (size_t i = 0; i < tree->unbound()->size(); i++) {
dvander@0
   162
        NameProxy *proxy = tree->unbound()->at(i);
dvander@0
   163
        BoundName *name = tree->scope()->lookup(proxy->name());
dvander@0
   164
        if (!name)
dvander@0
   165
            return false;
dvander@0
   166
dvander@0
   167
        proxy->bind(name);
dvander@0
   168
    }
dvander@0
   169
dvander@0
   170
    tree->scope()->allocateGlobals();
dvander@0
   171
    return true;
dvander@0
   172
}