Add some display for each, order of operations won't be correct without context

This commit is contained in:
Dane Johnson 2024-11-18 10:16:36 -06:00
parent c9295b5777
commit 08cab74fb5
2 changed files with 87 additions and 26 deletions

View File

@ -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 {

View File

@ -3,7 +3,6 @@ use std::fmt;
#[derive(Debug,PartialEq,Clone)]
pub enum Stmt {
Assignment(String, Expr),
Funcall(Expr),
Conditional(Vec<GuardedBlock>, Option<Block>),
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);
}