use super::parser::AST;
use super::parser::AST::*;
use super::parser::BinOps::*;
use super::parser::UnOps::*;
use std::collections::HashMap;
pub struct Interpreter {
current: Frame
}
#[derive(Clone)]
struct Frame {
parent: Option<Box<Frame>>,
locals: HashMap<String, Box<AST>>,
}
trait Replace {
fn replace(&self, orig: &str, repl: &str) -> String;
}
impl Replace for String {
fn replace(&self, orig: &str, repl: &str) -> String {
self.as_slice().replace(orig, repl)
}
}
impl Frame {
fn get(&mut self, s: &String) -> Option<Box<AST>> {
match self.locals.get_mut(s) {
Some(r) => Some(r.clone()),
None => {
match self.parent {
Some(ref mut p) => p.get(s),
None => None
}
}
}
}
}
#[allow(unused_variables)]
impl Interpreter {
pub fn new() -> Interpreter {
let f = Frame{parent: None, locals: HashMap::new()};
Interpreter{current: f}
}
pub fn toplevel(&mut self, statements: Vec<AST>) -> Result<Box<AST>, String> {
for ast in statements.iter() {
match self.eval(ast) {
Ok(box Return(a, b)) => return Err(format!("`return` can not appear here: col={} row={} {}", b.col, b.row, b.place)),
Ok(box Continue(b)) => return Err(format!("`continue` can not appear here: col={} row={} {}", b.col, b.row, b.place)),
Ok(box Break(b)) => return Err(format!("`break` can not appear here: col={} row={} {}", b.col, b.row, b.place)),
Ok(_) => (),
Err(e) => {
return Err(e);
}
}
}
return Ok(Box::new(Empty));
}
pub fn exec(&mut self, statements: Vec<AST>) -> Result<Box<AST>, String> {
for ast in statements.iter() {
match self.eval(ast) {
Ok(box Return(a, b)) => return Ok(Box::new(Return(a.clone(), b.clone()))),
Ok(box Continue(a)) => return Ok(Box::new(Continue(a.clone()))),
Ok(box Break(a)) => return Ok(Box::new(Break(a.clone()))),
Ok(_) => (),
Err(e) => {
return Err(e);
}
}
}
return Ok(Box::new(Empty));
}
pub fn debug(&self) {
for (name, value) in self.current.locals.iter() {
println!("{} => {:?}", name, value);
}
}
fn eval(&mut self, ast: &AST) -> Result<Box<AST>, String> {
match ast {
&Assign(ref s, ref expr, ref loc) => {
match self.eval(&**expr) {
Ok(x) => {
match s {
&box String_(ref n)=> {
self.current.locals.insert(n.clone(), x);
return Ok(Box::new(Empty));
},
&box IndexRef(ref expr, ref index) => {
let (base, mut acc) = self.traverse(&**expr);
acc.push(*index.clone());
let res = self.recursive_assign(&*base, acc, &*x);
match res {
Ok(r) => {
return match base {
box VarRef(ref a, ref b) =>
return self.eval(&Assign(Box::new(String_(a.clone())), r.clone(), loc.clone())),
_ => panic!("bug")
};
},
Err(e) => return Err(e.clone())
}
},
b @ _ => panic!("bug: {:?}", b)
};
},
Err(e) => Err(e)
}
},
&If(ref cond, ref then_, ref else_, ref loc) => {
match self.eval(&**cond) {
Ok(box Bool_(true)) => self.eval(&**then_),
Ok(box Bool_(false)) => self.eval(&**else_),
Ok(_) => Err(format!("condition must be bool value: {}", loc.clone())),
Err(e) => Err(e.clone()),
}
},
&For(ref name, ref itr, ref block, ref loc) => {
let vn = name.clone();
match self.eval(&**itr) {
Ok(v) => {
match v {
box List_(ref vec, ref l) => {
for i in vec.iter() {
let c = self.current.clone();
let b = false;
let mut f = Frame{
parent: Some(Box::new(self.current.clone())),
locals: HashMap::new()
};
f.locals.insert(vn.clone(), Box::new(i.clone()));
self.current = f;
match self.eval(&**block) {
Err(e) => {
self.current = c;
return Err(e.clone())
},
Ok(box Break(_))=> {
self.current = c;
break;
},
Ok(box Continue(_))=> {
self.current = c;
continue;
},
Ok(box Return(v, l)) => {
self.current = c;
return Ok(Box::new(Return(v.clone(), l.clone())))
}
_ => (),
}
self.current = c;
}
Ok(Box::new(Empty))
},
_ => Err(format!("{:?} is not iterable", v))
}
},
Err(e) => Err(e.clone())
}
},
&Print(ref expr, ref loc) => {
match self.eval(&**expr) {
Ok(v) => println!("{}", self.to_string(&*v)),
Err(e) => return Err(e.clone())
};
Ok(Box::new(Empty))
},
&DefFunc(ref name, ref params, ref block, ref loc) => {
self.current.locals.insert(name.clone(), Box::new(DefFunc(name.clone(), params.clone(), block.clone(), loc.clone())));
Ok(Box::new(Empty))
},
&Return(ref v, ref loc) => match self.eval(&**v) {
Ok(r) => Ok(Box::new(Return(r.clone(), loc.clone()))),
Err(e) => Err(e.clone())
},
&Continue(ref loc) => return Ok(Box::new(Continue(loc.clone()))),
&Break(ref loc) => return Ok(Box::new(Break(loc.clone()))),
&Int_(ref v) => Ok(Box::new(Int_(*v))),
&Float_(ref v) => Ok(Box::new(Float_(*v))),
&String_(ref v) => Ok(Box::new(String_((*v).clone()))),
&Bool_(ref v) => Ok(Box::new(Bool_(*v))),
&Null => Ok(Box::new(Null)),
&List_(ref vec, ref loc) => {
let mut l = Vec::new();
for v in vec.clone().iter() {
match self.eval(v) {
Ok(o) => l.push(*o.clone()),
Err(e) => return Err(e.clone())
}
}
Ok(Box::new(List_(l.clone(), loc.clone())))
},
&Object_(ref map, ref loc) => {
let mut m = HashMap::new();
for (k, v) in map.iter() {
match self.eval(v) {
Ok(o) => m.insert(k.clone(), *o.clone()),
Err(e) => return Err(e.clone())
};
}
Ok(Box::new(Object_(m.clone(), loc.clone())))
},
&Block(ref stmt, ref loc) => match self.exec(stmt.clone()) {
Ok(e) => Ok(e.clone()),
Err(e) => Err(e.clone())
},
&VarRef(ref name, ref loc) => {
let r = self.current.get(&name.clone());
match r {
Some(v) => Ok(v),
None => Err(format!("{} is not defined", name.clone()))
}
},
&BinOp(ref op, ref left, ref right) => {
match self.eval(&(*left.clone())) {
Ok(l) => match self.eval(&(*right.clone())) {
Ok(r) => self.operate(BinOp(op.clone(), l, r)),
Err(e) => Err(e)
},
Err(e) => Err(e)
}
},
&UnOp(ref op, ref expr) => match op.clone() {
PLUS => match self.eval(&**expr) {
Ok(box Int_(v))=> Ok(Box::new(Int_(v))),
Ok(box Float_(v))=> Ok(Box::new(Float_(v))),
_ => Err(format!("error!"))
},
MINUS => match self.eval(&**expr) {
Ok(box Int_(v))=> Ok(Box::new(Int_(-v))),
Ok(box Float_(v))=> Ok(Box::new(Float_(-v))),
_ => Err(format!("error!"))
},
NOT => match self.eval(&**expr) {
Ok(box Bool_(v))=> Ok(Box::new(Bool_(!v))),
_ => Err(format!("error!"))
}
},
&FunCall(ref fname, ref args, ref loc) => {
let mut local = self.current.clone();
let r = local.get(&fname.clone());
match r {
Some(box DefFunc(ref name, ref params, ref body, ref loc)) => {
if args.len() != params.len() {
return Err(format!("Can not apply {} arguments to {}", args.len(), name.clone()));
}
let b = false;
let mut f = Frame{
parent: Some(Box::new(self.current.clone())),
locals: HashMap::new()
};
let mut zp = args.iter().zip(params.iter());
for (expr, name) in zp {
match self.eval(expr) {
Ok(v) => f.locals.insert(name.clone(), v.clone()),
Err(e) => {
return Err(e.clone());
}
};
}
let c = self.current.clone();
self.current = f;
let res = match self.eval(&**body) {
Ok(box Return(expr, loc)) => Ok(Box::new(*expr.clone())),
Ok(box Continue(b))=> Err(format!("`continue` can not appear here: col={} row={} {}", b.col, b.row, b.place)),
Ok(box Break(b))=> Err(format!("`break` can not appear here: col={} row={} {}", b.col, b.row, b.place)),
Err(e) => Err(e.clone()),
_ => Ok(Box::new(Null))
};
self.current = c;
return res;
},
None => Err(format!("{} is not defined", fname.clone())),
Some(x @ _) => Err(format!("Can not call object: {:?}", x))
}
},
&IndexRef(ref expr, ref index) => {
let e = self.eval(&**expr);
match e {
Ok(box List_(ref ls, ref loc)) => match self.eval(&**index) {
Ok(box Int_(v))=> {
let idx = if v < 0 {
(ls.len() as isize + v) as usize
} else {
v as usize
};
if ls.len() <= idx {
Err(format!("Index ou of range: {}", v))
} else {
Ok(Box::new(ls[idx].clone()))
}
},
Ok(_) => Err("list indices must be integer".to_string()),
Err(e) => Err(e.clone())
},
Ok(box Object_(ref mp, ref loc)) => match self.eval(&**index) {
Ok(box String_(ref v))=> {
match mp.get(&v.clone()) {
Some(val) => Ok(Box::new(val.clone())),
None => Err(format!("key error: {}", v))
}
},
Ok(_) => Err("Key must be string".to_string()),
Err(e) => Err(e.clone())
},
Ok(_) => Err("must be list or object".to_string()),
Err(e) => Err(e.clone())
}
},
_ => {
Err("Not implemented yet".to_string())
}
}
}
fn traverse(&mut self, expr: &AST) -> (Box<AST>, Vec<AST>) {
match expr {
&IndexRef(ref e, ref idx) => {
let (r, mut vec) = self.traverse(&**e);
vec.push(*idx.clone());
(r, vec)
},
r @ _ => (Box::new(r.clone()), Vec::new())
}
}
fn recursive_assign(&mut self, expr: &AST, indices: Vec<AST>, val: &AST) -> Result<Box<AST>, String> {
match self.eval(expr) {
Ok(box List_(ref mut ls, ref loc)) => {
let i = indices[0].clone();
match self.eval(&i) {
Ok(box Int_(n) )=> {
let idx = if n < 0 {
((ls.len() as isize) + n) as usize
} else {
n as usize
};
if idx >= ls.len() {
return Err(format!("Index out of range: {}", idx));
}
if indices.len() > 1 {
let rest = indices.slice_from(1).to_vec();
let x = ls[idx].clone();
match self.recursive_assign(&x, rest, val) {
Ok(res) => ls[idx] = *res.clone(),
Err(e) => return Err(e.clone())
}
} else {
ls[idx] = val.clone();
}
return Ok(Box::new(List_(ls.clone(), loc.clone())));
},
Ok(_) => return Err("List indices must be integer".to_string()),
Err(e) => return Err(e.clone())
}
},
Ok(box Object_(ref mut mp, ref loc)) => {
let i = indices[0].clone();
match self.eval(&i) {
Ok(box String_(s) )=> {
if indices.len() > 1 {
let rest = indices.slice_from(1).to_vec();
let x = mp[s].clone();
match self.recursive_assign(&x, rest, val) {
Ok(res) => mp[s] = *res.clone(),
Err(e) => return Err(e.clone())
}
} else {
mp[s] = val.clone();
}
return Ok(Box::new(Object_(mp.clone(), loc.clone())));
}
Ok(_) => return Err("Key must be string".to_string()),
Err(e) => return Err(e.clone())
}
},
Ok(a) => {return Err(format!("list or object required: {:?}", a));},
Err(e) => {return Err(e.clone());}
};
}
fn operate(&self, triple: AST) -> Result<Box<AST>, String> {
match triple {
BinOp(ADD, box Int_(l), box Int_(r) )=> Ok(Box::new(Int_(l+r))),
BinOp(SUB, box Int_(l), box Int_(r) )=> Ok(Box::new(Int_(l-r))),
BinOp(MUL, box Int_(l), box Int_(r) )=> Ok(Box::new(Int_(l*r))),
BinOp(DIV, box Int_(l), box Int_(r) )=> Ok(Box::new(Int_(l/r))),
BinOp(MOD, box Int_(l), box Int_(r) )=> Ok(Box::new(Int_(l%r))),
BinOp(EQ, box Int_(l), box Int_(r) )=> Ok(Box::new(Bool_(l==r))),
BinOp(NE, box Int_(l), box Int_(r) )=> Ok(Box::new(Bool_(l!=r))),
BinOp(GT, box Int_(l), box Int_(r) )=> Ok(Box::new(Bool_(l>r))),
BinOp(GE, box Int_(l), box Int_(r) )=> Ok(Box::new(Bool_(l>=r))),
BinOp(LT, box Int_(l), box Int_(r) )=> Ok(Box::new(Bool_(l<r))),
BinOp(LE, box Int_(l), box Int_(r) )=> Ok(Box::new(Bool_(l<=r))),
BinOp(ADD, box Float_(l), box Float_(r) )=> Ok(Box::new(Float_(l+r))),
BinOp(SUB, box Float_(l), box Float_(r) )=> Ok(Box::new(Float_(l-r))),
BinOp(MUL, box Float_(l), box Float_(r) )=> Ok(Box::new(Float_(l*r))),
BinOp(DIV, box Float_(l), box Float_(r) )=> Ok(Box::new(Float_(l/r))),
BinOp(MOD, box Float_(l), box Float_(r) )=> Ok(Box::new(Float_(l%r))),
BinOp(EQ, box Float_(l), box Float_(r) )=> Ok(Box::new(Bool_(l==r))),
BinOp(NE, box Float_(l), box Float_(r) )=> Ok(Box::new(Bool_(l!=r))),
BinOp(GT, box Float_(l), box Float_(r) )=> Ok(Box::new(Bool_(l>r))),
BinOp(GE, box Float_(l), box Float_(r) )=> Ok(Box::new(Bool_(l>=r))),
BinOp(LT, box Float_(l), box Float_(r) )=> Ok(Box::new(Bool_(l<r))),
BinOp(LE, box Float_(l), box Float_(r) )=> Ok(Box::new(Bool_(l<=r))),
BinOp(ADD, box Int_(l), box Float_(r) )=> Ok(Box::new(Float_(l as f64+r))),
BinOp(SUB, box Int_(l), box Float_(r) )=> Ok(Box::new(Float_(l as f64-r))),
BinOp(MUL, box Int_(l), box Float_(r) )=> Ok(Box::new(Float_(l as f64*r))),
BinOp(DIV, box Int_(l), box Float_(r) )=> Ok(Box::new(Float_(l as f64/r))),
BinOp(MOD, box Int_(l), box Float_(r) )=> Ok(Box::new(Float_(l as f64%r))),
BinOp(EQ, box Int_(l), box Float_(r) )=> Ok(Box::new(Bool_(l as f64==r))),
BinOp(NE, box Int_(l), box Float_(r) )=> Ok(Box::new(Bool_(l as f64!=r))),
BinOp(GT, box Int_(l), box Float_(r) )=> Ok(Box::new(Bool_(l as f64>r))),
BinOp(GE, box Int_(l), box Float_(r) )=> Ok(Box::new(Bool_(l as f64>=r))),
BinOp(LT, box Int_(l), box Float_(r) )=> Ok(Box::new(Bool_((l as f64) <r))),
BinOp(LE, box Int_(l), box Float_(r) )=> Ok(Box::new(Bool_(l as f64<=r))),
BinOp(ADD, box Float_(l), box Int_(r) )=> Ok(Box::new(Float_(l+r as f64))),
BinOp(SUB, box Float_(l), box Int_(r) )=> Ok(Box::new(Float_(l-r as f64))),
BinOp(MUL, box Float_(l), box Int_(r) )=> Ok(Box::new(Float_(l*r as f64))),
BinOp(DIV, box Float_(l), box Int_(r) )=> Ok(Box::new(Float_(l/r as f64))),
BinOp(MOD, box Float_(l), box Int_(r) )=> Ok(Box::new(Float_(l%r as f64))),
BinOp(EQ, box Float_(l), box Int_(r) )=> Ok(Box::new(Bool_(l==r as f64))),
BinOp(NE, box Float_(l), box Int_(r) )=> Ok(Box::new(Bool_(l!=r as f64))),
BinOp(GT, box Float_(l), box Int_(r) )=> Ok(Box::new(Bool_(l>r as f64))),
BinOp(GE, box Float_(l), box Int_(r) )=> Ok(Box::new(Bool_(l>=r as f64))),
BinOp(LT, box Float_(l), box Int_(r) )=> Ok(Box::new(Bool_(l<r as f64))),
BinOp(LE, box Float_(l), box Int_(r) )=> Ok(Box::new(Bool_(l<=r as f64))),
BinOp(ADD, box String_(l), box String_(r) )=> {
let mut s = String::new();
s.push_str(l.as_slice());
s.push_str(r.as_slice());
Ok(box String_(s.clone()))
},
BinOp(MUL, box String_(l), box Int_(r) )=> {
let mut s = String::new();
for i in range(0, r) {
s.push_str(l.as_slice());
}
Ok(box String_(s.clone()))
},
BinOp(EQ, box String_(l), box String_(r) )=> Ok(Box::new(Bool_(l.as_slice() == r.as_slice()))),
BinOp(NE, box String_(l), box String_(r) )=> Ok(Box::new(Bool_(l.as_slice() != r.as_slice()))),
BinOp(EQ, box Bool_(l), box Bool_(r) )=> Ok(Box::new(Bool_(l == r))),
BinOp(NE, box Bool_(l), box Bool_(r) )=> Ok(Box::new(Bool_(l != r))),
BinOp(LAND, box Bool_(l), box Bool_(r) )=> Ok(Box::new(Bool_(l && r))),
BinOp(LOR, box Bool_(l), box Bool_(r) )=> Ok(Box::new(Bool_(l || r))),
BinOp(EQ, box Null, box Null )=> Ok(Box::new(Bool_(true))),
BinOp(EQ, _, box Null )=> Ok(Box::new(Bool_(false))),
BinOp(EQ, box Null, _) => Ok(Box::new(Bool_(false))),
BinOp(NE, box Null, box Null)=> Ok(Box::new(Bool_(false))),
BinOp(NE, _, box Null )=> Ok(Box::new(Bool_(true))),
BinOp(NE, box Null, _) => Ok(Box::new(Bool_(true))),
BinOp(a @ _, b @ _, c @ _) => Err(format!("{:?} is not defined between {:?} and {:?}", a, b, c)),
_ => Err("undefined operation".to_string())
}
}
fn to_string(&self, term: &AST) -> String {
match term {
&Int_(i) => format!("{}", i),
&Float_(f) => format!("{}", f),
&String_(ref s) => s.clone(),
&Bool_(b) => format!("{}", b),
&Null => "null".to_string(),
&DefFunc(ref s, ref v, ref b, ref l) => format!("<{}({:?})>", s, v),
&List_(ref e, ref l) => {
let mut r = Vec::new();
for v in e.iter() {
r.push(self.to_string_quote_str(v));
}
format!("[{}]", r.connect(", "))
},
&Object_(ref e, ref l) => {
let mut r = Vec::new();
for (k,v) in e.iter() {
r.push(format!("{}: {}", k, self.to_string_quote_str(v)));
}
format!("{{{}}}", r.connect(", "))
}
a @ _ => format!("{:?}", a)
}
}
fn to_string_quote_str(&self, term: &AST) -> String {
match term {
&String_(ref s) => format!("\"{}\"", s).replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t").replace("\\", "\\\\"),
_ => self.to_string(term)
}
}
}