From 8259b57a4608acd948d5160af45c567c1f322497 Mon Sep 17 00:00:00 2001 From: Dane Johnson Date: Wed, 13 Nov 2024 11:13:09 -0600 Subject: [PATCH] Change the way blocks are handled, i.e. not expressions but something else --- src/emitter.rs | 17 ++++---------- src/evaluator.rs | 14 ++++++------ src/parser.rs | 58 +++++++++++++++++++++++++----------------------- 3 files changed, 41 insertions(+), 48 deletions(-) diff --git a/src/emitter.rs b/src/emitter.rs index cf7ad2e..6f50b24 100644 --- a/src/emitter.rs +++ b/src/emitter.rs @@ -42,7 +42,7 @@ pub fn emit_all(w: &mut dyn Write, ast: &Vec, ctx: &mut LexicalCon pub fn emit(w: &mut dyn Write, stmt: &parser::Stmt, ctx: &mut LexicalContext) -> std::io::Result<()> { match &stmt { - parser::Stmt::ReplPrint(expr) => { + parser::Stmt::BareExpr(expr) => { write!(w, "console.log((")?; emit_expr(w, expr, ctx)?; writeln!(w, "));")?; @@ -72,13 +72,13 @@ pub fn emit(w: &mut dyn Write, stmt: &parser::Stmt, ctx: &mut LexicalContext) -> emit_expr(w, &if_block.guard, ctx)?; writeln!(w, ") {{")?; let mut block_ctx = LexicalContext::new(ctx); - emit_expr(w, &if_block.block, &mut block_ctx)?; + emit_all(w, &if_block.block, &mut block_ctx)?; writeln!(w, "}}")?; } if let Some(block) = else_block { writeln!(w, "else {{")?; let mut block_ctx = LexicalContext::new(ctx); - emit_expr(w, block, &mut block_ctx)?; + emit_all(w, block, &mut block_ctx)?; writeln!(w, "}}")?; } } @@ -113,18 +113,9 @@ pub fn emit_expr(w: &mut dyn Write, expr: &parser::Expr, ctx: &mut LexicalContex } let mut fun_ctx = LexicalContext::new(ctx); fun_ctx.is_tail = true; - emit_expr(w, body.as_ref(), &mut fun_ctx)?; + emit_all(w, body.as_ref(), &mut fun_ctx)?; write!(w, "}}")?; } - parser::Expr::Block(stmts) => { - let mut peek_iter = stmts.iter().peekable(); - while let Some(stmt) = peek_iter.next() { - if peek_iter.peek().is_none() { - write!(w, "return ")?; - } - emit(w, stmt, ctx)?; - } - } parser::Expr::Plus(e1, e2) => { emit_expr(w, e1.as_ref(), ctx)?; write!(w, " + ")?; diff --git a/src/evaluator.rs b/src/evaluator.rs index f53c306..f11f57a 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -38,7 +38,7 @@ impl<'a> Env<'a> { pub fn eval(ast: &parser::Stmt, env: &mut Env) { match &ast { - parser::Stmt::ReplPrint(expr) => + parser::Stmt::BareExpr(expr) => println!("{}", eval_expr(expr, env)), parser::Stmt::Assignment(id, expr) => env.set(id.clone(), eval_expr(expr, env)), @@ -49,11 +49,9 @@ pub fn eval(ast: &parser::Stmt, env: &mut Env) { match res { Atom::Bool(true) => { matched = true; - if let parser::Expr::Block(block) = block { - for stmt in block { - eval(stmt, env); - } - } + for stmt in block { + eval(stmt, env); + } break; } Atom::Bool(false) => continue, @@ -62,7 +60,9 @@ pub fn eval(ast: &parser::Stmt, env: &mut Env) { } if !matched { if let Some(block) = default_block { - eval_expr(block, env); + for stmt in block { + eval(stmt, env); + } } } } diff --git a/src/parser.rs b/src/parser.rs index a2a21f0..9b914fa 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -4,8 +4,8 @@ use std::fmt; pub enum Stmt { Assignment(String, Expr), Funcall(Expr), - Conditional(Vec, Option), - ReplPrint(Expr), + Conditional(Vec, Option), + BareExpr(Expr), } #[derive(Debug,PartialEq,Clone)] @@ -13,15 +13,16 @@ pub enum Expr { Id(String), Atom(Atom), Funcall(String, Vec), - Funcdef(Option, Box), + Funcdef(Option, Block), UnaryMinus(Box), Plus(Box, Box), Minus(Box, Box), Mult(Box, Box), Div(Box, Box), - Block(Vec), } +pub type Block = Vec; + #[derive(Debug,PartialEq,Clone)] pub enum Atom { String(String), @@ -42,7 +43,7 @@ impl fmt::Display for Atom { #[derive(Debug,PartialEq,Clone)] pub struct GuardedBlock { pub guard: Expr, - pub block: Expr, + pub block: Block, } peg::parser! { @@ -53,7 +54,7 @@ peg::parser! { = a:assignment() { a } / f:funcall() stop() { Stmt::Funcall(f) } / c:conditional() { c } / - e:expr() stop() { Stmt::ReplPrint(e) } + e:expr() stop() { Stmt::BareExpr(e) } rule expr() -> Expr = precedence! { "-" _ e1:@ { Expr::UnaryMinus(Box::new(e1)) } -- @@ -84,7 +85,7 @@ peg::parser! { rule funcall() -> Expr = i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Expr::Funcall(i, e) } rule funcdef() -> Expr - = i:id()? "->" _ e:(expr() / block()) { Expr::Funcdef(i, Box::new(e)) } + = i:id()? "->" _ b:(block()) { Expr::Funcdef(i, b) } rule conditional() -> Stmt = i:_if() __* ei:elif()* __* e:_else()? __* { Stmt::Conditional([vec![i], ei].concat(), e) } rule _if() -> GuardedBlock @@ -101,11 +102,12 @@ peg::parser! { block: b } } - rule _else() -> Expr + rule _else() -> Block = "else" _ b:block() { b } - rule block() -> Expr - = i:indented_block() { Expr::Block(i) } - rule indented_block() -> Vec + rule block() -> Block + = i:indented_block() { i } / + e:expr() { vec![Stmt::BareExpr(e)] } + rule indented_block() -> Block = stop() indent() __* s:stmt()+ dedent() { s } rule letter() @@ -280,36 +282,36 @@ foo <- x -> y -> x * y"; "foo".to_string(), Expr::Funcdef( None, - Box::new(Expr::Funcall("bar".to_string(), vec![])), - ) + vec![Stmt::BareExpr(Expr::Funcall("bar".to_string(), vec![]))], + ), ), Stmt::Assignment( "foo".to_string(), Expr::Funcdef( None, - Box::new(Expr::Block(vec![ + vec![ Stmt::Funcall(Expr::Funcall("bar".to_string(), vec![])), Stmt::Funcall(Expr::Funcall("baz".to_string(), vec![])), - ])) - ) + ], + ) ), Stmt::Assignment( "foo".to_string(), Expr::Funcdef( Some("x".to_string()), - Box::new( - Expr::Funcdef( + vec![ + Stmt::BareExpr(Expr::Funcdef( Some("y".to_string()), - Box::new( - Expr::Mult( + vec![ + Stmt::BareExpr(Expr::Mult( Box::new(Expr::Id("x".to_string())), Box::new(Expr::Id("y".to_string())), - ) - ) - ) - ) + )) + ], + )) + ], ) - ) + ), ]; assert_eq!(deelang_parser::program(prgm).unwrap(), expected); } @@ -328,14 +330,14 @@ else vec![ GuardedBlock { guard: Expr::Id("foo".to_string()), - block: Expr::Block(vec![Stmt::Funcall(Expr::Funcall("bar".to_string(), vec![]))]) + block: vec![Stmt::Funcall(Expr::Funcall("bar".to_string(), vec![]))] }, GuardedBlock { guard: Expr::Id("baz".to_string()), - block: Expr::Block(vec![Stmt::Funcall(Expr::Funcall("foobar".to_string(), vec![]))]) + block: vec![Stmt::Funcall(Expr::Funcall("foobar".to_string(), vec![]))], }, ], - Some(Expr::Block(vec![Stmt::Funcall(Expr::Funcall("quux".to_string(), vec![]))])), + Some(vec![Stmt::Funcall(Expr::Funcall("quux".to_string(), vec![]))]), )]; assert_eq!(deelang_parser::program(prgm).unwrap(), expected); }