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@195: bool dvander@195: GlobalScope::addPublic(Symbol *sym) dvander@195: { dvander@195: return publics_.append(sym); dvander@195: } dvander@195: dvander@195: Symbol * dvander@195: GlobalScope::findPublic(Handle name) dvander@195: { dvander@195: for (size_t i = 0; i < publics_.length(); i++) { dvander@195: if (publics_[i]->name() == name) dvander@195: return publics_[i]; dvander@195: } dvander@195: return NULL; dvander@195: } dvander@195: dvander@195: Struct * dvander@195: GlobalScope::build(Zone *zone) dvander@85: { dvander@195: Local descriptors(zone, FixedArray::New(zone, names_.length(), Heap::Tenure_Old)); dvander@195: dvander@195: for (size_t i = 0; i < names_.length(); i++) { dvander@195: Handle name = names_[i]->name(); dvander@195: Handle type = names_[i]->type(); dvander@195: assert(type); dvander@195: dvander@195: Local desc(zone, Descriptor::New(zone, name, type)); dvander@195: if (!desc) dvander@195: return NULL; dvander@195: dvander@195: descriptors->set(zone, i, desc); dvander@195: } dvander@195: dvander@195: Local type(zone, StructType::New(zone, Handle::Null(), descriptors)); dvander@195: if (!type) dvander@195: return NULL; dvander@195: dvander@195: Local map(zone, type->newMap()); dvander@195: return Struct::New(zone, map, Heap::Tenure_Old); dvander@85: } dvander@195: 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: }