Some improvements to the thing
This commit is contained in:
parent
df76e7c120
commit
27729cefdf
@ -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)]
|
||||||
|
@ -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"))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user