diff --git a/src/emitter.rs b/src/emitter.rs index 7873ca4..cb1772f 100644 --- a/src/emitter.rs +++ b/src/emitter.rs @@ -78,13 +78,6 @@ pub fn emit(w: &mut dyn Write, stmt: &parser::Stmt, ctx: &mut LexicalContext) -> writeln!(w, "return;")?; } } - parser::Stmt::Funcall(call) => { - if ctx.is_tail { - write!(w, "return ")?; - } - emit_expr(w, call, ctx)?; - writeln!(w, ";")?; - } parser::Stmt::Conditional(if_blocks, else_block) => { let mut first_block = true; for if_block in if_blocks { diff --git a/src/parser.rs b/src/parser.rs index 075c930..e9cb611 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3,7 +3,6 @@ use std::fmt; #[derive(Debug,PartialEq,Clone)] pub enum Stmt { Assignment(String, Expr), - Funcall(Expr), Conditional(Vec, Option), Loop(Loop), BareExpr(Expr), @@ -34,16 +33,6 @@ pub enum Atom { Bool(bool), } -impl fmt::Display for Atom { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Atom::String(a) => write!(f, "\"{}\"", a), - Atom::Num(a) => write!(f, "{}", a), - Atom::Bool(a) => write!(f, "{}", a), - } - } -} - #[derive(Debug,PartialEq,Clone)] pub struct GuardedBlock { pub guard: Expr, @@ -63,7 +52,6 @@ peg::parser! { = __* s:stmt()* { s } pub rule stmt() -> Stmt = a:assignment() { a } / - f:funcall() stop() { Stmt::Funcall(f) } / c:conditional() { c } / l:_loop() { Stmt::Loop(l) } / e:expr() stop() { Stmt::BareExpr(e) } @@ -215,6 +203,86 @@ pub fn parse_stmt(stmt: &str) -> Stmt { deelang_parser::stmt(&stmt).unwrap() } +impl fmt::Display for Stmt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Stmt::Assignment(id, expr) => writeln!(f, "{} <- {}", id, expr), + Stmt::BareExpr(expr) => writeln!(f, "{}", expr), + Stmt::Conditional(guarded_blocks, else_block) => { + let (if_block, elif_blocks) = guarded_blocks.split_first().unwrap(); + write!(f, "if {}", if_block.guard)?; + write_block(f, &if_block.block)?; + for elif_block in elif_blocks { + write!(f, "elif {}", elif_block.guard)?; + write_block(f, &if_block.block)?; + } + if let Some(block) = else_block { + write!(f, "else")?; + write_block(f, &block)?; + } + Ok(()) + } + Stmt::Loop(loop_inner) => match &loop_inner { + Loop::Bare(block) => { + write!(f, "loop")?; + write_block(f, block) + } + Loop::Over(id, pred, block) => { + write!(f, "loop over {} in {}", id, pred)?; + write_block(f, block) + } + Loop::Until(guarded_block) => { + write!(f, "loop until {}", guarded_block.guard)?; + write_block(f, &guarded_block.block) + } + }, + } + } +} + +fn write_block (f: &mut fmt::Formatter<'_>, block: &Block) -> fmt::Result { + if block.len() == 1 { + writeln!(f, " {}", block[0]) + } else { + writeln!(f)?; + writeln!(f, ">>>")?; + for stmt in block { + write!(f, "{}", stmt)?; + } + writeln!(f, "<<<") + } +} + +impl fmt::Display for Expr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Expr::Atom(a) => write!(f, "{}", a), + Expr::Id(id) => write!(f, "{}", id), + Expr::Equal(e1, e2) => write!(f, "{} = {}", e1, e2), + Expr::Relop(op, e1, e2) => write!(f, "{} {} {}", e1, op, e2), + Expr::Plus(e1, e2) => write!(f, "{} + {}", e1, e2), + Expr::Minus(e1, e2) => write!(f, "{} - {}", e1, e2), + Expr::Div(e1, e2) => write!(f, "{} / {}", e1, e2), + Expr::Mult(e1, e2) => write!(f, "{} * {}", e1, e2), + Expr::Mod(e1, e2) => write!(f, "{} % {}", e1, e2), + Expr::UnaryMinus(e) => write!(f, "-{}", e), + + Expr::Funcdef(_arg, _block) => todo!(), + Expr::Funcall(_id, _args) => todo!(), + } + } +} + +impl fmt::Display for Atom { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Atom::String(a) => write!(f, "\"{}\"", a), + Atom::Num(a) => write!(f, "{}", a), + Atom::Bool(a) => write!(f, "{}", a), + } + } +} + #[cfg(test)] mod test { @@ -232,8 +300,8 @@ apple <- 1 ## This is too #[test] fn test_funcall() { let expected = vec![ - Stmt::Funcall(Expr::Funcall("pear".to_string(), vec![])), - Stmt::Funcall(Expr::Funcall("pear".to_string(), + Stmt::BareExpr(Expr::Funcall("pear".to_string(), vec![])), + Stmt::BareExpr(Expr::Funcall("pear".to_string(), vec![Expr::Id("x".to_string()), Expr::Id("y".to_string())], )) ]; @@ -326,8 +394,8 @@ foo <- x -> y -> x * y"; Expr::Funcdef( None, vec![ - Stmt::Funcall(Expr::Funcall("bar".to_string(), vec![])), - Stmt::Funcall(Expr::Funcall("baz".to_string(), vec![])), + Stmt::BareExpr(Expr::Funcall("bar".to_string(), vec![])), + Stmt::BareExpr(Expr::Funcall("baz".to_string(), vec![])), ], ) ), @@ -366,14 +434,14 @@ else vec![ GuardedBlock { guard: Expr::Id("foo".to_string()), - block: vec![Stmt::Funcall(Expr::Funcall("bar".to_string(), vec![]))] + block: vec![Stmt::BareExpr(Expr::Funcall("bar".to_string(), vec![]))] }, GuardedBlock { guard: Expr::Id("baz".to_string()), - block: vec![Stmt::Funcall(Expr::Funcall("foobar".to_string(), vec![]))], + block: vec![Stmt::BareExpr(Expr::Funcall("foobar".to_string(), vec![]))], }, ], - Some(vec![Stmt::Funcall(Expr::Funcall("quux".to_string(), vec![]))]), + Some(vec![Stmt::BareExpr(Expr::Funcall("quux".to_string(), vec![]))]), )]; assert_eq!(deelang_parser::program(prgm).unwrap(), expected); }