1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230


pub const STACK_SIZE: usize = 4000;
pub const FRAME_STACK_SIZE: usize = 200;

// Assert size of usize is at least 32 bit.

#[path = "system/system.rs"]
mod system;

#[macro_use]
pub mod object;

mod compiler;
mod vm;
mod global;

#[path = "objects/list.rs"]
mod list;

#[path = "objects/map.rs"]
mod map;

#[path = "objects/function.rs"]
mod function;

#[path = "objects/iterable.rs"]
mod iterable;

#[path = "objects/string.rs"]
mod string;

#[path = "objects/range.rs"]
mod range;

#[path = "objects/table.rs"]
mod table;

#[cfg(feature = "long-gmp")]
#[path = "objects/long-gmp.rs"]
mod long;

#[cfg(feature = "long-none")]
#[path = "objects/long-none.rs"]
mod long;

#[path = "objects/tuple.rs"]
mod tuple;

#[path = "objects/class.rs"]
mod class;

#[path = "modules/module.rs"]
pub mod module;

#[path = "modules/complex.rs"]
pub mod complex;

#[path = "modules/math.rs"]
mod math;

#[path = "modules/rand.rs"]
pub mod rand;

#[path = "modules/format.rs"]
mod format;

#[path = "modules/sys.rs"]
mod sys;

#[path = "modules/time.rs"]
mod time;

#[cfg(feature = "la")]
#[path = "modules/la.rs"]
mod la;

#[cfg(feature = "math-la")]
#[path = "modules/math-la.rs"]
mod math_la;

#[cfg(feature = "math-sf")]
#[path = "modules/sf.rs"]
mod sf;

#[path = "modules/regex.rs"]
mod regex;

#[path = "modules/data.rs"]
mod data;

#[path = "modules/fs.rs"]
mod fs;

#[cfg(feature = "graphics")]
#[path = "modules/sdl.rs"]
mod sdl;

#[cfg(feature = "graphics")]
#[path = "modules/graphics.rs"]
mod graphics;

use std::rc::Rc;
use std::cell::RefCell;
// use std::fs::File;
// use std::io::Read;
use object::{Object, List, CharString, TypeName, Downcast};
use vm::{RTE,State,EnvPart,Env};
pub use vm::{get_env};
pub use compiler::{Value, CompilerExtra};
use global::init_rte;

pub struct InterpreterLock<'a> {
    state: std::cell::RefMut<'a,State>
}

impl<'a> InterpreterLock<'a> {
    pub fn env(&mut self) -> Env {
        return get_env(&mut self.state);
    }
}

pub struct Interpreter{
    pub rte: Rc<RTE>,
    pub state: RefCell<State>
}

impl Interpreter{
    pub fn lock(&self) -> InterpreterLock {
        InterpreterLock{state: self.state.borrow_mut()}
    }
    pub fn tie<T>(&self, f: impl FnOnce(&mut Env)->T) -> T {
        f(&mut self.lock().env())
    }
    pub fn eval(&self, s: &str) -> Object {
        self.lock().env().eval(s)
    }
    pub fn eval_cast<T>(&self, s: &str) -> T
    where T: TypeName+Downcast<Output=T>
    {
        self.tie(|env| {
           let y = env.eval(s);
           env.downcast::<T>(&y)
        })
    }

    pub fn new_config(stack_size: usize) -> Self {
        let rte = RTE::new();
        init_rte(&rte);

        let mut stack: Vec<Object> = Vec::with_capacity(stack_size);
        for _ in 0..stack_size {
            stack.push(Object::Null);
        }

        let state = RefCell::new(State{
            stack: stack, sp: 0,
            env: EnvPart::new(FRAME_STACK_SIZE, rte.clone())
        });

        return Self{rte, state};
    }

    pub fn new() -> Rc<Self> {
        Rc::new(Interpreter::new_config(STACK_SIZE))
    }

    pub fn repr(&self, x: &Object) -> String {
        let mut ilock = self.lock();
        let mut env = ilock.env();
        match x.repr(&mut env) {
            Ok(s)=>s,
            Err(e)=>{
                println!("{}",env.exception_to_string(&e));
                "[exception in Interpreter::repr, see stdout]".to_string()
            }
        }
    }

    pub fn string(&self, x: &Object) -> String {
        let mut ilock = self.lock();
        let mut env = ilock.env();
        match x.string(&mut self.lock().env()) {
            Ok(s) => return s,
            Err(e) => {
                println!("{}",env.exception_to_string(&e));
                panic!();
            }
        }
    }

    pub fn set_config(&self, config: CompilerExtra) {
        let mut conf = self.rte.compiler_config.borrow_mut();
        *conf = Some(Box::new(config));
    }
    
    pub fn set_capabilities(&self, root_mode: bool) {
        if root_mode {
            let mut capabilities = self.rte.capabilities.borrow_mut();
            capabilities.write = true;
            capabilities.command = true;
        }
    }
}

pub fn new_list_str(a: &[String]) -> Rc<RefCell<List>> {
    let mut v: Vec<Object> = Vec::with_capacity(a.len());
    for i in 0..a.len() {
        v.push(CharString::new_object_str(&a[i]));
    }
    return Rc::new(RefCell::new(List{v: v, frozen: false}));
}

impl Drop for Interpreter {
    fn drop(&mut self) {
        let v = self.rte.delay.borrow_mut();
        let mut buffer: Vec<Object> = Vec::new();
        for gtab in &v[..] {
            // println!("clear {}",Object::Map(gtab.clone()));
            {
                let m = &mut gtab.borrow_mut().m;
                for (_k,v) in m.drain() {
                    buffer.push(v);
                }
            }
            buffer.clear();
        }
    }
}