mtots_core/base/gl/
mod.rs

1use crate::annotate;
2use crate::compile;
3use crate::ArgSpec;
4use crate::Behavior;
5use crate::Class;
6use crate::ConstVal;
7use crate::DocStr;
8use crate::Error;
9use crate::Handle;
10use crate::HandleBehaviorBuilder;
11use crate::Key;
12use crate::LexErrorKind;
13use crate::Lexer;
14use crate::List;
15use crate::Map;
16use crate::Mark;
17use crate::Module;
18use crate::ModuleDisplay;
19use crate::NativeFunction;
20use crate::NativeGenerator;
21use crate::Parser;
22use crate::RcStr;
23use crate::Result;
24use crate::ResumeResult;
25use crate::Set;
26use crate::Source;
27use crate::Value;
28use std::any::Any;
29use std::any::TypeId;
30use std::cell::Ref;
31use std::cell::RefCell;
32use std::cell::RefMut;
33use std::cmp;
34use std::collections::hash_map::Entry;
35use std::collections::HashMap;
36use std::collections::HashSet;
37use std::convert::TryFrom;
38use std::path::PathBuf;
39use std::rc::Rc;
40mod bltn;
41mod clss;
42mod ge;
43mod hist;
44mod hnd;
45mod load;
46mod nm;
47mod parse;
48mod stash;
49mod trampoline;
50pub use clss::*;
51pub use ge::*;
52pub use nm::*;
53pub use stash::*;
54
55/// The global state for mtots
56pub struct Globals {
57    // debug info (stack trace)
58    trace: Vec<Mark>,
59
60    // frontend stuff
61    lexer: Lexer,
62    parser: Parser,
63
64    // module management
65    module_map: HashMap<RcStr, Rc<Module>>,
66    native_modules: HashMap<RcStr, NativeModule>,
67    source_roots: Vec<RcStr>,
68    main_module: Option<RcStr>,
69
70    // builtins
71    class_manager: ClassManager,
72    builtins: HashMap<RcStr, Value>,
73    repl_scope: Option<HashMap<RcStr, Rc<RefCell<Value>>>>,
74
75    // interfacing with native types (i.e. Handles)
76    handle_class_map: HashMap<TypeId, Rc<Class>>,
77
78    // For storing arbitrary global data for various applications
79    // You can use an application local type to store application
80    // local information
81    stash: Stash,
82
83    // For application that needs to hijack the main thread (e.g. GUIs),
84    // the Globals object might need to be moved.
85    // The trampoline allows an application to request this from its host
86    // environment.
87    trampoline: Option<Box<dyn FnOnce(Globals)>>,
88
89    // command line arguments; need to be explicitly set to be nonempty
90    argv: Option<Vec<RcStr>>,
91
92    // Just a best effort support and line editing experience with
93    // rustyline.
94    #[cfg(feature = "line")]
95    line: rustyline::Editor<()>,
96}
97
98impl Globals {
99    pub fn new() -> Self {
100        let class_manager = ClassManager::new();
101        let builtins = Self::bootstrap_new_builtins(&class_manager);
102        #[cfg(feature = "line")]
103        let line = Self::new_line_editor();
104        let mut globals = Self {
105            trace: vec![],
106            lexer: Lexer::new(),
107            parser: Parser::new(),
108            module_map: HashMap::new(),
109            native_modules: HashMap::new(),
110            source_roots: vec![],
111            main_module: None,
112            class_manager,
113            builtins,
114            repl_scope: None,
115            handle_class_map: HashMap::new(),
116            stash: Default::default(),
117            trampoline: None,
118            argv: None,
119            #[cfg(feature = "line")]
120            line,
121        };
122        globals.add_builtin_native_libraries();
123        globals
124    }
125    pub fn trace(&self) -> &Vec<Mark> {
126        &self.trace
127    }
128    pub fn trace_unwind(&mut self, len: usize) {
129        self.trace.truncate(len);
130    }
131    pub(crate) fn trace_push(&mut self, mark: Mark) {
132        self.trace.push(mark);
133    }
134    pub(crate) fn trace_pop(&mut self) {
135        self.trace.pop().unwrap();
136    }
137    pub fn register_module(&mut self, module: Rc<Module>) -> Result<()> {
138        let name = module.name().clone();
139        if self.module_map.contains_key(&name) {
140            return Err(rterr!("Module {:?} registered twice", name));
141        }
142        self.module_map.insert(name, module);
143        Ok(())
144    }
145    pub fn class_manager(&self) -> &ClassManager {
146        &self.class_manager
147    }
148    pub fn get_main(&self) -> &Option<RcStr> {
149        &self.main_module
150    }
151    pub fn set_main(&mut self, main_module_name: RcStr) {
152        self.main_module = Some(main_module_name);
153    }
154    pub fn exec(&mut self, source: Rc<Source>) -> Result<Rc<Module>> {
155        let name = source.name().clone();
156        let path = source.path().clone();
157        let mut display = self.parse(source)?;
158        annotate(&mut display)?;
159        let code = compile(&display)?;
160        let mut map = self.builtins.clone();
161        map.insert("__name".into(), name.into());
162        if let Some(path) = path {
163            if let Some(pathstr) = path.to_str() {
164                map.insert("__file".into(), pathstr.into());
165            }
166        }
167        code.apply_for_module(self, &map)
168    }
169    pub fn exec_str(&mut self, name: &str, path: Option<&str>, data: &str) -> Result<Rc<Module>> {
170        self.exec(
171            Source::new(
172                name.into(),
173                path.map(PathBuf::from).map(Rc::from),
174                data.into(),
175            )
176            .into(),
177        )
178    }
179    pub fn exec_repl(&mut self, data: &str) -> Result<Value> {
180        let mut display = self.parse(Rc::new(Source::new("[repl]".into(), None, data.into())))?;
181        annotate(&mut display)?;
182        let code = compile(&display)?;
183        code.apply_for_repl(self)
184    }
185    pub(super) fn repl_scope_mut(&mut self) -> &mut HashMap<RcStr, Rc<RefCell<Value>>> {
186        if self.repl_scope.is_none() {
187            let mut scope = HashMap::new();
188            for (key, val) in &self.builtins {
189                scope.insert(key.clone(), Rc::new(RefCell::new(val.clone())));
190            }
191            self.repl_scope = Some(scope);
192        }
193        self.repl_scope.as_mut().unwrap()
194    }
195    pub fn argv(&self) -> &Option<Vec<RcStr>> {
196        &self.argv
197    }
198    pub fn set_argv(&mut self, argv: Vec<RcStr>) {
199        self.argv = Some(argv);
200    }
201}