pub fn eval(&mut self, stack: &mut Stack) -> VMResult {
        let (global, local) = stack.frames()?;
        let local = local.unwrap_or(global);

        let mut increment = true;

        let ins = &self.code[self.counter];
        println!("{:?}", ins);

        // TODO: return VMError instead of panicking on out-of-bounds?
        match ins {
            PushConst(idx) => {
                local.push(self.consts[*idx].clone());
            }
            Pop => {
                local.pop()?;
            }
            Load(idx) => {
                local.push(local.get(&self.locals[*idx])?);
            }
            LoadGlobal(s) => global.eval.push(global.get(s)?),
            Store(idx) => {
                let o = local.pop()?;
                local.set(self.locals[*idx].to_owned(), o);
            }
            StoreGlobal(s) => {
                let o = global.pop()?;
                global.set(s.to_owned(), o);
            }
            Delete(idx) => {
                local.delete(&self.locals[*idx])?;
            }
            DeleteGlobal(s) => {
                global.delete(s)?;
            }
            Add => type_binop!(local, add),
            Sub => type_binop!(local, sub),
            Mul => type_binop!(local, mul),
            Div => type_binop!(local, div),
            Pow => type_binop!(local, pow),
            Cmp(op) => {
                let rhs = local.pop()?;
                let lhs = local.pop()?;

                let cmp_fn = type_fn!(cmp(lhs, rhs))?;
                local.push(cmp_fn(lhs, rhs, *op)?);
            }
            And => type_binop!(local, and),
            Or => type_binop!(local, or),
            Not => type_unop!(local, not),
            Nop => {}
            Jump(delta) => {
                increment = false;

                self.counter = *delta;
            }
            JumpIf(delta) => {
                increment = false;

                let v = local.pop()?;
                let b = Boolean::try_from(&*v.borrow())?;

                if b {
                    self.counter = *delta;
                }
            }
            JumpIfNot(delta) => {
                increment = false;

                let v = local.pop()?;
                let b = Boolean::try_from(&*v.borrow())?;

                if !b {
                    self.counter = *delta;
                }
            }
            _ => return Err(VMError::Unimplemented),
        };

        if increment {
            self.counter += 1;
        }

        Ok(())
    }
/// Evaluate the instruction indexed by counter.
Evaluate the instruction indexed by counter.
Evaluate the instruction indexed by counter .
pub fn eval(&mut self, stack: &mut Stack) -> VMResult {
        let (global, local) = stack.frames()?;
        let local = local.unwrap_or(global);
        let mut increment = true;
        let ins = &self.code[self.counter];
        println!("{:?}", ins);
        // TODO: return VMError instead of panicking on out-of-bounds?
        match ins {
            PushConst(idx) => {
                local.push(self.consts[*idx].clone());
            }
            Pop => {
                local.pop()?;
            }
            Load(idx) => {
                local.push(local.get(&self.locals[*idx])?);
            }
            LoadGlobal(s) => global.eval.push(global.get(s)?),
            Store(idx) => {
                let o = local.pop()?;
                local.set(self.locals[*idx].to_owned(), o);
            }
            StoreGlobal(s) => {
                let o = global.pop()?;
                global.set(s.to_owned(), o);
            }
            Delete(idx) => {
                local.delete(&self.locals[*idx])?;
            }
            DeleteGlobal(s) => {
                global.delete(s)?;
            }
            Add => type_binop!(local, add),
            Sub => type_binop!(local, sub),
            Mul => type_binop!(local, mul),
            Div => type_binop!(local, div),
            Pow => type_binop!(local, pow),
            Cmp(op) => {
                let rhs = local.pop()?;
                let lhs = local.pop()?;
                let cmp_fn = type_fn!(cmp(lhs, rhs))?;
                local.push(cmp_fn(lhs, rhs, *op)?);
            }
            And => type_binop!(local, and),
            Or => type_binop!(local, or),
            Not => type_unop!(local, not),
            Nop => {}
            Jump(delta) => {
                increment = false;
                self.counter = *delta;
            }
            JumpIf(delta) => {
                increment = false;
                let v = local.pop()?;
                let b = Boolean::try_from(&*v.borrow())?;
                if b {
                    self.counter = *delta;
                }
            }
            JumpIfNot(delta) => {
                increment = false;
                let v = local.pop()?;
                let b = Boolean::try_from(&*v.borrow())?;
                if !b {
                    self.counter = *delta;
                }
            }
            _ => return Err(VMError::Unimplemented),
        };
        if increment {
            self.counter += 1;
        }
        Ok(())
    }
pub fn eval ( & mut self , stack : & mut Stack ) -> VMResult { let ( global , local ) = stack . frames ( ) ? ; let local = local . unwrap_or ( global ) ; let mut increment = true ; let ins = & self . code [ self . counter ] ; println ! ( " " ins ) ; // TODO: return VMError instead of panicking on out-of-bounds? match ins { PushConst ( idx ) => { local . push ( self . consts [ * idx ] . clone ( ) ) ; } Pop => { local . pop ( ) ? ; } Load ( idx ) => { local . push ( local . get ( & self . locals [ * idx ] ) ? ) ; } LoadGlobal ( s ) => global . eval . push ( global . get ( s ) ? ) , Store ( idx ) => { let o = local . pop ( ) ? ; local . set ( self . locals [ * idx ] . to_owned ( ) , o ) ; } StoreGlobal ( s ) => { let o = global . pop ( ) ? ; global . set ( s . to_owned ( ) , o ) ; } Delete ( idx ) => { local . delete ( & self . locals [ * idx ] ) ? ; } DeleteGlobal ( s ) => { global . delete ( s ) ? ; } Add => type_binop ! ( local add ) , Sub => type_binop ! ( local sub ) , Mul => type_binop ! ( local mul ) , Div => type_binop ! ( local div ) , Pow => type_binop ! ( local pow ) , Cmp ( op ) => { let rhs = local . pop ( ) ? ; let lhs = local . pop ( ) ? ; let cmp_fn = type_fn ! ( cmp ( lhs rhs ) ) ? ; local . push ( cmp_fn ( lhs , rhs , * op ) ? ) ; } And => type_binop ! ( local and ) , Or => type_binop ! ( local or ) , Not => type_unop ! ( local not ) , Nop => { } Jump ( delta ) => { increment = false ; self . counter = * delta ; } JumpIf ( delta ) => { increment = false ; let v = local . pop ( ) ? ; let b = Boolean :: try_from ( & * v . borrow ( ) ) ? ; if b { self . counter = * delta ; } } JumpIfNot ( delta ) => { increment = false ; let v = local . pop ( ) ? ; let b = Boolean :: try_from ( & * v . borrow ( ) ) ? ; if ! b { self . counter = * delta ; } } _ => return Err ( VMError :: Unimplemented ) , } ; if increment { self . counter += 1 ; } Ok ( ( ) ) }
Evaluate the instruction indexed by counter.
Evaluate the instruction indexed by counter .
&mut self
stack
&mut Stack