ucglib/build/opcode/
vm.rs

1// Copyright 2019 Jeremy Wall
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14use std::cell::RefCell;
15use std::collections::BTreeSet;
16use std::convert::TryInto;
17use std::path::PathBuf;
18use std::rc::Rc;
19
20use crate::ast::{CastType, Position};
21
22use super::environment::Environment;
23use super::pointer::OpPointer;
24use super::runtime;
25use super::scope::Stack;
26use super::translate::OpsMap;
27use super::Composite::{List, Tuple};
28use super::Hook;
29use super::Primitive::{Bool, Empty, Float, Int, Str};
30use super::Value::{C, F, M, P, S, T};
31use super::{Error, Op, Primitive, Value};
32use super::{Func, Module};
33
34fn construct_reserved_word_set() -> BTreeSet<&'static str> {
35    let mut words = BTreeSet::new();
36    for word in vec![
37        "let", "module", "func", "out", "assert", "self", "import", "include", "as", "map",
38        "filter", "convert", "fail", "NULL", "in", "is", "TRACE",
39    ] {
40        words.insert(word);
41    }
42    words
43}
44
45pub struct VM {
46    working_dir: PathBuf,
47    stack: Vec<(Rc<Value>, Position)>,
48    symbols: Stack,
49    import_stack: Vec<String>,
50    runtime: runtime::Builtins,
51    ops: OpPointer,
52    pub last: Option<(Rc<Value>, Position)>,
53    self_stack: Vec<(Rc<Value>, Position)>,
54    reserved_words: BTreeSet<&'static str>,
55}
56
57impl VM {
58    pub fn new<P: Into<PathBuf>>(strict: bool, ops: Rc<OpsMap>, working_dir: P) -> Self {
59        Self::with_pointer(strict, OpPointer::new(ops), working_dir)
60    }
61
62    pub fn with_pointer<P: Into<PathBuf>>(strict: bool, ops: OpPointer, working_dir: P) -> Self {
63        Self {
64            working_dir: working_dir.into(),
65            stack: Vec::new(),
66            symbols: Stack::new(),
67            import_stack: Vec::new(),
68            runtime: runtime::Builtins::new(strict),
69            ops: ops,
70            last: None,
71            self_stack: Vec::new(),
72            reserved_words: construct_reserved_word_set(),
73        }
74    }
75
76    pub fn set_path(&mut self, path: PathBuf) {
77        self.ops.set_path(path);
78    }
79
80    pub fn to_new_pointer(mut self, ops: OpPointer) -> Self {
81        self.ops = ops;
82        self
83    }
84
85    pub fn with_import_stack(mut self, imports: Vec<String>) -> Self {
86        self.import_stack = imports;
87        self
88    }
89
90    pub fn enable_validate_mode(&mut self) {
91        self.runtime.enable_validate_mode();
92    }
93
94    pub fn clean_copy(&self) -> Self {
95        Self {
96            working_dir: self.working_dir.clone(),
97            stack: Vec::new(),
98            symbols: Stack::new(),
99            import_stack: Vec::new(),
100            runtime: self.runtime.clone(),
101            ops: self.ops.clone(),
102            last: None,
103            self_stack: self.self_stack.clone(),
104            reserved_words: self.reserved_words.clone(),
105        }
106    }
107
108    pub fn to_scoped(mut self, symbols: Stack) -> Self {
109        self.symbols = symbols;
110        self
111    }
112
113    pub fn symbols_to_tuple(&self, include_mod: bool) -> Value {
114        let mut flds = Vec::new();
115        let mut pos_list = Vec::new();
116        for sym in self.symbols.symbol_list() {
117            if include_mod || sym != "mod" {
118                let (val, pos) = self.symbols.get(sym).unwrap().clone();
119                pos_list.push((pos.clone(), pos.clone()));
120                flds.push((sym.clone(), val));
121            }
122        }
123        return C(Tuple(flds, pos_list));
124    }
125
126    pub fn remove_symbol(&mut self, sym: &str) -> Option<(Rc<Value>, Position)> {
127        self.symbols.remove_symbol(sym)
128    }
129
130    pub fn run<'a, O, E>(&mut self, env: &'a RefCell<Environment<O, E>>) -> Result<(), Error>
131    where
132        O: std::io::Write + Clone,
133        E: std::io::Write + Clone,
134    {
135        loop {
136            let op = if let Some(op) = self.ops.next() {
137                op.clone()
138            } else {
139                break;
140            };
141            let pos = self.ops.pos().unwrap().clone();
142            let idx = self.ops.idx()?;
143            match op {
144                Op::Val(p) => self.push(Rc::new(P(p.clone())), pos)?,
145                Op::Cast(t) => self.op_cast(t)?,
146                Op::Sym(s) => self.push(Rc::new(S(s.clone())), pos)?,
147                Op::DeRef(s) => self.op_deref(s.clone(), env, &pos)?,
148                Op::Add => self.op_add(pos)?,
149                Op::Mod => self.op_mod(pos)?,
150                Op::Sub => self.op_sub(pos)?,
151                Op::Mul => self.op_mul(pos)?,
152                Op::Div => self.op_div(pos)?,
153                Op::Bind => self.op_bind(true)?,
154                Op::BindOver => self.op_bind(false)?,
155                Op::Equal => self.op_equal(pos)?,
156                Op::Not => self.op_not(&pos)?,
157                Op::Gt => self.op_gt(&pos)?,
158                Op::Lt => self.op_lt(&pos)?,
159                Op::GtEq => self.op_gteq(pos)?,
160                Op::LtEq => self.op_lteq(pos)?,
161                // Add a Composite list value to the stack
162                Op::InitList => self.push(Rc::new(C(List(Vec::new(), Vec::new()))), pos)?,
163                // Add a composite tuple value to the stack
164                Op::InitTuple => self.push(Rc::new(C(Tuple(Vec::new(), Vec::new()))), pos)?,
165                Op::Field => self.op_field()?,
166                Op::Element => self.op_element()?,
167                Op::Index => self.op_index(!self.runtime.strict, pos)?,
168                Op::SafeIndex => self.op_index(true, pos)?,
169                Op::Exist => self.op_exist(pos)?,
170                Op::Cp => self.op_copy(pos, env)?,
171                //FIXME(jwall): Should this take a user provided message?
172                Op::Bang => self.op_bang()?,
173                Op::InitThunk(jp) => self.op_thunk(idx, jp, pos)?,
174                Op::Noop => {
175                    // Do nothing
176                }
177                Op::Jump(jp) => self.op_jump(jp)?,
178                Op::JumpIfTrue(jp) => self.op_jump_if_true(jp)?,
179                Op::JumpIfFalse(jp) => self.op_jump_if_false(jp)?,
180                Op::SelectJump(jp) => self.op_select_jump(jp)?,
181                Op::And(jp) => self.op_and(jp, pos)?,
182                Op::Or(jp) => self.op_or(jp, pos)?,
183                Op::Module(mptr) => self.op_module(idx, mptr, pos)?,
184                Op::Func(jptr) => self.op_func(idx, jptr, pos)?,
185                Op::FCall => self.op_fcall(pos, env)?,
186                Op::NewScope(jp) => self.op_new_scope(jp, self.ops.clone(), env)?,
187                Op::Return => {
188                    return Ok(());
189                }
190                Op::Pop => {
191                    self.pop()?;
192                }
193                Op::Typ => self.op_typ()?,
194                Op::Runtime(h) => self.op_runtime(h, pos, env)?,
195                Op::Render => self.op_render()?,
196                Op::PushSelf => self.op_push_self()?,
197                Op::PopSelf => self.op_pop_self()?,
198            };
199        }
200        if let Some(p) = self.ops.path.as_ref() {
201            self.import_stack.push(p.to_string_lossy().to_string());
202        }
203        Ok(())
204    }
205
206    fn do_cast(&mut self, t: CastType, val: &Value, pos: Position) -> Result<(), Error> {
207        if let Value::P(ref p) = val {
208            self.push(
209                Rc::new(match t {
210                    CastType::Str => Value::P(Primitive::Str(format!("{}", p))),
211                    CastType::Int => Value::P(Primitive::Int(p.try_into()?)),
212                    CastType::Float => Value::P(Primitive::Float(p.try_into()?)),
213                    CastType::Bool => Value::P(Primitive::Bool(p.try_into()?)),
214                }),
215                pos,
216            )?;
217        }
218        Ok(())
219    }
220    fn op_cast(&mut self, t: CastType) -> Result<(), Error> {
221        let (val, pos) = self.pop()?;
222        decorate_error!(pos => self.do_cast(t, &val, pos.clone()))
223    }
224
225    fn op_typ(&mut self) -> Result<(), Error> {
226        let (val, pos) = self.pop()?;
227        let typ_name = match val.as_ref() {
228            P(Int(_)) => "int",
229            P(Float(_)) => "float",
230            P(Bool(_)) => "bool",
231            P(Str(_)) => "str",
232            P(Empty) => "null",
233            C(Tuple(_, _)) => "tuple",
234            C(List(_, _)) => "list",
235            F(_) => "func",
236            M(_) => "module",
237            S(_) => "sym",
238            T(_) => "thunk",
239        }
240        .to_owned();
241        self.push(Rc::new(P(Str(typ_name))), pos)?;
242        Ok(())
243    }
244
245    fn op_deref<O, E>(
246        &mut self,
247        name: String,
248        env: &RefCell<Environment<O, E>>,
249        pos: &Position,
250    ) -> Result<(), Error>
251    where
252        O: std::io::Write + Clone,
253        E: std::io::Write + Clone,
254    {
255        let (val, _) = self.get_binding(&name, env, pos)?.clone();
256        self.push(val, pos.clone())
257    }
258
259    fn op_jump(&mut self, jp: i32) -> Result<(), Error> {
260        self.ops.jump(
261            self.ops
262                .ptr
263                .map(|v| (v as i32 + jp) as usize)
264                .unwrap_or(jp as usize),
265        )?;
266        Ok(())
267    }
268
269    fn op_and(&mut self, jp: i32, pos: Position) -> Result<(), Error> {
270        let (cond, cond_pos) = self.pop()?;
271        let cc = cond.clone();
272        if let &P(Bool(cond)) = cond.as_ref() {
273            if !cond {
274                self.push(cc, cond_pos)?;
275                self.op_jump(jp)?;
276            }
277        } else {
278            return Err(Error::new(
279                format!(
280                    "Not a boolean condition {:?} in && expression at {}",
281                    cond, pos
282                ),
283                cond_pos.clone(),
284            ));
285        }
286        Ok(())
287    }
288
289    fn op_or(&mut self, jp: i32, pos: Position) -> Result<(), Error> {
290        let (cond, cond_pos) = self.pop()?;
291        let cc = cond.clone();
292        if let &P(Bool(cond)) = cond.as_ref() {
293            if cond {
294                self.push(cc, cond_pos)?;
295                self.op_jump(jp)?;
296            }
297        } else {
298            return Err(Error::new(
299                format!(
300                    "Not a boolean condition {:?} in || expression at {}!",
301                    cond, pos
302                ),
303                cond_pos.clone(),
304            ));
305        }
306        Ok(())
307    }
308
309    fn op_jump_if_true(&mut self, jp: i32) -> Result<(), Error> {
310        let (cond, cond_pos) = self.pop()?;
311        if let &P(Bool(cond)) = cond.as_ref() {
312            if cond {
313                self.op_jump(jp)?;
314            }
315        } else {
316            return Err(Error::new(
317                format!("Expected boolean but got {:?}!", cond),
318                cond_pos.clone(),
319            ));
320        }
321        Ok(())
322    }
323
324    fn op_jump_if_false(&mut self, jp: i32) -> Result<(), Error> {
325        let (cond, pos) = self.pop()?;
326        if let &P(Bool(cond)) = cond.as_ref() {
327            if !cond {
328                self.op_jump(jp)?;
329            }
330        } else {
331            return Err(Error::new(
332                format!("Expected boolean but got {:?}!", cond),
333                pos.clone(),
334            ));
335        }
336        Ok(())
337    }
338
339    fn op_select_jump(&mut self, jp: i32) -> Result<(), Error> {
340        // pop field value off
341        let (field_name, _) = self.pop()?;
342        // pop search value off
343        let (search, srch_pos) = self.pop()?;
344        // compare them.
345        let matched = match (field_name.as_ref(), search.as_ref()) {
346            (&S(ref fname), &P(Str(ref sname))) | (&S(ref fname), &S(ref sname)) => fname == sname,
347            (&S(ref fname), &P(Bool(b))) => {
348                if fname == "true" && b {
349                    true
350                } else if fname == "false" && !b {
351                    true
352                } else {
353                    false
354                }
355            }
356            _ => false,
357        };
358        if !matched {
359            // if they aren't equal then push search value back on and jump
360            self.push(search, srch_pos)?;
361            self.op_jump(jp)?;
362        }
363        Ok(())
364    }
365
366    fn op_module(&mut self, idx: usize, jptr: i32, pos: Position) -> Result<(), Error> {
367        let (mod_val, mod_val_pos) = self.pop()?;
368        let (result_ptr, flds, pos_list) = match mod_val.as_ref() {
369            &C(Tuple(ref flds, ref pos_list)) => (None, flds.clone(), pos_list.clone()),
370            &T(ptr) => {
371                let (tpl_val, tpl_val_pos) = self.pop()?;
372                if let &C(Tuple(ref flds, ref pos_list)) = tpl_val.as_ref() {
373                    (Some(ptr), flds.clone(), pos_list.clone())
374                } else {
375                    return Err(Error::new(
376                        format!("Expected tuple but got {:?}", tpl_val),
377                        tpl_val_pos,
378                    ));
379                }
380            }
381            _ => {
382                return Err(Error::new(
383                    format!("Expected tuple but got {:?}", mod_val),
384                    mod_val_pos,
385                ));
386            }
387        };
388        let mut ops = self.ops.clone();
389        let pkg_pos = self.ops.pos().unwrap().clone();
390        ops.jump(idx)?;
391        let pkg_ptr = if let Some(ref path) = self.ops.path {
392            let pkg_ops = vec![
393                Op::InitList,
394                Op::Func(3),
395                Op::Val(Str(path.to_string_lossy().to_string())),
396                Op::Runtime(Hook::Import),
397                Op::Return,
398            ];
399            let pos_list = vec![
400                pkg_pos.clone(),
401                pkg_pos.clone(),
402                pkg_pos.clone(),
403                pkg_pos.clone(),
404                pkg_pos,
405            ];
406            Some(OpPointer::new(Rc::new(
407                OpsMap::new().with_ops(pkg_ops, pos_list),
408            )))
409        } else {
410            None
411        };
412        self.push(
413            Rc::new(M(Module {
414                ptr: ops,
415                result_ptr: result_ptr,
416                flds_pos_list: pos_list,
417                flds: flds,
418                pkg_ptr: pkg_ptr,
419            })),
420            pos,
421        )?;
422        self.op_jump(jptr)
423    }
424
425    fn op_func(&mut self, idx: usize, jptr: i32, pos: Position) -> Result<(), Error> {
426        // get arity from stack
427        let scope_snapshot = self.symbols.snapshot();
428        let mut bindings = Vec::new();
429        // get imported symbols from stack
430        let (list_val, args_pos) = self.pop()?;
431        if let &C(List(ref elems, _)) = list_val.as_ref() {
432            for e in elems {
433                if let &S(ref sym) = e.as_ref() {
434                    bindings.push(sym.clone());
435                } else {
436                    return Err(Error::new(
437                        format!("Not an argument name {:?}", e),
438                        args_pos,
439                    ));
440                }
441            }
442        } else {
443            return Err(Error::new(format!("Fault!!! Bad Argument List"), args_pos));
444        }
445        let mut ops = self.ops.clone();
446        ops.jump(idx)?;
447        // Our arguments will be pulled off the stack in reverse order;
448        bindings.reverse();
449        self.push(
450            Rc::new(F(Func {
451                ptr: ops, // where the function starts.
452                bindings: bindings,
453                snapshot: scope_snapshot,
454            })),
455            pos,
456        )?;
457        self.op_jump(jptr)
458    }
459
460    pub fn fcall_impl<'a, O, E>(
461        f: &Func,
462        strict: bool,
463        stack: &mut Vec<(Rc<Value>, Position)>,
464        env: &'a RefCell<Environment<O, E>>,
465        import_stack: &Vec<String>,
466    ) -> Result<(Rc<Value>, Position), Error>
467    where
468        O: std::io::Write + Clone,
469        E: std::io::Write + Clone,
470    {
471        let Func {
472            ref ptr,
473            ref bindings,
474            ref snapshot,
475        } = f;
476        // use the captured scope snapshot for the function.
477        let mut vm = Self::with_pointer(strict, ptr.clone(), std::env::current_dir()?)
478            .to_scoped(snapshot.clone())
479            .with_import_stack(import_stack.clone());
480        for nm in bindings.iter() {
481            // now put each argument on our scope stack as a binding.
482            // TODO(jwall): This should do a better error if there is
483            // nothing on the stack.
484            let (val, pos) = stack.pop().unwrap();
485            vm.binding_push(nm.clone(), val, false, &pos, &pos)?;
486        }
487        // proceed to the function body
488        vm.run(env)?;
489        return vm.pop();
490    }
491
492    fn op_new_scope<O, E>(
493        &mut self,
494        jp: i32,
495        ptr: OpPointer,
496        env: &RefCell<Environment<O, E>>,
497    ) -> Result<(), Error>
498    where
499        O: std::io::Write + Clone,
500        E: std::io::Write + Clone,
501    {
502        let scope_snapshot = self.symbols.snapshot();
503        let mut vm = self
504            .clean_copy()
505            .to_new_pointer(ptr)
506            .to_scoped(scope_snapshot)
507            .with_import_stack(self.import_stack.clone());
508        vm.run(env)?;
509        let result = vm.pop()?;
510        self.push(result.0, result.1)?;
511        self.op_jump(jp)?;
512        Ok(())
513    }
514
515    fn op_fcall<O, E>(
516        &mut self,
517        pos: Position,
518        env: &RefCell<Environment<O, E>>,
519    ) -> Result<(), Error>
520    where
521        O: std::io::Write + Clone,
522        E: std::io::Write + Clone,
523    {
524        let (f, f_pos) = self.pop()?;
525        let (arg_length, _) = self.pop()?;
526        if let &F(ref f) = f.as_ref() {
527            if let &P(Int(arg_length)) = arg_length.as_ref() {
528                let arity = f.bindings.len() as i64;
529                if arg_length > arity {
530                    return Err(Error::new(
531                        format!(
532                            "Func called with too many args expected {} args but got {}",
533                            arity, arg_length
534                        ),
535                        pos,
536                    ));
537                }
538                if arg_length < arity {
539                    return Err(Error::new(
540                        format!(
541                            "Func called with too few args expected {} args but got {}",
542                            arity, arg_length
543                        ),
544                        pos,
545                    ));
546                }
547            }
548            let (val, _) = decorate_call!(f_pos =>
549                Self::fcall_impl(f, self.runtime.strict, &mut self.stack, env.clone(), &self.import_stack))?;
550            self.push(val, pos.clone())?;
551        } else {
552            return Err(Error::new(format!("Not a function! {:?}", f,), pos));
553        }
554        Ok(())
555    }
556
557    fn op_thunk(&mut self, idx: usize, jp: i32, pos: Position) -> Result<(), Error> {
558        self.push(Rc::new(T(idx)), pos)?;
559        self.op_jump(jp)
560    }
561
562    fn op_not(&mut self, pos: &Position) -> Result<(), Error> {
563        let (operand, operand_pos) = self.pop()?;
564        if let P(Bool(val)) = operand.as_ref() {
565            self.push(Rc::new(P(Bool(!val))), operand_pos)?;
566            return Ok(());
567        }
568        return Err(Error::new(
569            format!(
570                "Expected Boolean but got {:?} in expression at {}",
571                operand, pos
572            ),
573            operand_pos,
574        ));
575    }
576
577    fn op_equal(&mut self, pos: Position) -> Result<(), Error> {
578        let (left, left_pos) = self.pop()?;
579        let (right, right_pos) = self.pop()?;
580        if left.type_name() != right.type_name()
581            && !(left.type_name() == "NULL" || right.type_name() == "NULL")
582        {
583            return Err(Error::new(
584                format!(
585                    "Expected values of the same type but got {:?} at {} and {:?} at {} for expression",
586                    left, left_pos, right, right_pos,
587                ),
588                pos,
589            ));
590        }
591        self.push(Rc::new(P(Bool(left == right))), pos)?;
592        Ok(())
593    }
594
595    fn op_gt(&mut self, pos: &Position) -> Result<(), Error> {
596        let (left, left_pos) = self.pop()?;
597        let (right, right_pos) = self.pop()?;
598        match (left.as_ref(), right.as_ref()) {
599            (&P(Int(i)), &P(Int(ii))) => {
600                self.push(Rc::new(P(Bool(i > ii))), pos.clone())?;
601            }
602            (&P(Float(f)), &P(Float(ff))) => {
603                self.push(Rc::new(P(Bool(f > ff))), pos.clone())?;
604            }
605            _ => {
606                return Err(Error::new(
607                    format!(
608                        "Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression",
609                        left, left_pos, right, right_pos,
610                    ),
611                    pos.clone(),
612                ));
613            }
614        }
615        Ok(())
616    }
617
618    fn op_lt(&mut self, pos: &Position) -> Result<(), Error> {
619        let (left, left_pos) = self.pop()?;
620        let (right, right_pos) = self.pop()?;
621        match (left.as_ref(), right.as_ref()) {
622            (&P(Int(i)), &P(Int(ii))) => {
623                self.push(Rc::new(P(Bool(i < ii))), pos.clone())?;
624            }
625            (&P(Float(f)), &P(Float(ff))) => {
626                self.push(Rc::new(P(Bool(f < ff))), pos.clone())?;
627            }
628            _ => {
629                return Err(Error::new(
630                    format!(
631                        "Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression",
632                        left, left_pos, right, right_pos,
633                    ),
634                    pos.clone(),
635                ));
636            }
637        }
638        Ok(())
639    }
640
641    fn op_lteq(&mut self, pos: Position) -> Result<(), Error> {
642        let (left, left_pos) = self.pop()?;
643        let (right, right_pos) = self.pop()?;
644        match (left.as_ref(), right.as_ref()) {
645            (&P(Int(i)), &P(Int(ii))) => {
646                self.push(Rc::new(P(Bool(i <= ii))), pos)?;
647            }
648            (&P(Float(f)), &P(Float(ff))) => {
649                self.push(Rc::new(P(Bool(f <= ff))), pos)?;
650            }
651            _ => {
652                return Err(Error::new(
653                    format!(
654                        "Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression",
655                        left, left_pos, right, right_pos,
656                    ),
657                    pos,
658                ));
659            }
660        }
661        Ok(())
662    }
663
664    fn op_gteq(&mut self, pos: Position) -> Result<(), Error> {
665        let (left, left_pos) = self.pop()?;
666        let (right, right_pos) = self.pop()?;
667        match (left.as_ref(), right.as_ref()) {
668            (&P(Int(i)), &P(Int(ii))) => {
669                self.push(Rc::new(P(Bool(i >= ii))), pos)?;
670            }
671            (&P(Float(f)), &P(Float(ff))) => {
672                self.push(Rc::new(P(Bool(f >= ff))), pos)?;
673            }
674            _ => {
675                return Err(Error::new(
676                    format!(
677                        "Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression",
678                        left, left_pos, right, right_pos,
679                    ),
680                    pos,
681                ));
682            }
683        }
684        Ok(())
685    }
686
687    fn op_mod(&mut self, pos: Position) -> Result<(), Error> {
688        // Adds the previous two items in the stack.
689        let (left, _) = self.pop()?;
690        let (right, right_pos) = self.pop()?;
691        // Then pushes the result onto the stack.
692        self.push(Rc::new(P(self.modulus(&left, &right, &right_pos)?)), pos)?;
693        Ok(())
694    }
695
696    fn op_add(&mut self, pos: Position) -> Result<(), Error> {
697        // Adds the previous two items in the stack.
698        let (left, _) = self.pop()?;
699        let (right, right_pos) = self.pop()?;
700        // Then pushes the result onto the stack.
701        self.push(Rc::new(self.add(&left, &right, &right_pos)?), pos)?;
702        Ok(())
703    }
704
705    fn op_sub(&mut self, pos: Position) -> Result<(), Error> {
706        // Subtracts the previous two items in the stack.
707        let (left, _) = self.pop()?;
708        let (right, right_pos) = self.pop()?;
709        // Then pushes the result onto the stack.
710        self.push(Rc::new(P(self.sub(&left, &right, &right_pos)?)), pos)?;
711        Ok(())
712    }
713
714    fn op_mul(&mut self, pos: Position) -> Result<(), Error> {
715        // Multiplies the previous two items in the stack.
716        let (left, _) = self.pop()?;
717        let (right, right_pos) = self.pop()?;
718        // Then pushes the result onto the stack.
719        self.push(Rc::new(P(self.mul(&left, &right, &right_pos)?)), pos)?;
720        Ok(())
721    }
722
723    fn op_div(&mut self, pos: Position) -> Result<(), Error> {
724        // Divides the previous two items in the stack.
725        let (left, _) = self.pop()?;
726        let (right, right_pos) = self.pop()?;
727        // Then pushes the result onto the stack.
728        self.push(Rc::new(P(self.div(&left, &right, &right_pos)?)), pos)?;
729        Ok(())
730    }
731
732    fn op_push_self(&mut self) -> Result<(), Error> {
733        // We'll need a self stack.
734        let (val, pos) = self.pop()?;
735        self.self_stack.push((val.clone(), pos.clone()));
736        self.push(val.clone(), pos)?;
737        Ok(())
738    }
739
740    fn op_pop_self(&mut self) -> Result<(), Error> {
741        // We'll need a self stack.
742        self.self_stack.pop();
743        Ok(())
744    }
745
746    fn op_bind(&mut self, strict: bool) -> Result<(), Error> {
747        // pop val off stack.
748        let (val, val_pos) = self.pop()?;
749        // pop name off stack.
750        let (name, name_pos) = self.pop()?;
751        // TODO(jwall): We need to restrict against our reserved word list.
752        if let &S(ref name) = name.as_ref() {
753            self.binding_push(name.clone(), val, strict, &val_pos, &name_pos)?;
754        } else {
755            unreachable!();
756        }
757        Ok(())
758    }
759
760    fn op_field(&mut self) -> Result<(), Error> {
761        // Add a Composite field value to a tuple on the stack
762        // get value from stack
763        let (val, val_pos) = self.pop()?;
764        // get name from stack.
765        let (name_val, name_pos) = self.pop()?;
766        let name = if let &S(ref s) | &P(Str(ref s)) = name_val.as_ref() {
767            s
768        } else {
769            unreachable!();
770        };
771        // get composite tuple from stack
772        let (tpl, tpl_pos) = self.pop()?;
773        if let &C(Tuple(ref flds, ref pos_list)) = tpl.as_ref() {
774            // add name and value to tuple
775            let mut flds = flds.clone();
776            let mut pos_list = pos_list.clone();
777            self.merge_field_into_tuple(
778                &mut flds,
779                &mut pos_list,
780                name.clone(),
781                &name_pos,
782                val,
783                &val_pos,
784            )?;
785            // place composite tuple back on stack
786            self.push(Rc::new(C(Tuple(flds, pos_list))), tpl_pos)?;
787        } else {
788            unreachable!();
789        };
790        Ok(())
791    }
792
793    fn op_element(&mut self) -> Result<(), Error> {
794        // get element from stack.
795        let (val, val_pos) = self.pop()?;
796        // get next value. It should be a Composite list.
797        let (list, pos) = self.pop()?;
798        if let &C(List(ref elems, ref pos_list)) = list.as_ref() {
799            // add value to list
800            let mut elems = elems.clone();
801            elems.push(val);
802            let mut pos_list = pos_list.clone();
803            pos_list.push(val_pos);
804            // Add that value to the list and put list back on stack.
805            self.push(Rc::new(C(List(elems, pos_list))), pos)?;
806        } else {
807            unreachable!();
808        };
809        Ok(())
810    }
811
812    fn op_bang(&mut self) -> Result<(), Error> {
813        let (msg_val, err_pos) = self.pop()?;
814        if let &P(Str(ref msg)) = msg_val.as_ref() {
815            return Err(Error::new(msg.clone(), err_pos));
816        } else {
817            unreachable!();
818        }
819    }
820
821    fn op_index(&mut self, safe: bool, pos: Position) -> Result<(), Error> {
822        // left and then right
823        let (right, right_pos) = self.pop()?;
824        let (left, _) = self.pop()?;
825        match right.as_ref() {
826            &P(Int(i)) => {
827                if let &C(List(ref elems, _)) = left.as_ref() {
828                    if i < (elems.len() as i64) && i >= 0 {
829                        self.push(elems[i as usize].clone(), right_pos)?;
830                        return Ok(());
831                    }
832                }
833            }
834            &P(Str(ref s)) => {
835                if let &C(Tuple(ref flds, _)) = left.as_ref() {
836                    for &(ref key, ref val) in flds.iter() {
837                        if key == s {
838                            self.push(val.clone(), right_pos)?;
839                            return Ok(());
840                        }
841                    }
842                }
843            }
844            _ => {
845                // noop
846            }
847        };
848        if safe {
849            self.push(Rc::new(P(Empty)), pos)?;
850            return Ok(());
851        }
852        return Err(Error::new(
853            format!("Invalid selector index: {:?} target: {:?}", right, left),
854            pos,
855        ));
856    }
857
858    fn op_exist(&mut self, pos: Position) -> Result<(), Error> {
859        let (right, right_pos) = self.pop()?;
860        let (left, left_pos) = self.pop()?;
861        match left.as_ref() {
862            &C(Tuple(ref flds, _)) => {
863                if let &P(Str(ref name)) = right.as_ref() {
864                    for (ref nm, _) in flds {
865                        if nm == name {
866                            self.push(Rc::new(P(Bool(true))), pos)?;
867                            return Ok(());
868                        }
869                    }
870                } else {
871                    return Err(Error::new(
872                        format!("Expected String or Symbol got: {}", right.type_name()),
873                        right_pos,
874                    ));
875                }
876            }
877            &C(List(ref elems, _)) => {
878                for e in elems {
879                    if e == &right {
880                        self.push(Rc::new(P(Bool(true))), pos)?;
881                        return Ok(());
882                    }
883                }
884            }
885            &P(Str(ref s)) => {
886                if let &P(Str(ref part)) = right.as_ref() {
887                    self.push(Rc::new(P(Bool(s.contains(part)))), pos)?;
888                    return Ok(());
889                }
890            }
891            _ => {
892                return Err(Error::new(
893                    format!("Expected String, Tuple, or List got: {}", left.type_name()),
894                    left_pos,
895                ));
896            }
897        };
898        self.push(Rc::new(P(Bool(false))), pos)?;
899        Ok(())
900    }
901
902    fn op_copy<O, E>(
903        &mut self,
904        pos: Position,
905        env: &RefCell<Environment<O, E>>,
906    ) -> Result<(), Error>
907    where
908        O: std::io::Write + Clone,
909        E: std::io::Write + Clone,
910    {
911        // This value should always be a tuple
912        let (override_val, val_pos) = self.pop()?;
913        // get target value. It should be a Module or Tuple.
914        let (tgt, tgt_pos) = self.pop()?;
915        let (overrides, override_pos_list) =
916            if let &C(Tuple(ref oflds, ref pos_list)) = override_val.as_ref() {
917                (oflds.clone(), pos_list.clone())
918            } else {
919                unreachable!();
920            };
921        match tgt.as_ref() {
922            &C(Tuple(ref flds, ref pos_list)) => {
923                let mut flds = flds.clone();
924                let mut pos_list = pos_list.clone();
925                let mut counter = 0;
926                for (name, val) in overrides {
927                    let name_pos = override_pos_list[counter].0.clone();
928                    let val_pos = override_pos_list[counter].1.clone();
929                    self.merge_field_into_tuple(
930                        &mut flds,
931                        &mut pos_list,
932                        name,
933                        &name_pos,
934                        val,
935                        &val_pos,
936                    )?;
937                    counter += 1;
938                }
939                // Put the copy on the Stack
940                self.push(Rc::new(C(Tuple(flds, pos_list))), tgt_pos.clone())?;
941                self.last = Some((tgt.clone(), tgt_pos));
942            }
943            &M(Module {
944                ref ptr,
945                ref result_ptr,
946                ref flds,
947                ref flds_pos_list,
948                ref pkg_ptr,
949            }) => {
950                let this = M(Module {
951                    ptr: ptr.clone(),
952                    result_ptr: result_ptr.clone(),
953                    flds: flds.clone(),
954                    flds_pos_list: flds_pos_list.clone(),
955                    pkg_ptr: pkg_ptr.clone(),
956                });
957
958                let mut flds = flds.clone();
959                let mut flds_pos_list = flds_pos_list.clone();
960                let mut counter = 0;
961                for (name, val) in overrides {
962                    let name_pos = override_pos_list[counter].0.clone();
963                    let val_pos = override_pos_list[counter].1.clone();
964                    self.merge_field_into_tuple(
965                        &mut flds,
966                        &mut flds_pos_list,
967                        name,
968                        &name_pos,
969                        val,
970                        &val_pos,
971                    )?;
972                    counter += 1;
973                }
974                self.merge_field_into_tuple(
975                    &mut flds,
976                    &mut flds_pos_list,
977                    "this".to_owned(),
978                    &pos,
979                    Rc::new(this),
980                    &val_pos,
981                )?;
982                if let Some(ptr) = pkg_ptr {
983                    let mut pkg_vm = self
984                        .clean_copy()
985                        .to_new_pointer(ptr.clone())
986                        .with_import_stack(self.import_stack.clone());
987                    pkg_vm.run(env)?;
988                    let (pkg_func, val_pos) = pkg_vm.pop()?;
989                    self.merge_field_into_tuple(
990                        &mut flds,
991                        &mut flds_pos_list,
992                        "pkg".to_owned(),
993                        &pos,
994                        pkg_func,
995                        &val_pos,
996                    )?;
997                }
998
999                let mut vm = self
1000                    .clean_copy()
1001                    .to_new_pointer(ptr.clone())
1002                    .with_import_stack(self.import_stack.clone());
1003                vm.push(Rc::new(S("mod".to_owned())), pos.clone())?;
1004                vm.push(Rc::new(C(Tuple(flds, flds_pos_list))), pos.clone())?;
1005                decorate_call!(pos => vm.run(env))?;
1006                if let Some(ptr) = result_ptr {
1007                    vm.ops.jump(ptr.clone())?;
1008                    vm.run(env)?;
1009                    let (result_val, result_pos) = vm.pop()?;
1010                    self.push(result_val, result_pos)?;
1011                } else {
1012                    self.push(Rc::new(vm.symbols_to_tuple(false)), pos)?;
1013                }
1014            }
1015            _ => {
1016                return Err(Error::new(
1017                    format!("Expected a Tuple or Module but got {:?}", tgt),
1018                    pos,
1019                ));
1020            }
1021        }
1022        Ok(())
1023    }
1024
1025    fn merge_field_into_tuple(
1026        &self,
1027        src_fields: &mut Vec<(String, Rc<Value>)>,
1028        pos_fields: &mut Vec<(Position, Position)>,
1029        name: String,
1030        name_pos: &Position,
1031        value: Rc<Value>,
1032        val_pos: &Position,
1033    ) -> Result<(), Error> {
1034        let mut counter = 0;
1035        for fld in src_fields.iter_mut() {
1036            if fld.0 == name {
1037                if fld.1.type_name() != value.type_name()
1038                    && !(fld.1.type_name() == "NULL" || value.type_name() == "NULL")
1039                {
1040                    return Err(Error::new(
1041                        format!(
1042                            "Expected type {} for field {} but got ({})",
1043                            fld.1.type_name(),
1044                            name,
1045                            value.type_name(),
1046                        ),
1047                        val_pos.clone(),
1048                    ));
1049                }
1050                pos_fields[counter].1 = val_pos.clone();
1051                fld.1 = value;
1052                return Ok(());
1053            }
1054            counter += 1;
1055        }
1056        src_fields.push((name, value));
1057        pos_fields.push((name_pos.clone(), val_pos.clone()));
1058        Ok(())
1059    }
1060
1061    fn push(&mut self, val: Rc<Value>, pos: Position) -> Result<(), Error> {
1062        self.stack.push((val, pos));
1063        Ok(())
1064    }
1065
1066    pub fn binding_push(
1067        &mut self,
1068        name: String,
1069        val: Rc<Value>,
1070        strict: bool,
1071        pos: &Position,
1072        name_pos: &Position,
1073    ) -> Result<(), Error> {
1074        if self.reserved_words.contains(name.as_str()) {
1075            return Err(Error::new(
1076                format!("{} is a reserved word.", name),
1077                name_pos.clone(),
1078            ));
1079        }
1080        if self.symbols.is_bound(&name) && strict {
1081            return Err(Error::new(
1082                format!("Binding {} already exists", name),
1083                pos.clone(),
1084            ));
1085        }
1086        self.symbols.add(name, val, pos.clone());
1087        Ok(())
1088    }
1089
1090    pub fn get_binding<O, E>(
1091        &self,
1092        name: &str,
1093        env: &RefCell<Environment<O, E>>,
1094        pos: &Position,
1095    ) -> Result<(Rc<Value>, Position), Error>
1096    where
1097        O: std::io::Write + Clone,
1098        E: std::io::Write + Clone,
1099    {
1100        // TODO(jwall): Handle environment variables here?
1101        let tpl = if name == "self" {
1102            self.self_stack.last().cloned()
1103        } else if name == "env" {
1104            let candidate = self.symbols.get(name);
1105            if candidate.is_some() {
1106                candidate
1107            } else {
1108                Some((
1109                    Rc::new(env.borrow().get_env_vars_tuple()),
1110                    Position::new(0, 0, 0),
1111                ))
1112            }
1113        } else {
1114            self.symbols.get(name)
1115        };
1116        match tpl {
1117            Some((v, pos)) => Ok((v, pos)),
1118            None => {
1119                return Err(Error::new(format!("No such binding {}", name), pos.clone()));
1120            }
1121        }
1122    }
1123
1124    pub fn pop(&mut self) -> Result<(Rc<Value>, Position), Error> {
1125        match self.stack.pop() {
1126            Some(v) => {
1127                self.last = Some(v.clone());
1128                Ok(v)
1129            }
1130            None => unreachable!(),
1131        }
1132    }
1133
1134    fn mul(&self, left: &Value, right: &Value, pos: &Position) -> Result<Primitive, Error> {
1135        Ok(match (left, right) {
1136            (P(Int(i)), P(Int(ii))) => Int(i * ii),
1137            (P(Float(f)), P(Float(ff))) => Float(f * ff),
1138            _ => {
1139                return Err(Error::new(
1140                    format!("Expected {} but got {:?}", left.type_name(), right),
1141                    pos.clone(),
1142                ))
1143            }
1144        })
1145    }
1146
1147    fn div(&self, left: &Value, right: &Value, pos: &Position) -> Result<Primitive, Error> {
1148        Ok(match (left, right) {
1149            (P(Int(i)), P(Int(ii))) => Int(i / ii),
1150            (P(Float(f)), P(Float(ff))) => Float(f / ff),
1151            _ => {
1152                return Err(Error::new(
1153                    format!("Expected {} but got {:?}", left.type_name(), right),
1154                    pos.clone(),
1155                ))
1156            }
1157        })
1158    }
1159
1160    fn sub(&self, left: &Value, right: &Value, pos: &Position) -> Result<Primitive, Error> {
1161        Ok(match (left, right) {
1162            (P(Int(i)), Value::P(Int(ii))) => Int(i - ii),
1163            (P(Float(f)), Value::P(Float(ff))) => Float(f - ff),
1164            _ => {
1165                return Err(Error::new(
1166                    format!("Expected {} but got {:?}", left.type_name(), right),
1167                    pos.clone(),
1168                ))
1169            }
1170        })
1171    }
1172
1173    fn modulus(&self, left: &Value, right: &Value, pos: &Position) -> Result<Primitive, Error> {
1174        Ok(match (left, right) {
1175            (P(Int(i)), Value::P(Int(ii))) => Int(i % ii),
1176            (P(Float(f)), Value::P(Float(ff))) => Float(f % ff),
1177            _ => {
1178                return Err(Error::new(
1179                    format!("Expected {} but got {:?}", left.type_name(), right),
1180                    pos.clone(),
1181                ))
1182            }
1183        })
1184    }
1185
1186    fn add(&self, left: &Value, right: &Value, pos: &Position) -> Result<Value, Error> {
1187        Ok(match (left, right) {
1188            (P(Int(i)), Value::P(Int(ii))) => P(Int(i + ii)),
1189            (P(Float(f)), Value::P(Float(ff))) => P(Float(f + ff)),
1190            (P(Str(s)), Value::P(Str(ss))) => {
1191                let mut ns = String::new();
1192                ns.push_str(&s);
1193                ns.push_str(&ss);
1194                P(Str(ns))
1195            }
1196            (
1197                C(List(ref left_list, ref left_pos_list)),
1198                C(List(ref right_list, ref right_pos_list)),
1199            ) => {
1200                let cap = left_list.len() + right_list.len();
1201                let mut new_list = Vec::with_capacity(cap);
1202                let mut new_pos_list = Vec::with_capacity(cap);
1203                let mut counter = 0;
1204                for v in left_list.iter() {
1205                    new_list.push(v.clone());
1206                    new_pos_list.push(left_pos_list[counter].clone());
1207                    counter += 1;
1208                }
1209                counter = 0;
1210                for v in right_list.iter() {
1211                    new_list.push(v.clone());
1212                    new_pos_list.push(right_pos_list[counter].clone());
1213                    counter += 1;
1214                }
1215                C(List(new_list, new_pos_list))
1216            }
1217            _ => {
1218                return Err(Error::new(
1219                    format!("Expected {} but got {:?}", left.type_name(), right),
1220                    pos.clone(),
1221                ))
1222            }
1223        })
1224    }
1225
1226    fn op_runtime<O, E>(
1227        &mut self,
1228        h: Hook,
1229        pos: Position,
1230        env: &RefCell<Environment<O, E>>,
1231    ) -> Result<(), Error>
1232    where
1233        O: std::io::Write + Clone,
1234        E: std::io::Write + Clone,
1235    {
1236        self.runtime.handle(
1237            self.ops.path.as_ref(),
1238            h,
1239            &mut self.stack,
1240            env,
1241            &mut self.import_stack,
1242            pos,
1243        )
1244    }
1245
1246    fn op_render(&mut self) -> Result<(), Error> {
1247        let (val, pos) = self.pop()?;
1248        self.push(Rc::new(P(Str(val.as_ref().into()))), pos)?;
1249        Ok(())
1250    }
1251}