dvander@37: /* vim: set ts=4 sw=4 tw=99 et: dvander@37: * dvander@0: * Copyright (C) 2012 David Anderson dvander@0: * dvander@0: * This file is part of JITCraft. dvander@0: * dvander@0: * JITCraft is free software: you can redistribute it and/or modify it under dvander@0: * the terms of the GNU General Public License as published by the Free dvander@0: * Software Foundation, either version 3 of the License, or (at your option) dvander@0: * any later version. dvander@0: * dvander@0: * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY dvander@0: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@0: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@0: * dvander@0: * You should have received a copy of the GNU General Public License along with dvander@0: * JITCraft. If not, see http://www.gnu.org/licenses/. dvander@0: */ dvander@195: #include "../Zone.h" dvander@195: #include "../Types.h" dvander@195: #include "../TypeManager.h" dvander@195: #include "../Strings.h" dvander@195: #include "../Environments.h" dvander@195: #include "../Structures.h" dvander@195: #include "CompileContext.h" dvander@0: #include "Scopes.h" dvander@195: #include "../Spaces-inl.h" dvander@195: #include "../Heap-inl.h" dvander@0: dvander@59: using namespace ke; dvander@0: dvander@0: Scope::Scope(PoolAllocator &pool, Kind kind, Scope *enclosing) dvander@0: : pool_(pool), dvander@28: kind_(kind), dvander@28: enclosing_(enclosing) dvander@0: { dvander@0: } dvander@0: dvander@0: bool dvander@0: Scope::initialize() dvander@0: { dvander@58: if (enclosing_ && !enclosing_->children_.append(this)) dvander@58: return false; dvander@0: return true; dvander@0: } dvander@0: dvander@0: void dvander@0: Scope::unlink() dvander@0: { dvander@0: assert(empty()); dvander@0: dvander@58: assert(enclosing_->children_[enclosing_->children_.length() - 1] == this); dvander@58: enclosing_->children_.pop(); dvander@0: dvander@58: // OOM here is swallowed and checked after compilation. dvander@58: // :TODO: make the above true. dvander@58: for (size_t i = 0; i < children_.length(); i++) dvander@58: enclosing_->children_.append(children_[i]); dvander@0: } dvander@0: dvander@0: Scope * dvander@0: Scope::unlinkIfEmpty() dvander@0: { dvander@0: if (empty()) { dvander@0: unlink(); dvander@0: return NULL; dvander@0: } dvander@0: return this; dvander@0: } dvander@0: dvander@195: Symbol * dvander@54: Scope::localLookup(Handle name) dvander@0: { dvander@58: for (size_t i = 0; i < names_.length(); i++) { dvander@0: if (names_[i]->name() == name) dvander@0: return names_[i]; dvander@0: } dvander@0: return NULL; dvander@0: } dvander@0: dvander@195: Symbol * dvander@54: Scope::lookup(Handle name) dvander@0: { dvander@0: for (Scope *scope = this; scope; scope = scope->enclosing()) { dvander@195: if (Symbol *bound = scope->localLookup(name)) dvander@0: return bound; dvander@0: } dvander@0: return NULL; dvander@0: } dvander@0: dvander@195: #if 0 dvander@12: void dvander@12: Scope::setUsesLifoHeap() dvander@1: { dvander@12: // Only one lifo slot is needed per scope. dvander@195: #if 0 dvander@12: if (lifoSlot_) dvander@12: return; dvander@195: #endif dvander@12: dvander@12: // If the parent of this scope is the function scope, then this is the dvander@12: // function's block scope, and the lifo slot is part of the Frame instead. dvander@16: // Note we can get a function scope here if we're making a temporary in a dvander@16: // function with no local variables. dvander@16: if (kind() == FUNCTION || enclosing()->kind() == FUNCTION) dvander@12: return; dvander@12: dvander@37: Local type(ZONE(), ZONE()->types()->getPrimitive(PrimitiveType_Native)); dvander@37: if (!type) dvander@37: return; dvander@37: dvander@54: Local name(ZONE()); dvander@195: #if 0 dvander@54: lifoSlot_ = new (pool_) Variable(this, name, SourcePosition()); dvander@37: lifoSlot_->setType(type); dvander@195: #endif dvander@195: } dvander@195: #endif dvander@195: dvander@195: bool dvander@195: Scope::addSymbol(Symbol *sym) dvander@195: { dvander@195: return names_.append(sym); dvander@195: } dvander@195: dvander@195: LocalScope::LocalScope(PoolAllocator &pool) dvander@195: : Scope(pool, Scope::BLOCK, NULL) dvander@195: { dvander@195: } dvander@195: dvander@195: LocalScope * dvander@195: LocalScope::New(PoolAllocator &pool) dvander@195: { dvander@195: LocalScope *scope = new (pool) LocalScope(pool); dvander@195: if (!scope->initialize()) dvander@195: return NULL; dvander@195: dvander@195: return scope; dvander@195: } dvander@195: dvander@195: ArgumentScope::ArgumentScope(PoolAllocator &pool) dvander@195: : Scope(pool, Scope::FUNCTION, NULL) dvander@195: { dvander@195: } dvander@195: dvander@195: ArgumentScope * dvander@195: ArgumentScope::New(PoolAllocator &pool) dvander@195: { dvander@195: ArgumentScope *scope = new (pool) ArgumentScope(pool); dvander@195: if (!scope->initialize()) dvander@195: return NULL; dvander@195: dvander@195: return scope; dvander@195: } dvander@195: dvander@195: GlobalScope::GlobalScope(PoolAllocator &pool, ImportScope *parent) dvander@195: : Scope(pool, Scope::GLOBAL, parent) dvander@195: { dvander@1: } dvander@85: dvander@195: GlobalScope * dvander@195: GlobalScope::New(PoolAllocator &pool, ImportScope *parent) dvander@195: { dvander@195: GlobalScope *scope = new (pool) GlobalScope(pool, parent); dvander@195: if (!scope->initialize()) dvander@195: return NULL; dvander@195: dvander@195: return scope; dvander@195: } dvander@195: dvander@259: Symbol * dvander@259: GlobalScope::findExported(Handle name) dvander@259: { dvander@259: for (size_t i = 0; i < exported_.length(); i++) { dvander@259: if (exported_[i]->name() == name) dvander@259: return exported_[i]; dvander@259: } dvander@259: return NULL; dvander@259: } dvander@259: dvander@195: ImportScope::ImportScope(PoolAllocator &pool) dvander@195: : Scope(pool, Scope::IMPORT, NULL) dvander@195: { dvander@195: } dvander@195: dvander@195: ImportScope * dvander@195: ImportScope::New(PoolAllocator &pool) dvander@195: { dvander@195: ImportScope *scope = new (pool) ImportScope(pool); dvander@195: if (!scope->initialize()) dvander@195: return NULL; dvander@195: dvander@195: return scope; dvander@195: }