little/
interpreter.rs

1//! Template interpreter.
2
3use std::io;
4use std::io::{ Read, Write };
5use std::collections::HashMap;
6use std::borrow::Cow;
7
8use options;
9
10use {
11    Options,
12    Call,
13    Constant,
14    Binding,
15    Instruction,
16    Cond,
17    Mem,
18    Execute,
19    Fingerprint,
20    LittleValue,
21    Template,
22    Build,
23    Function,
24    BuildError,
25    LittleError,
26    LittleResult,
27};
28
29const MAX_VALUES: usize = 500000;
30
31/// Executes template without compilation.
32pub struct Interpreter;
33
34impl Interpreter {
35    pub fn new() -> Interpreter {
36        Interpreter
37    }
38}
39
40impl<'a, V: LittleValue + 'a> Build<'a, V> for Interpreter {
41    type Output = Executable<'a, V>;
42
43    /// Loads the interpreter's executable.
44    ///
45    /// Also maps templates call indices to runtime calls.
46    fn build(
47        &'a mut self,
48        id: &str,
49        template: Template<V>,
50        calls: &'a HashMap<&'a str, &'a (Function<V> + 'a)>
51    ) -> LittleResult<Executable<V>> {
52        Ok(Executable::<V> {
53            id: id.into(),
54            instructions: template.instructions,
55            constants: template.constants,
56            calls: match template.calls_template.build(calls) {
57                Ok(built) => built,
58                Err(options::Error::ParameterMissing(s)) => return Err(BuildError::FunctionNotFound { required: s }.into()),
59            },
60        })
61    }
62
63    /// Loads existing executable by unique fingerprint and env fingerprint.
64    fn load(&'a mut self, id: &str, env: Fingerprint, calls: &'a Vec<&'a (Function<V> + 'a)>)
65        -> LittleResult<Self::Output>
66    {
67        unreachable!("interpreter load is not implemented");
68    }
69}
70
71pub struct Executable<'a, V: 'a> {
72    id: String,
73    instructions: Vec<Instruction>,
74    constants: Options<Constant, V>,
75    calls: Options<Call, &'a Function<V>>,
76}
77
78impl<'a, V: LittleValue + 'a> Execute<'a, V> for Executable<'a, V> {
79    type Stream = InterpreterStream<'a, V>;
80
81    fn execute(&'a self, data: V) -> InterpreterStream<'a, V> {
82        InterpreterStream {
83            pc: 0,
84            buf: Vec::new(),
85            values: Values {
86                stack: Vec::new(),
87                values: Vec::new(),
88                executable: self,
89                parameters: data,
90            }
91        }
92    }
93
94    fn get_id<'r>(&'r self) -> &'r str {
95        &self.id
96    }
97
98    fn identify_env(&self) -> Fingerprint {
99        Fingerprint::empty()
100    }
101}
102
103pub struct InterpreterStream<'a, V: 'a> {
104    pc: usize,
105    buf: Vec<u8>,
106    values: Values<'a, V>,
107}
108
109enum ExecutionResult {
110    Done,
111    Continue,
112    Interupt,
113}
114
115impl<'a, V: LittleValue> InterpreterStream<'a, V> {
116    /// Returns specified number of stack items.
117    ///
118    /// If stack is smaller, returns None.
119    pub fn peek_stack<'r>(&'r self, slice_size: usize) -> Option<&'r [V]> {
120        let stack_len = self.values.stack.len();
121
122        if stack_len < slice_size {
123            return None;
124        }
125
126        Some(&self.values.stack[stack_len - slice_size as usize .. stack_len])
127    }
128
129    fn execute(&mut self) -> Result<ExecutionResult, LittleError>  {
130        match self.values.executable.instructions.get(self.pc) {
131            Some(i) => {
132                match *i {
133                    Instruction::Output { ref location } => {
134                        try!(write!(self.buf, "{}", try!(self.values.get_mem_value(location))))
135                    },
136                    Instruction::Property { mut name } => {
137                        unreachable!("execute Property not implemented")
138                    },
139                    Instruction::Pop { mut times } => while times > 0 {
140                        if let None = self.values.stack.pop() {
141                            return Err(LittleError::StackUnderflow);
142                        }
143                        times -= 1;
144                    },
145                    Instruction::Push { ref location } => {
146                        let value = try!(self.values.get_mem_value(location)).into_owned();
147                        self.values.stack.push(value);
148                    },
149                    Instruction::Load { binding, ref location } => {
150                        let value = try!(self.values.get_mem_value(location)).into_owned();
151                        self.values.set(binding, value);
152                    },
153                    Instruction::Jump { pc } => {
154                        self.pc = pc as usize;
155                        return Ok(ExecutionResult::Continue);
156                    },
157                    Instruction::CondJump { pc, ref location, test } => {
158                        let value = try!(self.values.get_mem_value(location));
159                        let value_ref = value.as_ref();
160                        let stack = match self.values.stack.last() {
161                            Some(value) => value,
162                            None => return Err(LittleError::StackUnderflow),
163                        };
164                        let should_jump = match test {
165                            Cond::Eq => stack == value_ref,
166                            Cond::Gt => stack > value_ref,
167                            Cond::Gte => stack >= value_ref,
168                            Cond::Lt => stack < value_ref,
169                            Cond::Lte => stack <= value_ref,
170                            Cond::Ne => stack != value_ref,
171                        };
172                        if should_jump {
173                            self.pc = pc as usize;
174                            return Ok(ExecutionResult::Continue);
175                        }
176                    },
177                    Instruction::Call { call, argc, push_result_to_stack } => {
178                        let fun = match self.values.executable.calls.get(call) {
179                            Some(f) => f,
180                            None => return Err(LittleError::CallMissing(call)),
181                        };
182
183                        let stack_len = self.values.stack.len();
184                        let result = fun.invoke(&self.values.stack[stack_len - argc as usize .. stack_len]);
185
186                        if push_result_to_stack {
187                            self.values.stack.push(result.unwrap());
188                        }
189                    },
190                    Instruction::Interupt => {
191                        self.pc += 1;
192                        return Ok(ExecutionResult::Interupt);
193                    }
194                };
195                self.pc += 1;
196                Ok(ExecutionResult::Continue)
197            },
198            None => Ok(ExecutionResult::Done),
199        }
200    }
201
202    #[cfg(feature="nightly")]
203    fn consume_buf(&mut self, buf: &mut [u8]) -> io::Result<usize> {
204        let self_buf_len = self.buf.len();
205        if self_buf_len >= buf.len() {
206            for (i, o) in self.buf.drain(..buf.len()).zip(buf.iter_mut()) {
207                *o = i
208            }
209            Ok(buf.len())
210        } else {
211            for (i, o) in self.buf.drain(..).zip(&mut buf[..self_buf_len]) {
212                *o = i
213            }
214            Ok(self_buf_len)
215        }
216    }
217
218    #[cfg(not(feature="nightly"))]
219    fn consume_buf(&mut self, buf: &mut [u8]) -> io::Result<usize> {
220        let self_buf_len = self.buf.len();
221        if self_buf_len >= buf.len() {
222            for (_, o) in (0..buf.len()).zip(buf.iter_mut()) {
223                *o = self.buf.remove(0);
224            }
225            Ok(buf.len())
226        } else {
227            for (_, o) in (0..self_buf_len).zip(&mut buf[..self_buf_len]) {
228                *o = self.buf.remove(0)
229            }
230            Ok(self_buf_len)
231        }
232    }
233}
234
235impl<'a, V: LittleValue> io::Read for InterpreterStream<'a, V> {
236    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
237        loop {
238            if self.buf.len() >= buf.len() {
239                break;
240            }
241
242            match self.execute() {
243                Ok(res) => match res {
244                    ExecutionResult::Done => return self.consume_buf(buf),
245                    ExecutionResult::Continue => (),
246                    ExecutionResult::Interupt => return Err(io::Error::new(io::ErrorKind::Other, LittleError::Interupt)),
247                },
248                Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidInput, e)),
249            }
250        }
251
252        self.consume_buf(buf)
253    }
254}
255
256struct Values<'a, V: 'a> {
257    stack: Vec<V>,
258    values: Vec<V>,
259    parameters: V,
260    executable: &'a Executable<'a, V>,
261}
262
263impl<'a, V: LittleValue> Values<'a, V> {
264    fn get_mem_value(&self, mem: &Mem) -> Result<Cow<V>, LittleError> {
265        Ok(match *mem {
266            Mem::Binding(i) => self.get(i),
267            Mem::Parameter { name } => {
268                unreachable!("get_mem_value Parameter not implemented")
269                // let name = match self.parameters.get(name) {
270                //     Some(value) => Cow::Borrowed(value),
271                //     None => return Err(LittleError::ParameterMissing(i)),
272                // };
273                // match self.parameters.get(i) {
274                //     Some(value) => Cow::Borrowed(value),
275                //     None => return Err(LittleError::ParameterMissing(i)),
276                // }
277            },
278            Mem::Parameters => { Cow::Borrowed(&self.parameters) },
279            Mem::Const(i) => match self.executable.constants.get(i) {
280                Some(value) => Cow::Borrowed(value),
281                None => return Err(LittleError::ConstantMissing(i)),
282            },
283            Mem::StackTop1 => match self.stack.last() {
284                Some(value) => Cow::Borrowed(value),
285                None => return Err(LittleError::StackUnderflow),
286            },
287            Mem::StackTop2 => match self.stack.get(self.stack.len() - 2) {
288                Some(value) => Cow::Borrowed(value),
289                None => return Err(LittleError::StackUnderflow),
290            },
291        })
292    }
293
294    fn set(&mut self, Binding(index): Binding, value: V) {
295        let i = index as usize;
296        self.ensure_capacity_for_index(i);
297        * unsafe { self.values.get_unchecked_mut(i) } = value;
298    }
299
300    fn get<'r>(&'r self, Binding(index): Binding) -> Cow<'r, V> {
301        let i = index as usize;
302        if i >= self.values.len() {
303            Cow::Owned(V::default())
304        } else {
305            Cow::Borrowed(self.values.get(i).unwrap())
306        }
307    }
308
309    #[cfg(feature="nightly")]
310    fn ensure_capacity_for_index(&mut self, index: usize) {
311        let required_len = index + 1;
312        if required_len > MAX_VALUES {
313            panic!("maximum number of values {} reached!", MAX_VALUES);
314        }
315        if required_len > self.values.len() {
316            self.values.resize(required_len, V::default());
317        }
318    }
319
320    #[cfg(not(feature="nightly"))]
321    fn ensure_capacity_for_index(&mut self, index: usize) {
322        use std::iter;
323
324        let required_len = index + 1;
325        if required_len > MAX_VALUES {
326            panic!("maximum number of values {} reached!", MAX_VALUES);
327        }
328        if required_len > self.values.len() {
329            let missing_len = required_len - self.values.len();
330            self.values.reserve(missing_len);
331            self.values.extend(iter::repeat(V::default()).take(missing_len));
332        }
333    }
334}