Some improvements to the thing

This commit is contained in:
greg 2018-06-04 18:17:03 -07:00
parent df76e7c120
commit 27729cefdf
2 changed files with 33 additions and 22 deletions

View File

@ -51,7 +51,7 @@ pub enum Lit {
Float(f64), Float(f64),
Bool(bool), Bool(bool),
StringLit(Rc<String>), StringLit(Rc<String>),
Custom(Rc<String>), Custom(Rc<String>, Vec<Expr>),
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View File

@ -44,10 +44,24 @@ enum ValueEntry {
type EvalResult<T> = Result<T, String>; type EvalResult<T> = Result<T, String>;
impl Expr { impl Expr {
fn to_repl(&self) -> String { fn to_repl(&self) -> String {
use self::Lit::*; use self::Lit::*;
use self::Func::*; use self::Func::*;
fn paren_wrapped_vec(exprs: &Vec<Expr>) -> String {
let mut buf = String::new();
write!(buf, "(").unwrap();
for term in exprs.iter().map(|e| Some(e)).intersperse(None) {
match term {
Some(e) => write!(buf, "{}", e.to_repl()).unwrap(),
None => write!(buf, ", ").unwrap(),
};
}
write!(buf, ")").unwrap();
buf
}
match self { match self {
Expr::Lit(ref l) => match l { Expr::Lit(ref l) => match l {
Nat(n) => format!("{}", n), Nat(n) => format!("{}", n),
@ -55,25 +69,15 @@ impl Expr {
Float(f) => format!("{}", f), Float(f) => format!("{}", f),
Bool(b) => format!("{}", b), Bool(b) => format!("{}", b),
StringLit(s) => format!("\"{}\"", s), StringLit(s) => format!("\"{}\"", s),
Custom(s) => format!("{}", s), Custom(name, args) if args.len() == 0 => format!("{}", name),
Custom(name, args) => format!("{}{}", name, paren_wrapped_vec(args)),
}, },
Expr::Func(f) => match f { Expr::Func(f) => match f {
BuiltIn(name) => format!("<built-in function {}>", name), BuiltIn(name) => format!("<built-in function {}>", name),
UserDefined { name: None, .. } => format!("<function>"), UserDefined { name: None, .. } => format!("<function>"),
UserDefined { name: Some(name), .. } => format!("<function {}>", name), UserDefined { name: Some(name), .. } => format!("<function {}>", name),
}, },
Expr::Tuple(exprs) => { Expr::Tuple(exprs) => paren_wrapped_vec(exprs),
let mut buf = String::new();
write!(buf, "(").unwrap();
for term in exprs.iter().map(|e| Some(e)).intersperse(None) {
match term {
Some(e) => write!(buf, "{}", e.to_repl()).unwrap(),
None => write!(buf, ", ").unwrap(),
};
}
write!(buf, ")").unwrap();
buf
},
_ => format!("{:?}", self), _ => format!("{:?}", self),
} }
} }
@ -141,13 +145,7 @@ impl<'a> State<'a> {
literal @ Lit(_) => Ok(literal), literal @ Lit(_) => Ok(literal),
Call { box f, args } => { Call { box f, args } => {
if let Val(name) = f { if let Val(name) = f {
let symbol_table = self.symbol_table_handle.borrow(); self.apply_data_constructor(name, args)
match symbol_table.values.get(&name) {
Some(Symbol { spec: SymbolSpec::DataConstructor { type_name, type_args }, .. }) => {
Ok(Expr::Lit(self::Lit::Nat(99)))
},
_ => return Err(format!("Bad symbol {}", name))
}
} else { } else {
match self.expression(f)? { match self.expression(f)? {
Func(f) => self.apply_function(f, args), Func(f) => self.apply_function(f, args),
@ -180,6 +178,19 @@ impl<'a> State<'a> {
} }
} }
fn apply_data_constructor(&mut self, name: Rc<String>, args: Vec<Expr>) -> EvalResult<Expr> {
let symbol_table = self.symbol_table_handle.borrow();
match symbol_table.values.get(&name) {
Some(Symbol { spec: SymbolSpec::DataConstructor { type_name, type_args }, name }) => {
if args.len() != type_args.len() {
return Err(format!("Data constructor {} requires {} args", name, type_args.len()));
}
Ok(Expr::Lit(self::Lit::Custom(name.clone(), vec![])))
},
_ => return Err(format!("Bad symbol {}", name))
}
}
fn apply_function(&mut self, f: Func, args: Vec<Expr>) -> EvalResult<Expr> { fn apply_function(&mut self, f: Func, args: Vec<Expr>) -> EvalResult<Expr> {
match f { match f {
Func::BuiltIn(sigil) => self.apply_builtin(sigil, args), Func::BuiltIn(sigil) => self.apply_builtin(sigil, args),
@ -278,7 +289,7 @@ impl<'a> State<'a> {
Some(Symbol { name, spec }) => match spec { Some(Symbol { name, spec }) => match spec {
SymbolSpec::DataConstructor { type_name, type_args } => { SymbolSpec::DataConstructor { type_name, type_args } => {
if type_args.len() == 0 { if type_args.len() == 0 {
Expr::Lit(Lit::Custom(name.clone())) Expr::Lit(Lit::Custom(name.clone(), vec![]))
} else { } else {
return Err(format!("This data constructor thing not done")) return Err(format!("This data constructor thing not done"))
} }