Enable dynamic array declarations.
1 /* vim: set ts=4 sw=4 tw=99 et:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of JITCraft.
7 * JITCraft is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free
9 * Software Foundation, either version 3 of the License, or (at your option)
12 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with
17 * JITCraft. If not, see http://www.gnu.org/licenses/.
22 #include "TypeManager.h"
24 #include "CompileContext.h"
25 #include "Environments.h"
26 #include "Spaces-inl.h"
31 Scope::Scope(PoolAllocator &pool, Kind kind, Scope *enclosing)
34 maxContainedLocals_(0),
46 if (enclosing_ && !enclosing_->children_.append(this))
56 assert(enclosing_->children_[enclosing_->children_.length() - 1] == this);
57 enclosing_->children_.pop();
59 // OOM here is swallowed and checked after compilation.
60 // :TODO: make the above true.
61 for (size_t i = 0; i < children_.length(); i++)
62 enclosing_->children_.append(children_[i]);
66 Scope::unlinkIfEmpty()
76 Scope::localLookup(Handle<String> name)
78 for (size_t i = 0; i < names_.length(); i++) {
79 if (names_[i]->name() == name)
86 Scope::lookup(Handle<String> name)
88 for (Scope *scope = this; scope; scope = scope->enclosing()) {
89 if (BoundName *bound = scope->localLookup(name))
96 Scope::declareVariable(Handle<String> name, const SourcePosition &pos)
98 assert(!localLookup(name));
100 Variable *var = new (pool_) Variable(this, name, pos);
101 if (!names_.append(var))
107 Scope::declareArgument(Handle<String> name, const SourcePosition &pos)
109 assert(kind() == FUNCTION);
110 Variable *var = declareVariable(name, pos);
111 if (!names_.append(var))
113 if (!parameters_.append(var))
119 Scope::declareFunction(Handle<String> name, const SourcePosition &pos, TokenKind token)
121 assert(!localLookup(name));
122 assert(kind() == GLOBAL);
124 NamedFunction *fun = new (pool_) NamedFunction(this, name, pos, token);
125 if (!names_.append(fun))
131 Scope::declareConstant(Handle<String> name, const SourcePosition &pos)
133 NamedConstant *constant = new (pool_) NamedConstant(this, name, pos);
134 if (!names_.append(constant))
140 Scope::declareType(Handle<String> name, const SourcePosition &pos)
142 NamedType *decl = new (pool_) NamedType(this, name, pos);
143 if (!names_.append(decl))
149 Scope::declareType(Handle<String> name, Handle<Type> type)
151 NamedType *decl = new (pool_) NamedType(this, name, type);
152 if (!names_.append(decl))
158 Scope::allocateGlobals()
160 assert(kind() == GLOBAL);
162 for (size_t i = 0; i < children_.length(); i++) {
163 assert(children_[i]->kind() == FUNCTION);
164 children_[i]->allocate();
167 Local<Type> type(ZONE());
168 for (size_t i = 0; i < names_.length(); i++) {
169 BoundName *name = names_[i];
171 if (name->kind() == BoundName::FUNCTION) {
172 NamedFunction *fun = name->toNamedFunction();
177 fun->allocate(numNatives_++);
179 fun->allocate(numFunctions_++);
180 } else if (name->kind() == BoundName::VARIABLE) {
181 allocate(name->toVariable());
187 Scope::allocate(Variable *var)
189 if (!var->unallocated())
192 if (kind() == GLOBAL) {
193 var->allocate(Variable::ENVIRONMENT, envVars_.length());
194 envVars_.append(var);
196 var->allocate(Variable::STACK, maxContainedLocals_ + locals_);
204 maxContainedLocals_ = 0;
205 for (size_t i = 0; i < children_.length(); i++) {
206 Scope *scope = children_[i];
208 if (scope->maxContainedLocals() > maxContainedLocals_)
209 maxContainedLocals_ = scope->maxContainedLocals();
212 for (size_t i = 0; i < parameters_.length(); i++)
213 parameters_[i]->allocate(Variable::PARAMETER, i);
217 for (size_t i = 0; i < names_.length(); i++) {
218 if (names_[i]->kind() != BoundName::VARIABLE)
221 allocate(names_[i]->toVariable());
224 maxContainedLocals_ += locals_;
228 Scope::Bind(CompileContext &cc, ParseTree *tree)
230 Local<String> name(ZONE());
231 for (size_t i = 0; i < tree->unbound()->length(); i++) {
232 NameProxy *proxy = tree->unbound()->at(i);
233 name = proxy->name();
234 BoundName *binding = tree->scope()->lookup(name);
237 cc.reportError(proxy->pos(), Message_IdentifierNotFound, name->chars());
241 // We only allow global functions to be late-bound.
242 if (binding->kind() != BoundName::FUNCTION ||
243 binding->scope()->kind() != Scope::GLOBAL)
245 cc.reportError(proxy->pos(), Message_IdentifierNotFound, name->chars());
249 proxy->bind(binding);
251 // Find the function the proxy is defined in.
257 Scope::Allocate(ParseTree *tree)
259 tree->scope()->allocateGlobals();
263 Scope::setUsesLifoHeap()
265 // Only one lifo slot is needed per scope.
269 // If the parent of this scope is the function scope, then this is the
270 // function's block scope, and the lifo slot is part of the Frame instead.
271 // Note we can get a function scope here if we're making a temporary in a
272 // function with no local variables.
273 if (kind() == FUNCTION || enclosing()->kind() == FUNCTION)
276 Local<Type> type(ZONE(), ZONE()->types()->getPrimitive(PrimitiveType_Native));
280 Local<String> name(ZONE());
281 lifoSlot_ = new (pool_) Variable(this, name, SourcePosition());
282 lifoSlot_->setType(type);
286 Scope::createEnvironmentMap(Zone *zone)
288 return EnvironmentMap::New(zone, envVars_.length(), envVars_.buffer());