Select Git revision
UDP-client-server.py
interpreter.rs 11.55 KiB
// Interpreter
use crate::ast::{Expr, Op, SpanExpr};
pub fn eval_expr(e: &SpanExpr) -> i32 {
match e.clone().1 {
Expr::Num(i) => i,
Expr::BinOp(op, l, r) => {
let lv = eval_expr(&l);
let rv = eval_expr(&r);
match op {
Op::Add => lv + rv,
Op::Sub => lv - rv,
Op::Mul => lv * rv,
Op::Div => lv / rv,
Op::Pow => lv.pow(rv as u32),
_ => unimplemented!(),
}
}
Expr::UnaryOp(op, e) => {
let e = eval_expr(&e);
match op {
Op::Add => e,
Op::Sub => -e,
_ => unimplemented!(),
}
}
_ => unimplemented!(),
}
}
// use crate::ast::{Binop, Cmd, Constant, Expr, Item, Prog, TypeDecl};
// use crate::check::{check_prog, Fenv, Tenv};
// use crate::parse::parse_prog;
//use std::collections::HashMap;
// pub type Addr = u32;
// #[derive(Debug, PartialEq, Clone)]
// pub enum Data {
// Value(Constant),
// Pointer(Addr),
// }
// pub type Venv = HashMap<String, Addr>;
// pub type Menv = HashMap<Addr, Data>;
// #[derive(Debug, PartialEq, Clone)]
// pub struct Mem {
// pub Addr: u32,
// pub Menv: Menv,
// }
// impl Mem {
// fn new() -> Mem {
// Mem {
// Addr: 0,
// Menv: Menv::new(),
// }
// }
// fn alloc(&mut self) -> Addr {
// // allocate a new address
// self.Addr += 1;
// self.Addr
// }
// }
// pub fn get_bool(d: Data) -> bool {
// if let Data::Value(Constant::Boolean(b)) = d {
// b
// } else {
// panic!("cannot evaluate into Boolean");
// }
// }
// pub fn get_i32(d: Data) -> i32 {
// if let Data::Value(Constant::Num(i)) = d {
// i
// } else {
// panic!("cannot evaluate into i32");
// }
// }
// pub fn eval_expr(exp: &Expr, mem: &mut Mem, venv: &Venv, fenv: &Fenv) -> Data {
// println!("\neval_expr {:?}, mem {:?}, venv {:?}", exp, mem, venv);
// match exp {
// Expr::Constant(c) => Data::Value(c.clone()),
// Expr::Binop(e1, op, e2) => {
// let ev1 = eval_expr(e1, mem, venv, fenv);
// let ev2 = eval_expr(e2, mem, venv, fenv);
// Data::Value(match op {
// Binop::And => Constant::Boolean(get_bool(ev1) && get_bool(ev2)),
// Binop::Or => Constant::Boolean(get_bool(ev1) && get_bool(ev2)),
// Binop::Equal => Constant::Boolean(ev1 == ev2),
// Binop::Less => Constant::Boolean(get_i32(ev1) < get_i32(ev2)),
// Binop::LessEqual => Constant::Boolean(get_i32(ev1) <= get_i32(ev2)),
// Binop::Greater => Constant::Boolean(get_i32(ev1) > get_i32(ev2)),
// Binop::GreaterEqual => Constant::Boolean(get_i32(ev1) >= get_i32(ev2)),
// Binop::Divide => Constant::Num(get_i32(ev1) / get_i32(ev2)),
// Binop::Reminder => Constant::Num(get_i32(ev1) % get_i32(ev2)),
// Binop::Minus => Constant::Num(get_i32(ev1) - get_i32(ev2)),
// Binop::Plus => Constant::Num(get_i32(ev1) + get_i32(ev2)),
// Binop::Times => Constant::Num(get_i32(ev1) * get_i32(ev2)),
// })
// }
// Expr::Id(id) => {
// let e = mem.Menv.get(venv.get(id).unwrap()).unwrap();
// println!("{:?} -> {:?}", id, e);
// e.to_owned()
// }
// Expr::Not(e) => {
// let ev = eval_expr(e, mem, venv, fenv);
// Data::Value(Constant::Boolean(!get_bool(ev)))
// }
// Expr::Application(id, exprs) => {
// // evaluate arguments
// println!("application {:?}", id);
// let args: Vec<Data> = exprs
// .into_iter()
// .map(|e| eval_expr(e, mem, venv, fenv))
// .collect();
// println!("args {:?}", args);
// // lookup callee
// let f = fenv.get(id).unwrap();
// println!("f {:?}", &f);
// let parameter_names: Vec<String> =
// f.sig.1.clone().into_iter().map(|idt| idt.0).collect();
// println!("f par_names {:?}", ¶meter_names);
// let mut lenv = Venv::new(); // local environment for function application
// let arg_assign: Vec<(String, Data)> =
// parameter_names.into_iter().zip(args.into_iter()).collect();
// println!("arg assignments {:?}", &arg_assign);
// for (id, val) in arg_assign {
// let addr = mem.alloc(); // get new allocation slot
// mem.Menv.insert(addr, val); // write the new value
// lenv.insert(id, addr);
// }
// println!("local enviroment {:?}", &lenv);
// println!("memory {:?}", &mem);
// // execute function, unwrap the result as we need a Constant
// eval_body(f.body.clone(), mem, &mut lenv, fenv).unwrap()
// }
// Expr::Ref(exp) => {
// println!("here");
// match *exp.to_owned() {
// Expr::Id(id) => {
// println!("id {:?}", &id);
// let addr = venv.get(&id).unwrap();
// Data::Pointer(*addr)
// }
// _ => {
// let val = eval_expr(exp, mem, venv, fenv);
// println!("-- value {:?}", &val);
// let addr = mem.alloc(); // get new allocation slot
// mem.Menv.insert(addr, val.to_owned()); // write the new value
// let ref_val = Data::Pointer(addr);
// println!(
// "Ref exp {:?} e {:?} mem {:?} venv {:?}",
// exp, val, mem, venv
// );
// ref_val
// }
// }
// }
// Expr::RefMut(exp) => {
// println!("here");
// match *exp.to_owned() {
// Expr::Id(id) => {
// println!("id {:?}", &id);
// let addr = venv.get(&id).unwrap();
// Data::Pointer(*addr)
// }
// _ => {
// let val = eval_expr(exp, mem, venv, fenv);
// println!("-- value {:?}", &val);
// let addr = mem.alloc(); // get new allocation slot
// mem.Menv.insert(addr, val.to_owned()); // write the new value
// let ref_val = Data::Pointer(addr);
// println!(
// "Ref exp {:?} e {:?} mem {:?} venv {:?}",
// exp, val, mem, venv
// );
// ref_val
// }
// }
// }
// Expr::Deref(exp) => {
// println!("-- Deref");
// let e = eval_expr(exp, mem, venv, fenv);
// println!("-- DereRef {:?} {:?}", exp, e);
// if let Data::Pointer(addr) = e {
// mem.Menv.get(&addr).unwrap().to_owned()
// } else {
// panic!("cannot deref {:?}", e);
// }
// }
// _ => unimplemented!(),
// }
// }
// pub fn eval_lvalue(exp: &Expr, mem: &mut Mem, venv: &Venv, fenv: &Fenv) -> Addr {
// println!("eval_lvalue {:?},{:?},{:?},{:?} ", exp, mem, venv, fenv);
// match exp {
// Expr::Id(id) => {
// let addr = venv.get(id).unwrap();
// println!("addr {:?}", addr);
// addr.to_owned()
// }
// Expr::Deref(exp) => {
// let lv = eval_expr(exp, mem, venv, fenv);
// println!("lv {:?}", lv);
// match eval_expr(exp, mem, venv, fenv) {
// Data::Pointer(addr) => addr,
// _ => panic!("cannot deref {:?}", exp),
// }
// }
// _ => unimplemented!(),
// }
// }
// // commands may return with a value
// // either directly (return) or
// // if inside an inner block (then/else, or while)
// pub fn menv_update(data: Data, menv: &mut Menv) {
// // match data {
// // Pointer::
// // }
// }
// pub fn dump(msg: &str, mem: &Mem, venv: &Venv) {
// println!("{:?} {:?} {:?}", msg, mem, venv);
// }
// // A return genaretes Some(Data) else None
// pub fn eval_cmd(cmd: &Cmd, mem: &mut Mem, venv: &mut Venv, fenv: &Fenv) -> Option<Data> {
// println!("{:?}", cmd);
// match cmd {
// Cmd::Assign(lexp, rexp) => {
// let rval = eval_expr(rexp, mem, venv, fenv);
// println!("val {:?}", rval);
// let addr = eval_lvalue(lexp, mem, venv, fenv);
// // println!("lval {:?}", lval);
// // let addr = venv.get(&lval).unwrap();
// mem.Menv.insert(addr, rval);
// None
// }
// Cmd::If(exp, then_block, opt_else) => {
// if get_bool(eval_expr(exp, mem, venv, fenv)) {
// eval_body(then_block.to_vec(), mem, venv, fenv)
// } else {
// if let Some(else_block) = opt_else {
// eval_body(else_block.to_vec(), mem, venv, fenv)
// } else {
// None
// }
// }
// }
// Cmd::Let(_, id, _, exp) => {
// let val = eval_expr(exp, mem, venv, fenv);
// println!("val {:?}", val);
// let addr = mem.alloc(); // get new allocation slot
// mem.Menv.insert(addr, val); // write the new value
// venv.insert(id.to_owned(), addr);
// dump("after Let", mem, venv);
// None
// }
// Cmd::Return(exp) => {
// let v = Some(eval_expr(exp, mem, venv, fenv));
// println!("return value {:?}", v);
// v
// }
// Cmd::While(exp, body) => {
// while get_bool(eval_expr(exp, mem, venv, fenv)) {
// if let Some(retv) = eval_body(body.to_vec(), mem, venv, fenv) {
// return Some(retv);
// }
// }
// None
// }
// }
// }
// pub fn eval_body(cmds: Vec<Cmd>, mem: &mut Mem, venv: &mut Venv, fenv: &Fenv) -> Option<Data> {
// for c in &cmds {
// if let Some(ret) = eval_cmd(c, mem, venv, fenv) {
// return Some(ret);
// }
// }
// None
// }
// pub fn build_env(prog: Prog) -> (Tenv, Fenv) {
// let mut tenv = Tenv::new();
// let mut fenv = Fenv::new();
// for i in prog {
// match i {
// Item::TypeDecl(TypeDecl::Struct(id, layout)) => {
// tenv.insert(id.clone(), TypeDecl::Struct(id, layout));
// }
// Item::Function(f) => {
// fenv.insert(f.sig.0.to_owned(), f);
// }
// }
// }
// (tenv, fenv)
// }
// pub fn eval_prog(prog: &str) {
// let (unparsed, prog) = parse_prog(prog).unwrap();
// println!("prog: {:?}", prog);
// println!("unparsed: {:?}", unparsed);
// let (tenv, fenv) = check_prog(&prog);
// println!("envs {:?}", (tenv, &fenv));
// // assume main does not take any parameters
// let call_main = Expr::Application("main".to_owned(), Vec::<Expr>::new());
// let mut mem = Mem::new();
// let mut venv = Venv::new();
// let ret = eval_expr(&call_main, &mut mem, &mut venv, &fenv);
// println!("return from main = {:?}", ret);
// println!("venv = {:?}", venv);
// println!("mem = {:?}", mem);
// }