Skip to main content

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<Rc<str>>,
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<Rc<str>>) -> 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.as_ref() != "mod" {
118                let (val, pos) = self.symbols.get(sym.as_ref()).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().into());
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).into())),
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        self.push(Rc::new(P(Str(typ_name.into()))), pos)?;
241        Ok(())
242    }
243
244    fn op_deref<O, E>(
245        &mut self,
246        name: Rc<str>,
247        env: &RefCell<Environment<O, E>>,
248        pos: &Position,
249    ) -> Result<(), Error>
250    where
251        O: std::io::Write + Clone,
252        E: std::io::Write + Clone,
253    {
254        let (val, _) = self.get_binding(&name, env, pos)?.clone();
255        self.push(val, pos.clone())
256    }
257
258    fn op_jump(&mut self, jp: i32) -> Result<(), Error> {
259        self.ops.jump(
260            self.ops
261                .ptr
262                .map(|v| (v as i32 + jp) as usize)
263                .unwrap_or(jp as usize),
264        )?;
265        Ok(())
266    }
267
268    fn op_and(&mut self, jp: i32, pos: Position) -> Result<(), Error> {
269        let (cond, cond_pos) = self.pop()?;
270        let cc = cond.clone();
271        if let &P(Bool(cond)) = cond.as_ref() {
272            if !cond {
273                self.push(cc, cond_pos)?;
274                self.op_jump(jp)?;
275            }
276        } else {
277            return Err(Error::new(
278                format!(
279                    "Not a boolean condition {:?} in && expression at {}",
280                    cond, pos
281                )
282                .into(),
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                .into(),
304                cond_pos.clone(),
305            ));
306        }
307        Ok(())
308    }
309
310    fn op_jump_if_true(&mut self, jp: i32) -> Result<(), Error> {
311        let (cond, cond_pos) = self.pop()?;
312        if let &P(Bool(cond)) = cond.as_ref() {
313            if cond {
314                self.op_jump(jp)?;
315            }
316        } else {
317            return Err(Error::new(
318                format!("Expected boolean but got {:?}!", cond).into(),
319                cond_pos.clone(),
320            ));
321        }
322        Ok(())
323    }
324
325    fn op_jump_if_false(&mut self, jp: i32) -> Result<(), Error> {
326        let (cond, pos) = self.pop()?;
327        if let &P(Bool(cond)) = cond.as_ref() {
328            if !cond {
329                self.op_jump(jp)?;
330            }
331        } else {
332            return Err(Error::new(
333                format!("Expected boolean but got {:?}!", cond).into(),
334                pos.clone(),
335            ));
336        }
337        Ok(())
338    }
339
340    fn op_select_jump(&mut self, jp: i32) -> Result<(), Error> {
341        // pop field value off
342        let (field_name, _) = self.pop()?;
343        // pop search value off
344        let (search, srch_pos) = self.pop()?;
345        // compare them.
346        let matched = match (field_name.as_ref(), search.as_ref()) {
347            (&S(ref fname), &P(Str(ref sname))) | (&S(ref fname), &S(ref sname)) => fname == sname,
348            (&S(ref fname), &P(Bool(b))) => {
349                if fname.as_ref() == "true" && b {
350                    true
351                } else if fname.as_ref() == "false" && !b {
352                    true
353                } else {
354                    false
355                }
356            }
357            _ => false,
358        };
359        if !matched {
360            // if they aren't equal then push search value back on and jump
361            self.push(search, srch_pos)?;
362            self.op_jump(jp)?;
363        }
364        Ok(())
365    }
366
367    fn op_module(&mut self, idx: usize, jptr: i32, pos: Position) -> Result<(), Error> {
368        let (mod_val, mod_val_pos) = self.pop()?;
369        let (result_ptr, flds, pos_list) = match mod_val.as_ref() {
370            &C(Tuple(ref flds, ref pos_list)) => (None, flds.clone(), pos_list.clone()),
371            &T(ptr) => {
372                let (tpl_val, tpl_val_pos) = self.pop()?;
373                if let &C(Tuple(ref flds, ref pos_list)) = tpl_val.as_ref() {
374                    (Some(ptr), flds.clone(), pos_list.clone())
375                } else {
376                    return Err(Error::new(
377                        format!("Expected tuple but got {:?}", tpl_val).into(),
378                        tpl_val_pos,
379                    ));
380                }
381            }
382            _ => {
383                return Err(Error::new(
384                    format!("Expected tuple but got {:?}", mod_val).into(),
385                    mod_val_pos,
386                ));
387            }
388        };
389        let mut ops = self.ops.clone();
390        let pkg_pos = self.ops.pos().unwrap().clone();
391        ops.jump(idx)?;
392        let pkg_ptr = if let Some(ref path) = self.ops.path {
393            let pkg_ops = vec![
394                Op::InitList,
395                Op::Func(3),
396                Op::Val(Str(path.to_string_lossy().into())),
397                Op::Runtime(Hook::Import),
398                Op::Return,
399            ];
400            let pos_list = vec![
401                pkg_pos.clone(),
402                pkg_pos.clone(),
403                pkg_pos.clone(),
404                pkg_pos.clone(),
405                pkg_pos,
406            ];
407            Some(OpPointer::new(Rc::new(
408                OpsMap::new().with_ops(pkg_ops, pos_list),
409            )))
410        } else {
411            None
412        };
413        self.push(
414            Rc::new(M(Module {
415                ptr: ops,
416                result_ptr: result_ptr,
417                flds_pos_list: pos_list,
418                flds: flds,
419                pkg_ptr: pkg_ptr,
420            })),
421            pos,
422        )?;
423        self.op_jump(jptr)
424    }
425
426    fn op_func(&mut self, idx: usize, jptr: i32, pos: Position) -> Result<(), Error> {
427        // get arity from stack
428        let scope_snapshot = self.symbols.snapshot();
429        let mut bindings = Vec::new();
430        // get imported symbols from stack
431        let (list_val, args_pos) = self.pop()?;
432        if let &C(List(ref elems, _)) = list_val.as_ref() {
433            for e in elems {
434                if let &S(ref sym) = e.as_ref() {
435                    bindings.push(sym.clone());
436                } else {
437                    return Err(Error::new(
438                        format!("Not an argument name {:?}", e).into(),
439                        args_pos,
440                    ));
441                }
442            }
443        } else {
444            return Err(Error::new("Fault!!! Bad Argument List".into(), args_pos));
445        }
446        let mut ops = self.ops.clone();
447        ops.jump(idx)?;
448        // Our arguments will be pulled off the stack in reverse order;
449        bindings.reverse();
450        self.push(
451            Rc::new(F(Func {
452                ptr: ops, // where the function starts.
453                bindings: bindings,
454                snapshot: scope_snapshot,
455            })),
456            pos,
457        )?;
458        self.op_jump(jptr)
459    }
460
461    pub fn fcall_impl<'a, O, E>(
462        f: &Func,
463        strict: bool,
464        stack: &mut Vec<(Rc<Value>, Position)>,
465        env: &'a RefCell<Environment<O, E>>,
466        import_stack: &Vec<Rc<str>>,
467    ) -> Result<(Rc<Value>, Position), Error>
468    where
469        O: std::io::Write + Clone,
470        E: std::io::Write + Clone,
471    {
472        let Func {
473            ref ptr,
474            ref bindings,
475            ref snapshot,
476        } = f;
477        // use the captured scope snapshot for the function.
478        let mut vm = Self::with_pointer(strict, ptr.clone(), std::env::current_dir()?)
479            .to_scoped(snapshot.clone())
480            .with_import_stack(import_stack.clone());
481        for nm in bindings.iter() {
482            // now put each argument on our scope stack as a binding.
483            // TODO(jwall): This should do a better error if there is
484            // nothing on the stack.
485            let (val, pos) = stack.pop().unwrap();
486            vm.binding_push(nm.clone(), val, false, &pos, &pos)?;
487        }
488        // proceed to the function body
489        vm.run(env)?;
490        return vm.pop();
491    }
492
493    fn op_new_scope<O, E>(
494        &mut self,
495        jp: i32,
496        ptr: OpPointer,
497        env: &RefCell<Environment<O, E>>,
498    ) -> Result<(), Error>
499    where
500        O: std::io::Write + Clone,
501        E: std::io::Write + Clone,
502    {
503        let scope_snapshot = self.symbols.snapshot();
504        let mut vm = self
505            .clean_copy()
506            .to_new_pointer(ptr)
507            .to_scoped(scope_snapshot)
508            .with_import_stack(self.import_stack.clone());
509        vm.run(env)?;
510        let result = vm.pop()?;
511        self.push(result.0, result.1)?;
512        self.op_jump(jp)?;
513        Ok(())
514    }
515
516    fn op_fcall<O, E>(
517        &mut self,
518        pos: Position,
519        env: &RefCell<Environment<O, E>>,
520    ) -> Result<(), Error>
521    where
522        O: std::io::Write + Clone,
523        E: std::io::Write + Clone,
524    {
525        let (f, f_pos) = self.pop()?;
526        let (arg_length, _) = self.pop()?;
527        if let &F(ref f) = f.as_ref() {
528            if let &P(Int(arg_length)) = arg_length.as_ref() {
529                let arity = f.bindings.len() as i64;
530                if arg_length > arity {
531                    return Err(Error::new(
532                        format!(
533                            "Func called with too many args expected {} args but got {}",
534                            arity, arg_length
535                        )
536                        .into(),
537                        pos,
538                    ));
539                }
540                if arg_length < arity {
541                    return Err(Error::new(
542                        format!(
543                            "Func called with too few args expected {} args but got {}",
544                            arity, arg_length
545                        )
546                        .into(),
547                        pos,
548                    ));
549                }
550            }
551            let (val, _) = decorate_call!(f_pos =>
552                Self::fcall_impl(f, self.runtime.strict, &mut self.stack, env, &self.import_stack))?;
553            self.push(val, pos.clone())?;
554        } else {
555            return Err(Error::new(format!("Not a function! {:?}", f,).into(), pos));
556        }
557        Ok(())
558    }
559
560    fn op_thunk(&mut self, idx: usize, jp: i32, pos: Position) -> Result<(), Error> {
561        self.push(Rc::new(T(idx)), pos)?;
562        self.op_jump(jp)
563    }
564
565    fn op_not(&mut self, pos: &Position) -> Result<(), Error> {
566        let (operand, operand_pos) = self.pop()?;
567        if let P(Bool(val)) = operand.as_ref() {
568            self.push(Rc::new(P(Bool(!val))), operand_pos)?;
569            return Ok(());
570        }
571        return Err(Error::new(
572            format!(
573                "Expected Boolean but got {:?} in expression at {}",
574                operand, pos
575            )
576            .into(),
577            operand_pos,
578        ));
579    }
580
581    fn op_equal(&mut self, pos: Position) -> Result<(), Error> {
582        let (left, left_pos) = self.pop()?;
583        let (right, right_pos) = self.pop()?;
584        if left.type_name() != right.type_name()
585            && !(left.type_name() == "NULL" || right.type_name() == "NULL")
586        {
587            return Err(Error::new(
588                format!(
589                    "Expected values of the same type but got {:?} at {} and {:?} at {} for expression",
590                    left, left_pos, right, right_pos,
591                ).into(),
592                pos,
593            ));
594        }
595        self.push(Rc::new(P(Bool(left == right))), pos)?;
596        Ok(())
597    }
598
599    fn op_gt(&mut self, pos: &Position) -> Result<(), Error> {
600        let (left, left_pos) = self.pop()?;
601        let (right, right_pos) = self.pop()?;
602        match (left.as_ref(), right.as_ref()) {
603            (&P(Int(i)), &P(Int(ii))) => {
604                self.push(Rc::new(P(Bool(i > ii))), pos.clone())?;
605            }
606            (&P(Float(f)), &P(Float(ff))) => {
607                self.push(Rc::new(P(Bool(f > ff))), pos.clone())?;
608            }
609            _ => {
610                return Err(Error::new(
611                    format!(
612                        "Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression",
613                        left, left_pos, right, right_pos,
614                    ).into(),
615                    pos.clone(),
616                ));
617            }
618        }
619        Ok(())
620    }
621
622    fn op_lt(&mut self, pos: &Position) -> Result<(), Error> {
623        let (left, left_pos) = self.pop()?;
624        let (right, right_pos) = self.pop()?;
625        match (left.as_ref(), right.as_ref()) {
626            (&P(Int(i)), &P(Int(ii))) => {
627                self.push(Rc::new(P(Bool(i < ii))), pos.clone())?;
628            }
629            (&P(Float(f)), &P(Float(ff))) => {
630                self.push(Rc::new(P(Bool(f < ff))), pos.clone())?;
631            }
632            _ => {
633                return Err(Error::new(
634                    format!(
635                        "Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression",
636                        left, left_pos, right, right_pos,
637                    ).into(),
638                    pos.clone(),
639                ));
640            }
641        }
642        Ok(())
643    }
644
645    fn op_lteq(&mut self, pos: Position) -> Result<(), Error> {
646        let (left, left_pos) = self.pop()?;
647        let (right, right_pos) = self.pop()?;
648        match (left.as_ref(), right.as_ref()) {
649            (&P(Int(i)), &P(Int(ii))) => {
650                self.push(Rc::new(P(Bool(i <= ii))), pos)?;
651            }
652            (&P(Float(f)), &P(Float(ff))) => {
653                self.push(Rc::new(P(Bool(f <= ff))), pos)?;
654            }
655            _ => {
656                return Err(Error::new(
657                    format!(
658                        "Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression",
659                        left, left_pos, right, right_pos,
660                    ).into(),
661                    pos,
662                ));
663            }
664        }
665        Ok(())
666    }
667
668    fn op_gteq(&mut self, pos: Position) -> Result<(), Error> {
669        let (left, left_pos) = self.pop()?;
670        let (right, right_pos) = self.pop()?;
671        match (left.as_ref(), right.as_ref()) {
672            (&P(Int(i)), &P(Int(ii))) => {
673                self.push(Rc::new(P(Bool(i >= ii))), pos)?;
674            }
675            (&P(Float(f)), &P(Float(ff))) => {
676                self.push(Rc::new(P(Bool(f >= ff))), pos)?;
677            }
678            _ => {
679                return Err(Error::new(
680                    format!(
681                        "Expected numeric values of the same type but got {:?} at {} and {:?} at {} for expression",
682                        left, left_pos, right, right_pos,
683                    ).into(),
684                    pos,
685                ));
686            }
687        }
688        Ok(())
689    }
690
691    fn op_mod(&mut self, pos: Position) -> Result<(), Error> {
692        // Adds the previous two items in the stack.
693        let (left, _) = self.pop()?;
694        let (right, right_pos) = self.pop()?;
695        // Then pushes the result onto the stack.
696        self.push(Rc::new(P(self.modulus(&left, &right, &right_pos)?)), pos)?;
697        Ok(())
698    }
699
700    fn op_add(&mut self, pos: Position) -> Result<(), Error> {
701        // Adds the previous two items in the stack.
702        let (left, _) = self.pop()?;
703        let (right, right_pos) = self.pop()?;
704        // Then pushes the result onto the stack.
705        self.push(Rc::new(self.add(&left, &right, &right_pos)?), pos)?;
706        Ok(())
707    }
708
709    fn op_sub(&mut self, pos: Position) -> Result<(), Error> {
710        // Subtracts the previous two items in the stack.
711        let (left, _) = self.pop()?;
712        let (right, right_pos) = self.pop()?;
713        // Then pushes the result onto the stack.
714        self.push(Rc::new(P(self.sub(&left, &right, &right_pos)?)), pos)?;
715        Ok(())
716    }
717
718    fn op_mul(&mut self, pos: Position) -> Result<(), Error> {
719        // Multiplies the previous two items in the stack.
720        let (left, _) = self.pop()?;
721        let (right, right_pos) = self.pop()?;
722        // Then pushes the result onto the stack.
723        self.push(Rc::new(P(self.mul(&left, &right, &right_pos)?)), pos)?;
724        Ok(())
725    }
726
727    fn op_div(&mut self, pos: Position) -> Result<(), Error> {
728        // Divides the previous two items in the stack.
729        let (left, _) = self.pop()?;
730        let (right, right_pos) = self.pop()?;
731        // Then pushes the result onto the stack.
732        self.push(Rc::new(P(self.div(&left, &right, &right_pos)?)), pos)?;
733        Ok(())
734    }
735
736    fn op_push_self(&mut self) -> Result<(), Error> {
737        // We'll need a self stack.
738        let (val, pos) = self.pop()?;
739        self.self_stack.push((val.clone(), pos.clone()));
740        self.push(val.clone(), pos)?;
741        Ok(())
742    }
743
744    fn op_pop_self(&mut self) -> Result<(), Error> {
745        // We'll need a self stack.
746        self.self_stack.pop();
747        Ok(())
748    }
749
750    fn op_bind(&mut self, strict: bool) -> Result<(), Error> {
751        // pop val off stack.
752        let (val, val_pos) = self.pop()?;
753        // pop name off stack.
754        let (name, name_pos) = self.pop()?;
755        // TODO(jwall): We need to restrict against our reserved word list.
756        if let &S(ref name) = name.as_ref() {
757            self.binding_push(name.clone(), val, strict, &val_pos, &name_pos)?;
758        } else {
759            unreachable!();
760        }
761        Ok(())
762    }
763
764    fn op_field(&mut self) -> Result<(), Error> {
765        // Add a Composite field value to a tuple on the stack
766        // get value from stack
767        let (val, val_pos) = self.pop()?;
768        // get name from stack.
769        let (name_val, name_pos) = self.pop()?;
770        let name = if let &S(ref s) | &P(Str(ref s)) = name_val.as_ref() {
771            s
772        } else {
773            unreachable!();
774        };
775        // get composite tuple from stack
776        let (tpl, tpl_pos) = self.pop()?;
777        if let &C(Tuple(ref flds, ref pos_list)) = tpl.as_ref() {
778            // add name and value to tuple
779            let mut flds = flds.clone();
780            let mut pos_list = pos_list.clone();
781            self.merge_field_into_tuple(
782                &mut flds,
783                &mut pos_list,
784                name.clone(),
785                &name_pos,
786                val,
787                &val_pos,
788            )?;
789            // place composite tuple back on stack
790            self.push(Rc::new(C(Tuple(flds, pos_list))), tpl_pos)?;
791        } else {
792            unreachable!();
793        };
794        Ok(())
795    }
796
797    fn op_element(&mut self) -> Result<(), Error> {
798        // get element from stack.
799        let (val, val_pos) = self.pop()?;
800        // get next value. It should be a Composite list.
801        let (list, pos) = self.pop()?;
802        if let &C(List(ref elems, ref pos_list)) = list.as_ref() {
803            // add value to list
804            let mut elems = elems.clone();
805            elems.push(val);
806            let mut pos_list = pos_list.clone();
807            pos_list.push(val_pos);
808            // Add that value to the list and put list back on stack.
809            self.push(Rc::new(C(List(elems, pos_list))), pos)?;
810        } else {
811            unreachable!();
812        };
813        Ok(())
814    }
815
816    fn op_bang(&mut self) -> Result<(), Error> {
817        let (msg_val, err_pos) = self.pop()?;
818        if let &P(Str(ref msg)) = msg_val.as_ref() {
819            return Err(Error::new(msg.clone(), err_pos));
820        } else {
821            unreachable!();
822        }
823    }
824
825    fn op_index(&mut self, safe: bool, pos: Position) -> Result<(), Error> {
826        // left and then right
827        let (right, right_pos) = self.pop()?;
828        let (left, _) = self.pop()?;
829        match right.as_ref() {
830            &P(Int(i)) => {
831                if let &C(List(ref elems, _)) = left.as_ref() {
832                    if i < (elems.len() as i64) && i >= 0 {
833                        self.push(elems[i as usize].clone(), right_pos)?;
834                        return Ok(());
835                    }
836                }
837            }
838            &P(Str(ref s)) => {
839                if let &C(Tuple(ref flds, _)) = left.as_ref() {
840                    for &(ref key, ref val) in flds.iter() {
841                        if key == s {
842                            self.push(val.clone(), right_pos)?;
843                            return Ok(());
844                        }
845                    }
846                }
847            }
848            _ => {
849                // noop
850            }
851        };
852        if safe {
853            self.push(Rc::new(P(Empty)), pos)?;
854            return Ok(());
855        }
856        return Err(Error::new(
857            format!("Invalid selector index: {:?} target: {:?}", right, left).into(),
858            pos,
859        ));
860    }
861
862    fn op_exist(&mut self, pos: Position) -> Result<(), Error> {
863        let (right, right_pos) = self.pop()?;
864        let (left, left_pos) = self.pop()?;
865        match left.as_ref() {
866            &C(Tuple(ref flds, _)) => {
867                if let &P(Str(ref name)) = right.as_ref() {
868                    for (ref nm, _) in flds {
869                        if nm == name {
870                            self.push(Rc::new(P(Bool(true))), pos)?;
871                            return Ok(());
872                        }
873                    }
874                } else {
875                    return Err(Error::new(
876                        format!("Expected String or Symbol got: {}", right.type_name()).into(),
877                        right_pos,
878                    ));
879                }
880            }
881            &C(List(ref elems, _)) => {
882                for e in elems {
883                    if e == &right {
884                        self.push(Rc::new(P(Bool(true))), pos)?;
885                        return Ok(());
886                    }
887                }
888            }
889            &P(Str(ref s)) => {
890                if let &P(Str(ref part)) = right.as_ref() {
891                    self.push(Rc::new(P(Bool(s.contains(part.as_ref())))), pos)?;
892                    return Ok(());
893                }
894            }
895            _ => {
896                return Err(Error::new(
897                    format!("Expected String, Tuple, or List got: {}", left.type_name()).into(),
898                    left_pos,
899                ));
900            }
901        };
902        self.push(Rc::new(P(Bool(false))), pos)?;
903        Ok(())
904    }
905
906    fn op_copy<O, E>(
907        &mut self,
908        pos: Position,
909        env: &RefCell<Environment<O, E>>,
910    ) -> Result<(), Error>
911    where
912        O: std::io::Write + Clone,
913        E: std::io::Write + Clone,
914    {
915        // This value should always be a tuple
916        let (override_val, val_pos) = self.pop()?;
917        // get target value. It should be a Module or Tuple.
918        let (tgt, tgt_pos) = self.pop()?;
919        let (overrides, override_pos_list) =
920            if let &C(Tuple(ref oflds, ref pos_list)) = override_val.as_ref() {
921                (oflds.clone(), pos_list.clone())
922            } else {
923                unreachable!();
924            };
925        match tgt.as_ref() {
926            &C(Tuple(ref flds, ref pos_list)) => {
927                let mut flds = flds.clone();
928                let mut pos_list = pos_list.clone();
929                let mut counter = 0;
930                for (name, val) in overrides {
931                    let name_pos = override_pos_list[counter].0.clone();
932                    let val_pos = override_pos_list[counter].1.clone();
933                    self.merge_field_into_tuple(
934                        &mut flds,
935                        &mut pos_list,
936                        name,
937                        &name_pos,
938                        val,
939                        &val_pos,
940                    )?;
941                    counter += 1;
942                }
943                // Put the copy on the Stack
944                self.push(Rc::new(C(Tuple(flds, pos_list))), tgt_pos.clone())?;
945                self.last = Some((tgt.clone(), tgt_pos));
946            }
947            &M(Module {
948                ref ptr,
949                ref result_ptr,
950                ref flds,
951                ref flds_pos_list,
952                ref pkg_ptr,
953            }) => {
954                let this = M(Module {
955                    ptr: ptr.clone(),
956                    result_ptr: result_ptr.clone(),
957                    flds: flds.clone(),
958                    flds_pos_list: flds_pos_list.clone(),
959                    pkg_ptr: pkg_ptr.clone(),
960                });
961
962                let mut flds = flds.clone();
963                let mut flds_pos_list = flds_pos_list.clone();
964                let mut counter = 0;
965                for (name, val) in overrides {
966                    let name_pos = override_pos_list[counter].0.clone();
967                    let val_pos = override_pos_list[counter].1.clone();
968                    self.merge_field_into_tuple(
969                        &mut flds,
970                        &mut flds_pos_list,
971                        name,
972                        &name_pos,
973                        val,
974                        &val_pos,
975                    )?;
976                    counter += 1;
977                }
978                self.merge_field_into_tuple(
979                    &mut flds,
980                    &mut flds_pos_list,
981                    "this".into(),
982                    &pos,
983                    Rc::new(this),
984                    &val_pos,
985                )?;
986                if let Some(ptr) = pkg_ptr {
987                    let mut pkg_vm = self
988                        .clean_copy()
989                        .to_new_pointer(ptr.clone())
990                        .with_import_stack(self.import_stack.clone());
991                    pkg_vm.run(env)?;
992                    let (pkg_func, val_pos) = pkg_vm.pop()?;
993                    self.merge_field_into_tuple(
994                        &mut flds,
995                        &mut flds_pos_list,
996                        "pkg".into(),
997                        &pos,
998                        pkg_func,
999                        &val_pos,
1000                    )?;
1001                }
1002
1003                let mut vm = self
1004                    .clean_copy()
1005                    .to_new_pointer(ptr.clone())
1006                    .with_import_stack(self.import_stack.clone());
1007                vm.push(Rc::new(S("mod".into())), pos.clone())?;
1008                vm.push(Rc::new(C(Tuple(flds, flds_pos_list))), pos.clone())?;
1009                decorate_call!(pos => vm.run(env))?;
1010                if let Some(ptr) = result_ptr {
1011                    vm.ops.jump(ptr.clone())?;
1012                    vm.run(env)?;
1013                    let (result_val, result_pos) = vm.pop()?;
1014                    self.push(result_val, result_pos)?;
1015                } else {
1016                    self.push(Rc::new(vm.symbols_to_tuple(false)), pos)?;
1017                }
1018            }
1019            _ => {
1020                return Err(Error::new(
1021                    format!("Expected a Tuple or Module but got {:?}", tgt).into(),
1022                    pos,
1023                ));
1024            }
1025        }
1026        Ok(())
1027    }
1028
1029    fn merge_field_into_tuple(
1030        &self,
1031        src_fields: &mut Vec<(Rc<str>, Rc<Value>)>,
1032        pos_fields: &mut Vec<(Position, Position)>,
1033        name: Rc<str>,
1034        name_pos: &Position,
1035        value: Rc<Value>,
1036        val_pos: &Position,
1037    ) -> Result<(), Error> {
1038        let mut counter = 0;
1039        for fld in src_fields.iter_mut() {
1040            if fld.0 == name {
1041                if fld.1.type_name() != value.type_name()
1042                    && !(fld.1.type_name() == "NULL" || value.type_name() == "NULL")
1043                {
1044                    return Err(Error::new(
1045                        format!(
1046                            "Expected type {} for field {} but got ({})",
1047                            fld.1.type_name(),
1048                            name,
1049                            value.type_name(),
1050                        )
1051                        .into(),
1052                        val_pos.clone(),
1053                    ));
1054                }
1055                pos_fields[counter].1 = val_pos.clone();
1056                fld.1 = value;
1057                return Ok(());
1058            }
1059            counter += 1;
1060        }
1061        src_fields.push((name, value));
1062        pos_fields.push((name_pos.clone(), val_pos.clone()));
1063        Ok(())
1064    }
1065
1066    fn push(&mut self, val: Rc<Value>, pos: Position) -> Result<(), Error> {
1067        self.stack.push((val, pos));
1068        Ok(())
1069    }
1070
1071    pub fn binding_push(
1072        &mut self,
1073        name: Rc<str>,
1074        val: Rc<Value>,
1075        strict: bool,
1076        pos: &Position,
1077        name_pos: &Position,
1078    ) -> Result<(), Error> {
1079        if self.reserved_words.contains(name.as_ref()) {
1080            return Err(Error::new(
1081                format!("{} is a reserved word.", name).into(),
1082                name_pos.clone(),
1083            ));
1084        }
1085        if self.symbols.is_bound(&name) && strict {
1086            return Err(Error::new(
1087                format!("Binding {} already exists", name).into(),
1088                pos.clone(),
1089            ));
1090        }
1091        self.symbols.add(name, val, pos.clone());
1092        Ok(())
1093    }
1094
1095    pub fn get_binding<O, E>(
1096        &self,
1097        name: &str,
1098        env: &RefCell<Environment<O, E>>,
1099        pos: &Position,
1100    ) -> Result<(Rc<Value>, Position), Error>
1101    where
1102        O: std::io::Write + Clone,
1103        E: std::io::Write + Clone,
1104    {
1105        // TODO(jwall): Handle environment variables here?
1106        let tpl = if name == "self" {
1107            self.self_stack.last().cloned()
1108        } else if name == "env" {
1109            let candidate = self.symbols.get(name);
1110            if candidate.is_some() {
1111                candidate
1112            } else {
1113                Some((
1114                    Rc::new(env.borrow().get_env_vars_tuple()),
1115                    Position::new(0, 0, 0),
1116                ))
1117            }
1118        } else {
1119            self.symbols.get(name)
1120        };
1121        match tpl {
1122            Some((v, pos)) => Ok((v, pos)),
1123            None => {
1124                return Err(Error::new(
1125                    format!("No such binding {}", name).into(),
1126                    pos.clone(),
1127                ));
1128            }
1129        }
1130    }
1131
1132    pub fn pop(&mut self) -> Result<(Rc<Value>, Position), Error> {
1133        match self.stack.pop() {
1134            Some(v) => {
1135                self.last = Some(v.clone());
1136                Ok(v)
1137            }
1138            None => unreachable!(),
1139        }
1140    }
1141
1142    fn mul(&self, left: &Value, right: &Value, pos: &Position) -> Result<Primitive, Error> {
1143        Ok(match (left, right) {
1144            (P(Int(i)), P(Int(ii))) => Int(i * ii),
1145            (P(Float(f)), P(Float(ff))) => Float(f * ff),
1146            _ => {
1147                return Err(Error::new(
1148                    format!("Expected {} but got {:?}", left.type_name(), right).into(),
1149                    pos.clone(),
1150                ))
1151            }
1152        })
1153    }
1154
1155    fn div(&self, left: &Value, right: &Value, pos: &Position) -> Result<Primitive, Error> {
1156        Ok(match (left, right) {
1157            (P(Int(i)), P(Int(ii))) => Int(i / ii),
1158            (P(Float(f)), P(Float(ff))) => Float(f / ff),
1159            _ => {
1160                return Err(Error::new(
1161                    format!("Expected {} but got {:?}", left.type_name(), right).into(),
1162                    pos.clone(),
1163                ))
1164            }
1165        })
1166    }
1167
1168    fn sub(&self, left: &Value, right: &Value, pos: &Position) -> Result<Primitive, Error> {
1169        Ok(match (left, right) {
1170            (P(Int(i)), Value::P(Int(ii))) => Int(i - ii),
1171            (P(Float(f)), Value::P(Float(ff))) => Float(f - ff),
1172            _ => {
1173                return Err(Error::new(
1174                    format!("Expected {} but got {:?}", left.type_name(), right).into(),
1175                    pos.clone(),
1176                ))
1177            }
1178        })
1179    }
1180
1181    fn modulus(&self, left: &Value, right: &Value, pos: &Position) -> Result<Primitive, Error> {
1182        Ok(match (left, right) {
1183            (P(Int(i)), Value::P(Int(ii))) => Int(i % ii),
1184            (P(Float(f)), Value::P(Float(ff))) => Float(f % ff),
1185            _ => {
1186                return Err(Error::new(
1187                    format!("Expected {} but got {:?}", left.type_name(), right).into(),
1188                    pos.clone(),
1189                ))
1190            }
1191        })
1192    }
1193
1194    fn add(&self, left: &Value, right: &Value, pos: &Position) -> Result<Value, Error> {
1195        Ok(match (left, right) {
1196            (P(Int(i)), Value::P(Int(ii))) => P(Int(i + ii)),
1197            (P(Float(f)), Value::P(Float(ff))) => P(Float(f + ff)),
1198            (P(Str(s)), Value::P(Str(ss))) => {
1199                let mut ns = String::new();
1200                ns.push_str(&s);
1201                ns.push_str(&ss);
1202                P(Str(ns.into()))
1203            }
1204            (
1205                C(List(ref left_list, ref left_pos_list)),
1206                C(List(ref right_list, ref right_pos_list)),
1207            ) => {
1208                let cap = left_list.len() + right_list.len();
1209                let mut new_list = Vec::with_capacity(cap);
1210                let mut new_pos_list = Vec::with_capacity(cap);
1211                let mut counter = 0;
1212                for v in left_list.iter() {
1213                    new_list.push(v.clone());
1214                    new_pos_list.push(left_pos_list[counter].clone());
1215                    counter += 1;
1216                }
1217                counter = 0;
1218                for v in right_list.iter() {
1219                    new_list.push(v.clone());
1220                    new_pos_list.push(right_pos_list[counter].clone());
1221                    counter += 1;
1222                }
1223                C(List(new_list, new_pos_list))
1224            }
1225            _ => {
1226                return Err(Error::new(
1227                    format!("Expected {} but got {:?}", left.type_name(), right).into(),
1228                    pos.clone(),
1229                ))
1230            }
1231        })
1232    }
1233
1234    fn op_runtime<O, E>(
1235        &mut self,
1236        h: Hook,
1237        pos: Position,
1238        env: &RefCell<Environment<O, E>>,
1239    ) -> Result<(), Error>
1240    where
1241        O: std::io::Write + Clone,
1242        E: std::io::Write + Clone,
1243    {
1244        self.runtime.handle(
1245            self.ops.path.as_ref(),
1246            h,
1247            &mut self.stack,
1248            env,
1249            &mut self.import_stack,
1250            pos,
1251        )
1252    }
1253
1254    fn op_render(&mut self) -> Result<(), Error> {
1255        let (val, pos) = self.pop()?;
1256        self.push(Rc::new(P(Str(val.as_ref().into()))), pos)?;
1257        Ok(())
1258    }
1259}