Change the way blocks are handled, i.e. not expressions but something else
This commit is contained in:
parent
0524efef03
commit
8259b57a46
@ -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, " + ")?;
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user