use std::any::TypeId;
use std::cell::{Ref, RefMut, RefCell};
use std::rc::{Rc, Weak};
use crate::function::{Function, Lambda};
use crate::io::GlobalIo;
use crate::lexer::CodeMap;
use crate::module::{BuiltinModuleLoader, ModuleRegistry};
use crate::name::{get_standard_name, get_system_fn, is_system_operator,
is_standard_value, NUM_STANDARD_VALUES,
SYSTEM_OPERATORS_END, Name, NameMap, NameSetSlice, NameStore};
use crate::structs::{ForeignStructDef, StructDef, StructDefMap, StructValue};
use crate::value::Value;
pub struct GlobalScope {
name: Name,
namespace: RefCell<Namespace>,
name_store: Rc<RefCell<NameStore>>,
codemap: Rc<RefCell<CodeMap>>,
modules: Rc<ModuleRegistry>,
io: Rc<GlobalIo>,
struct_defs: Rc<RefCell<StructDefMap>>,
}
#[derive(Clone)]
struct Namespace {
constants: NameMap<Value>,
macros: NameMap<Lambda>,
values: NameMap<Value>,
exports: Option<NameSetSlice>,
imports: Vec<ImportSet>,
module_doc: Option<String>,
docs: NameMap<String>,
}
#[derive(Clone)]
pub struct ImportSet {
pub module_name: Name,
pub names: Vec<(Name, Name)>,
}
impl ImportSet {
pub fn new(module_name: Name) -> ImportSet {
ImportSet{
module_name,
names: Vec::new(),
}
}
}
pub type Scope = Rc<GlobalScope>;
pub type WeakScope = Weak<GlobalScope>;
impl GlobalScope {
pub fn new(name: Name,
names: Rc<RefCell<NameStore>>,
codemap: Rc<RefCell<CodeMap>>,
registry: Rc<ModuleRegistry>,
io: Rc<GlobalIo>,
struct_defs: Rc<RefCell<StructDefMap>>) -> GlobalScope {
GlobalScope{
name,
namespace: RefCell::new(Namespace::new()),
name_store: names,
codemap,
modules: registry,
io,
struct_defs,
}
}
pub fn default(name: &str) -> GlobalScope {
let mut names = NameStore::new();
let name = names.add(name);
let names = Rc::new(RefCell::new(names));
let codemap = Rc::new(RefCell::new(CodeMap::new()));
let modules = Rc::new(ModuleRegistry::new(Box::new(BuiltinModuleLoader)));
let io = Rc::new(GlobalIo::default());
let struct_defs = Rc::new(RefCell::new(StructDefMap::new()));
GlobalScope::new(name, names, codemap, modules, io, struct_defs)
}
pub fn new_using(name: Name, scope: &Scope) -> Scope {
Rc::new(GlobalScope::new(
name,
scope.name_store.clone(),
scope.codemap.clone(),
scope.modules.clone(),
scope.io.clone(),
scope.struct_defs.clone()))
}
pub fn clone_scope(&self) -> Scope {
Rc::new(GlobalScope{
name: self.name,
namespace: self.namespace.clone(),
name_store: self.name_store.clone(),
codemap: self.codemap.clone(),
modules: self.modules.clone(),
io: self.io.clone(),
struct_defs: self.struct_defs.clone(),
})
}
pub fn add_constant(&self, name: Name, value: Value) {
self.namespace.borrow_mut().constants.insert(name, value);
}
pub fn add_doc_string(&self, name: Name, doc: String) {
self.namespace.borrow_mut().docs.insert(name, doc);
}
pub fn add_macro(&self, name: Name, lambda: Lambda) {
self.namespace.borrow_mut().macros.insert(name, lambda);
}
pub fn add_name(&self, name: &str) -> Name {
self.name_store.borrow_mut().add(name)
}
pub fn add_imports(&self, imports: ImportSet) {
self.namespace.borrow_mut().add_imports(imports);
}
pub fn add_value(&self, name: Name, value: Value) {
self.namespace.borrow_mut().values.insert(name, value);
}
pub fn add_named_value(&self, name: &str, value: Value) {
let name = self.name_store.borrow_mut().add(name);
self.add_value(name, value);
}
pub fn add_value_with_name<F>(&self, name: &str, f: F)
where F: FnOnce(Name) -> Value {
let name = self.name_store.borrow_mut().add(name);
self.add_value(name, f(name));
}
pub fn borrow_codemap(&self) -> Ref<CodeMap> {
self.codemap.borrow()
}
pub fn borrow_codemap_mut(&self) -> RefMut<CodeMap> {
self.codemap.borrow_mut()
}
pub fn borrow_names(&self) -> Ref<NameStore> {
self.name_store.borrow()
}
pub fn borrow_names_mut(&self) -> RefMut<NameStore> {
self.name_store.borrow_mut()
}
pub fn num_constants(&self) -> usize {
self.namespace.borrow().constants.len()
}
pub fn num_macros(&self) -> usize {
self.namespace.borrow().macros.len()
}
pub fn num_values(&self) -> usize {
self.namespace.borrow().values.len()
}
pub fn codemap(&self) -> &Rc<RefCell<CodeMap>> {
&self.codemap
}
pub fn get_constant(&self, name: Name) -> Option<Value> {
self.namespace.borrow().constants.get(name).cloned()
}
pub fn get_named_constant(&self, name: &str) -> Option<Value> {
let name = self.borrow_names().get_name(name);
name.and_then(|name| self.get_constant(name))
}
pub fn get_struct_def(&self, id: TypeId) -> Option<Rc<StructDef>> {
self.struct_defs.borrow().get(&id).cloned()
}
pub fn register_struct_value<T: StructValue>(&self) {
let name = self.add_name(T::struct_name());
let def = Rc::new(StructDef::new(name,
Box::new(ForeignStructDef::<T>::new(&mut self.name_store.borrow_mut()))));
self.insert_struct_def(TypeId::of::<T>(), def.clone());
self.add_value(name, Value::StructDef(def));
}
fn insert_struct_def(&self, id: TypeId, def: Rc<StructDef>) {
self.struct_defs.borrow_mut().insert(id, def);
}
pub fn io(&self) -> &Rc<GlobalIo> {
&self.io
}
pub fn modules(&self) -> &Rc<ModuleRegistry> {
&self.modules
}
pub fn name(&self) -> Name {
self.name
}
pub fn names(&self) -> &Rc<RefCell<NameStore>> {
&self.name_store
}
pub fn contains_name(&self, name: Name) -> bool {
let ns = self.namespace.borrow();
ns.constants.contains_key(name) ||
ns.macros.contains_key(name) ||
ns.values.contains_key(name)
}
pub fn contains_constant(&self, name: Name) -> bool {
self.namespace.borrow().constants.contains_key(name)
}
pub fn contains_macro(&self, name: Name) -> bool {
self.namespace.borrow().macros.contains_key(name)
}
pub fn contains_value(&self, name: Name) -> bool {
self.namespace.borrow().values.contains_key(name)
}
pub fn get_macro(&self, name: Name) -> Option<Lambda> {
self.namespace.borrow().macros.get(name).cloned()
}
pub fn get_named_macro(&self, name: &str) -> Option<Lambda> {
let name = self.borrow_names().get_name(name);
name.and_then(|name| self.get_macro(name))
}
pub fn get_named_value(&self, name: &str) -> Option<Value> {
let name = self.borrow_names().get_name(name);
name.and_then(|name| self.get_value(name))
}
pub fn get_value(&self, name: Name) -> Option<Value> {
self.namespace.borrow().values.get(name).cloned()
}
pub fn import_all(&self, other: &GlobalScope) -> Vec<Name> {
self.namespace.borrow_mut()
.import_all(&other.namespace.borrow())
}
pub fn import_qualified(&self, other: &GlobalScope) -> Vec<(Name, Name)> {
let mut names = self.name_store.borrow_mut();
let prefix = names.get(other.name).to_owned();
self.namespace.borrow_mut().import_qualified(
&prefix, &mut *names, &other.namespace.borrow())
}
pub fn is_exported(&self, name: Name) -> bool {
self.namespace.borrow().exports.as_ref()
.map_or(false, |e| e.contains(name))
}
pub fn is_imported(&self, name: Name) -> bool {
self.namespace.borrow().is_imported(name)
}
pub fn set_exports(&self, names: NameSetSlice) {
self.namespace.borrow_mut().exports = Some(names);
}
pub fn with_doc<F, R>(&self, name: Name, f: F) -> Option<R>
where F: FnOnce(&str) -> R {
let ns = self.namespace.borrow();
ns.docs.get(name).map(|s| f(s))
}
pub fn with_docs<F, R>(&self, f: F) -> R
where F: FnOnce(&NameMap<String>) -> R {
let ns = self.namespace.borrow();
f(&ns.docs)
}
pub fn with_docs_mut<F, R>(&self, f: F) -> R
where F: FnOnce(&mut NameMap<String>) -> R {
let mut ns = self.namespace.borrow_mut();
f(&mut ns.docs)
}
pub fn with_module_doc<F, R>(&self, f: F) -> Option<R>
where F: FnOnce(&str) -> R {
let ns = self.namespace.borrow();
ns.module_doc.as_ref().map(|d| f(d))
}
pub fn with_module_doc_mut<F, R>(&self, f: F) -> R
where F: FnOnce(&mut Option<String>) -> R {
let mut ns = self.namespace.borrow_mut();
f(&mut ns.module_doc)
}
pub fn with_name<F, R>(&self, name: Name, f: F) -> R
where F: FnOnce(&str) -> R {
let names = self.name_store.borrow();
f(names.get(name))
}
pub fn with_exports<F, R>(&self, f: F) -> Option<R>
where F: FnOnce(&NameSetSlice) -> R {
let ns = self.namespace.borrow();
ns.exports.as_ref().map(f)
}
pub fn with_imports<F, R>(&self, f: F) -> R
where F: FnOnce(&[ImportSet]) -> R {
let ns = self.namespace.borrow();
f(&ns.imports)
}
pub fn with_constants<F, R>(&self, f: F) -> R
where F: FnOnce(&NameMap<Value>) -> R {
let ns = self.namespace.borrow();
f(&ns.constants)
}
pub fn with_macros<F, R>(&self, f: F) -> R
where F: FnOnce(&NameMap<Lambda>) -> R {
let ns = self.namespace.borrow();
f(&ns.macros)
}
pub fn with_values<F, R>(&self, f: F) -> R
where F: FnOnce(&NameMap<Value>) -> R {
let ns = self.namespace.borrow();
f(&ns.values)
}
}
impl Namespace {
fn new() -> Namespace {
Namespace{
constants: NameMap::new(),
macros: NameMap::new(),
values: NameMap::new(),
exports: None,
imports: Vec::new(),
module_doc: None,
docs: NameMap::new(),
}
}
fn add_imports(&mut self, imports: ImportSet) {
self.imports.push(imports);
}
fn import_all(&mut self, other: &Namespace) -> Vec<Name> {
let mut names = Vec::new();
if let Some(ref exports) = other.exports {
for name in exports {
names.push(name);
self.import_doc(name, other);
if let Some(v) = other.constants.get(name).cloned() {
self.constants.insert(name, v);
}
if let Some(v) = other.macros.get(name).cloned() {
self.macros.insert(name, v);
}
if let Some(v) = other.values.get(name).cloned() {
self.values.insert(name, v);
}
}
}
names
}
fn import_qualified(&mut self, prefix: &str,
store: &mut NameStore, other: &Namespace) -> Vec<(Name, Name)> {
let mut names = Vec::new();
if let Some(ref exports) = other.exports {
for src in exports {
let dest_name = format!("{}/{}", prefix, store.get(src));
let dest = store.add(&dest_name);
names.push((src, dest));
self.import_doc_as(src, dest, other);
if let Some(v) = other.constants.get(src).cloned() {
self.constants.insert(dest, v);
}
if let Some(v) = other.macros.get(src).cloned() {
self.macros.insert(dest, v);
}
if let Some(v) = other.values.get(src).cloned() {
self.values.insert(dest, v);
}
}
}
names
}
fn import_doc(&mut self, name: Name, other: &Namespace) {
self.import_doc_as(name, name, other);
}
fn import_doc_as(&mut self, name: Name, dest: Name, other: &Namespace) {
if let Some(doc) = other.docs.get(name) {
self.docs.insert(dest, doc.clone());
}
}
fn is_imported(&self, name: Name) -> bool {
self.imports.iter().any(
|imp| imp.names.iter().any(|&(_, dest)| name == dest))
}
}
pub enum MasterScope {}
impl MasterScope {
pub fn contains(name: Name) -> bool {
is_standard_value(name)
}
pub fn can_define(name: Name) -> bool {
!(is_standard_value(name) || is_system_operator(name))
}
pub fn get(name: Name) -> Option<Value> {
MasterScope::get_function(name)
.or_else(|| MasterScope::get_bool(name).map(Value::Bool))
}
pub fn names() -> MasterNames {
MasterNames::new()
}
pub fn values() -> MasterValues {
MasterValues::new()
}
fn get_bool(name: Name) -> Option<bool> {
use crate::name::standard_names::{TRUE, FALSE};
match name {
TRUE => Some(true),
FALSE => Some(false),
_ => None
}
}
fn get_function(name: Name) -> Option<Value> {
get_system_fn(name).map(|f| Value::Function(Function{
name,
sys_fn: *f,
}))
}
}
pub struct MasterNames {
next: u32,
}
impl MasterNames {
fn new() -> MasterNames {
MasterNames{next: 0}
}
}
impl Iterator for MasterNames {
type Item = Name;
fn next(&mut self) -> Option<Name> {
if self.next >= SYSTEM_OPERATORS_END {
None
} else {
let name = get_standard_name(self.next)
.expect("invalid standard name");
self.next += 1;
Some(name)
}
}
}
impl ExactSizeIterator for MasterNames {
fn len(&self) -> usize {
if self.next >= SYSTEM_OPERATORS_END {
0
} else {
(SYSTEM_OPERATORS_END - self.next) as usize
}
}
}
pub struct MasterValues {
next: u32,
}
impl MasterValues {
fn new() -> MasterValues {
MasterValues{next: 0}
}
}
impl Iterator for MasterValues {
type Item = (Name, Value);
fn next(&mut self) -> Option<(Name, Value)> {
if self.next >= NUM_STANDARD_VALUES {
None
} else {
let name = get_standard_name(self.next)
.expect("invalid standard name");
let v = MasterScope::get(name).expect("missing standard value");
self.next += 1;
Some((name, v))
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let n = self.len();
(n, Some(n))
}
}
impl ExactSizeIterator for MasterValues {
fn len(&self) -> usize {
if self.next >= NUM_STANDARD_VALUES {
0
} else {
(NUM_STANDARD_VALUES - self.next) as usize
}
}
}