Compare commits

...

2 Commits

2 changed files with 100 additions and 27 deletions

View File

@ -78,13 +78,6 @@ pub fn emit(w: &mut dyn Write, stmt: &parser::Stmt, ctx: &mut LexicalContext) ->
writeln!(w, "return;")?; 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) => { parser::Stmt::Conditional(if_blocks, else_block) => {
let mut first_block = true; let mut first_block = true;
for if_block in if_blocks { for if_block in if_blocks {

View File

@ -3,7 +3,6 @@ use std::fmt;
#[derive(Debug,PartialEq,Clone)] #[derive(Debug,PartialEq,Clone)]
pub enum Stmt { pub enum Stmt {
Assignment(String, Expr), Assignment(String, Expr),
Funcall(Expr),
Conditional(Vec<GuardedBlock>, Option<Block>), Conditional(Vec<GuardedBlock>, Option<Block>),
Loop(Loop), Loop(Loop),
BareExpr(Expr), BareExpr(Expr),
@ -34,16 +33,6 @@ pub enum Atom {
Bool(bool), 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)] #[derive(Debug,PartialEq,Clone)]
pub struct GuardedBlock { pub struct GuardedBlock {
pub guard: Expr, pub guard: Expr,
@ -63,7 +52,6 @@ peg::parser! {
= __* s:stmt()* { s } = __* s:stmt()* { s }
pub rule stmt() -> Stmt pub rule stmt() -> Stmt
= a:assignment() { a } / = a:assignment() { a } /
f:funcall() stop() { Stmt::Funcall(f) } /
c:conditional() { c } / c:conditional() { c } /
l:_loop() { Stmt::Loop(l) } / l:_loop() { Stmt::Loop(l) } /
e:expr() stop() { Stmt::BareExpr(e) } e:expr() stop() { Stmt::BareExpr(e) }
@ -215,6 +203,86 @@ pub fn parse_stmt(stmt: &str) -> Stmt {
deelang_parser::stmt(&stmt).unwrap() 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)] #[cfg(test)]
mod test { mod test {
@ -232,8 +300,8 @@ apple <- 1 ## This is too
#[test] #[test]
fn test_funcall() { fn test_funcall() {
let expected = vec![ let expected = vec![
Stmt::Funcall(Expr::Funcall("pear".to_string(), vec![])), Stmt::BareExpr(Expr::Funcall("pear".to_string(), vec![])),
Stmt::Funcall(Expr::Funcall("pear".to_string(), Stmt::BareExpr(Expr::Funcall("pear".to_string(),
vec![Expr::Id("x".to_string()), Expr::Id("y".to_string())], vec![Expr::Id("x".to_string()), Expr::Id("y".to_string())],
)) ))
]; ];
@ -326,8 +394,8 @@ foo <- x -> y -> x * y";
Expr::Funcdef( Expr::Funcdef(
None, None,
vec![ vec![
Stmt::Funcall(Expr::Funcall("bar".to_string(), vec![])), Stmt::BareExpr(Expr::Funcall("bar".to_string(), vec![])),
Stmt::Funcall(Expr::Funcall("baz".to_string(), vec![])), Stmt::BareExpr(Expr::Funcall("baz".to_string(), vec![])),
], ],
) )
), ),
@ -366,18 +434,30 @@ else
vec![ vec![
GuardedBlock { GuardedBlock {
guard: Expr::Id("foo".to_string()), 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 { GuardedBlock {
guard: Expr::Id("baz".to_string()), 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); assert_eq!(deelang_parser::program(prgm).unwrap(), expected);
} }
#[test]
fn test_loop() {
let prgm = r"loop until i > 100 a";
let expected = vec![Stmt::Loop(Loop::Until(GuardedBlock {
guard: Expr::Relop(
">".to_string(),
Box::new(Expr::Id("i".to_string())),
Box::new(Expr::Atom(Atom::Num(100.0))),
),
block: vec![Stmt::BareExpr(Expr::Id("a".to_string()))],
}))];
assert_eq!(deelang_parser::program(prgm).unwrap(), expected);
}
#[test] #[test]
fn test_preprocess() { fn test_preprocess() {
let prgm = r" let prgm = r"