Change the way blocks are handled, i.e. not expressions but something else

This commit is contained in:
Dane Johnson 2024-11-13 11:13:09 -06:00
parent 0524efef03
commit 8259b57a46
3 changed files with 41 additions and 48 deletions

View File

@ -42,7 +42,7 @@ pub fn emit_all(w: &mut dyn Write, ast: &Vec<parser::Stmt>, ctx: &mut LexicalCon
pub fn emit(w: &mut dyn Write, stmt: &parser::Stmt, ctx: &mut LexicalContext) -> std::io::Result<()> { pub fn emit(w: &mut dyn Write, stmt: &parser::Stmt, ctx: &mut LexicalContext) -> std::io::Result<()> {
match &stmt { match &stmt {
parser::Stmt::ReplPrint(expr) => { parser::Stmt::BareExpr(expr) => {
write!(w, "console.log((")?; write!(w, "console.log((")?;
emit_expr(w, expr, ctx)?; emit_expr(w, expr, ctx)?;
writeln!(w, "));")?; 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)?; emit_expr(w, &if_block.guard, ctx)?;
writeln!(w, ") {{")?; writeln!(w, ") {{")?;
let mut block_ctx = LexicalContext::new(ctx); 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, "}}")?; writeln!(w, "}}")?;
} }
if let Some(block) = else_block { if let Some(block) = else_block {
writeln!(w, "else {{")?; writeln!(w, "else {{")?;
let mut block_ctx = LexicalContext::new(ctx); let mut block_ctx = LexicalContext::new(ctx);
emit_expr(w, block, &mut block_ctx)?; emit_all(w, block, &mut block_ctx)?;
writeln!(w, "}}")?; 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); let mut fun_ctx = LexicalContext::new(ctx);
fun_ctx.is_tail = true; 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, "}}")?; 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) => { parser::Expr::Plus(e1, e2) => {
emit_expr(w, e1.as_ref(), ctx)?; emit_expr(w, e1.as_ref(), ctx)?;
write!(w, " + ")?; write!(w, " + ")?;

View File

@ -38,7 +38,7 @@ impl<'a> Env<'a> {
pub fn eval(ast: &parser::Stmt, env: &mut Env) { pub fn eval(ast: &parser::Stmt, env: &mut Env) {
match &ast { match &ast {
parser::Stmt::ReplPrint(expr) => parser::Stmt::BareExpr(expr) =>
println!("{}", eval_expr(expr, env)), println!("{}", eval_expr(expr, env)),
parser::Stmt::Assignment(id, expr) => parser::Stmt::Assignment(id, expr) =>
env.set(id.clone(), eval_expr(expr, env)), env.set(id.clone(), eval_expr(expr, env)),
@ -49,11 +49,9 @@ pub fn eval(ast: &parser::Stmt, env: &mut Env) {
match res { match res {
Atom::Bool(true) => { Atom::Bool(true) => {
matched = true; matched = true;
if let parser::Expr::Block(block) = block { for stmt in block {
for stmt in block { eval(stmt, env);
eval(stmt, env); }
}
}
break; break;
} }
Atom::Bool(false) => continue, Atom::Bool(false) => continue,
@ -62,7 +60,9 @@ pub fn eval(ast: &parser::Stmt, env: &mut Env) {
} }
if !matched { if !matched {
if let Some(block) = default_block { if let Some(block) = default_block {
eval_expr(block, env); for stmt in block {
eval(stmt, env);
}
} }
} }
} }

View File

@ -4,8 +4,8 @@ use std::fmt;
pub enum Stmt { pub enum Stmt {
Assignment(String, Expr), Assignment(String, Expr),
Funcall(Expr), Funcall(Expr),
Conditional(Vec<GuardedBlock>, Option<Expr>), Conditional(Vec<GuardedBlock>, Option<Block>),
ReplPrint(Expr), BareExpr(Expr),
} }
#[derive(Debug,PartialEq,Clone)] #[derive(Debug,PartialEq,Clone)]
@ -13,15 +13,16 @@ pub enum Expr {
Id(String), Id(String),
Atom(Atom), Atom(Atom),
Funcall(String, Vec<Expr>), Funcall(String, Vec<Expr>),
Funcdef(Option<String>, Box<Expr>), Funcdef(Option<String>, Block),
UnaryMinus(Box<Expr>), UnaryMinus(Box<Expr>),
Plus(Box<Expr>, Box<Expr>), Plus(Box<Expr>, Box<Expr>),
Minus(Box<Expr>, Box<Expr>), Minus(Box<Expr>, Box<Expr>),
Mult(Box<Expr>, Box<Expr>), Mult(Box<Expr>, Box<Expr>),
Div(Box<Expr>, Box<Expr>), Div(Box<Expr>, Box<Expr>),
Block(Vec<Stmt>),
} }
pub type Block = Vec<Stmt>;
#[derive(Debug,PartialEq,Clone)] #[derive(Debug,PartialEq,Clone)]
pub enum Atom { pub enum Atom {
String(String), String(String),
@ -42,7 +43,7 @@ impl fmt::Display for Atom {
#[derive(Debug,PartialEq,Clone)] #[derive(Debug,PartialEq,Clone)]
pub struct GuardedBlock { pub struct GuardedBlock {
pub guard: Expr, pub guard: Expr,
pub block: Expr, pub block: Block,
} }
peg::parser! { peg::parser! {
@ -53,7 +54,7 @@ peg::parser! {
= a:assignment() { a } / = a:assignment() { a } /
f:funcall() stop() { Stmt::Funcall(f) } / f:funcall() stop() { Stmt::Funcall(f) } /
c:conditional() { c } / c:conditional() { c } /
e:expr() stop() { Stmt::ReplPrint(e) } e:expr() stop() { Stmt::BareExpr(e) }
rule expr() -> Expr = precedence! { rule expr() -> Expr = precedence! {
"-" _ e1:@ { Expr::UnaryMinus(Box::new(e1)) } "-" _ e1:@ { Expr::UnaryMinus(Box::new(e1)) }
-- --
@ -84,7 +85,7 @@ peg::parser! {
rule funcall() -> Expr rule funcall() -> Expr
= i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Expr::Funcall(i, e) } = i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Expr::Funcall(i, e) }
rule funcdef() -> Expr 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 rule conditional() -> Stmt
= i:_if() __* ei:elif()* __* e:_else()? __* { Stmt::Conditional([vec![i], ei].concat(), e) } = i:_if() __* ei:elif()* __* e:_else()? __* { Stmt::Conditional([vec![i], ei].concat(), e) }
rule _if() -> GuardedBlock rule _if() -> GuardedBlock
@ -101,11 +102,12 @@ peg::parser! {
block: b block: b
} }
} }
rule _else() -> Expr rule _else() -> Block
= "else" _ b:block() { b } = "else" _ b:block() { b }
rule block() -> Expr rule block() -> Block
= i:indented_block() { Expr::Block(i) } = i:indented_block() { i } /
rule indented_block() -> Vec<Stmt> e:expr() { vec![Stmt::BareExpr(e)] }
rule indented_block() -> Block
= stop() indent() __* s:stmt()+ dedent() { s } = stop() indent() __* s:stmt()+ dedent() { s }
rule letter() rule letter()
@ -280,36 +282,36 @@ foo <- x -> y -> x * y";
"foo".to_string(), "foo".to_string(),
Expr::Funcdef( Expr::Funcdef(
None, None,
Box::new(Expr::Funcall("bar".to_string(), vec![])), vec![Stmt::BareExpr(Expr::Funcall("bar".to_string(), vec![]))],
) ),
), ),
Stmt::Assignment( Stmt::Assignment(
"foo".to_string(), "foo".to_string(),
Expr::Funcdef( Expr::Funcdef(
None, None,
Box::new(Expr::Block(vec![ vec![
Stmt::Funcall(Expr::Funcall("bar".to_string(), vec![])), Stmt::Funcall(Expr::Funcall("bar".to_string(), vec![])),
Stmt::Funcall(Expr::Funcall("baz".to_string(), vec![])), Stmt::Funcall(Expr::Funcall("baz".to_string(), vec![])),
])) ],
) )
), ),
Stmt::Assignment( Stmt::Assignment(
"foo".to_string(), "foo".to_string(),
Expr::Funcdef( Expr::Funcdef(
Some("x".to_string()), Some("x".to_string()),
Box::new( vec![
Expr::Funcdef( Stmt::BareExpr(Expr::Funcdef(
Some("y".to_string()), Some("y".to_string()),
Box::new( vec![
Expr::Mult( Stmt::BareExpr(Expr::Mult(
Box::new(Expr::Id("x".to_string())), Box::new(Expr::Id("x".to_string())),
Box::new(Expr::Id("y".to_string())), Box::new(Expr::Id("y".to_string())),
) ))
) ],
) ))
) ],
) )
) ),
]; ];
assert_eq!(deelang_parser::program(prgm).unwrap(), expected); assert_eq!(deelang_parser::program(prgm).unwrap(), expected);
} }
@ -328,14 +330,14 @@ else
vec![ vec![
GuardedBlock { GuardedBlock {
guard: Expr::Id("foo".to_string()), 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 { GuardedBlock {
guard: Expr::Id("baz".to_string()), 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); assert_eq!(deelang_parser::program(prgm).unwrap(), expected);
} }