diff --git a/schala-lang/src/ast_reducing.rs b/schala-lang/src/ast_reducing.rs index 24fd796..51795ce 100644 --- a/schala-lang/src/ast_reducing.rs +++ b/schala-lang/src/ast_reducing.rs @@ -51,7 +51,7 @@ pub enum Lit { Float(f64), Bool(bool), StringLit(Rc), - Custom(Rc), + Custom(Rc, Vec), } #[derive(Debug, Clone)] diff --git a/schala-lang/src/eval.rs b/schala-lang/src/eval.rs index a83a182..dfdbe90 100644 --- a/schala-lang/src/eval.rs +++ b/schala-lang/src/eval.rs @@ -44,10 +44,24 @@ enum ValueEntry { type EvalResult = Result; + impl Expr { fn to_repl(&self) -> String { use self::Lit::*; use self::Func::*; + fn paren_wrapped_vec(exprs: &Vec) -> 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 { Expr::Lit(ref l) => match l { Nat(n) => format!("{}", n), @@ -55,25 +69,15 @@ impl Expr { Float(f) => format!("{}", f), Bool(b) => format!("{}", b), 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 { BuiltIn(name) => format!("", name), UserDefined { name: None, .. } => format!(""), UserDefined { name: Some(name), .. } => format!("", name), }, - Expr::Tuple(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 - }, + Expr::Tuple(exprs) => paren_wrapped_vec(exprs), _ => format!("{:?}", self), } } @@ -141,13 +145,7 @@ impl<'a> State<'a> { literal @ Lit(_) => Ok(literal), Call { box f, args } => { if let Val(name) = f { - let symbol_table = self.symbol_table_handle.borrow(); - 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)) - } + self.apply_data_constructor(name, args) } else { match self.expression(f)? { Func(f) => self.apply_function(f, args), @@ -180,6 +178,19 @@ impl<'a> State<'a> { } } + fn apply_data_constructor(&mut self, name: Rc, args: Vec) -> EvalResult { + 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) -> EvalResult { match f { Func::BuiltIn(sigil) => self.apply_builtin(sigil, args), @@ -278,7 +289,7 @@ impl<'a> State<'a> { Some(Symbol { name, spec }) => match spec { SymbolSpec::DataConstructor { type_name, type_args } => { if type_args.len() == 0 { - Expr::Lit(Lit::Custom(name.clone())) + Expr::Lit(Lit::Custom(name.clone(), vec![])) } else { return Err(format!("This data constructor thing not done")) }