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