WIP to think about tail calls etc
This commit is contained in:
parent
201d7d2594
commit
d4d4756002
@ -5,14 +5,16 @@ use crate::parser;
|
|||||||
|
|
||||||
pub struct LexicalContext<'a> {
|
pub struct LexicalContext<'a> {
|
||||||
parent: Option<&'a LexicalContext<'a>>,
|
parent: Option<&'a LexicalContext<'a>>,
|
||||||
local: HashSet<String>
|
local: HashSet<String>,
|
||||||
|
is_tail: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a> LexicalContext<'a> {
|
impl <'a> LexicalContext<'a> {
|
||||||
pub fn toplevel() -> Self {
|
pub fn toplevel() -> Self {
|
||||||
LexicalContext {
|
LexicalContext {
|
||||||
parent: None,
|
parent: None,
|
||||||
local: HashSet::new()
|
local: HashSet::new(),
|
||||||
|
is_tail: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -20,6 +22,7 @@ impl <'a> LexicalContext<'a> {
|
|||||||
LexicalContext {
|
LexicalContext {
|
||||||
parent: Some(parent),
|
parent: Some(parent),
|
||||||
local: HashSet::new(),
|
local: HashSet::new(),
|
||||||
|
is_tail: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn contains(&self, s: &str) -> bool {
|
fn contains(&self, s: &str) -> bool {
|
||||||
@ -53,7 +56,32 @@ pub fn emit(w: &mut dyn Write, stmt: &parser::Stmt, ctx: &mut LexicalContext) ->
|
|||||||
emit_expr(w, expr, ctx)?;
|
emit_expr(w, expr, ctx)?;
|
||||||
writeln!(w, ";")?;
|
writeln!(w, ";")?;
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
parser::Stmt::Funcall(call) => {
|
||||||
|
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 {
|
||||||
|
if first_block {
|
||||||
|
write!(w, "if (")?;
|
||||||
|
} else {
|
||||||
|
write!(w, " else if(")?;
|
||||||
|
}
|
||||||
|
first_block = false;
|
||||||
|
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)?;
|
||||||
|
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)?;
|
||||||
|
writeln!(w, "}}")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -66,6 +94,42 @@ pub fn emit_expr(w: &mut dyn Write, expr: &parser::Expr, ctx: &mut LexicalContex
|
|||||||
parser::Expr::Atom(atom) => {
|
parser::Expr::Atom(atom) => {
|
||||||
write!(w, "{}", atom)?;
|
write!(w, "{}", atom)?;
|
||||||
}
|
}
|
||||||
|
parser::Expr::Funcall(id, args) => {
|
||||||
|
write!(w, "{}", id)?;
|
||||||
|
if args.is_empty() {
|
||||||
|
write!(w, "()")?;
|
||||||
|
}
|
||||||
|
for arg in args {
|
||||||
|
write!(w, "(")?;
|
||||||
|
emit_expr(w, arg, ctx)?;
|
||||||
|
write!(w, ")")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parser::Expr::Funcdef(arg, body) => {
|
||||||
|
if let Some(arg) = arg {
|
||||||
|
writeln!(w, "function ({}){{", arg)?;
|
||||||
|
} else {
|
||||||
|
writeln!(w, "function (){{")?;
|
||||||
|
}
|
||||||
|
let mut fun_ctx = LexicalContext::new(ctx);
|
||||||
|
fun_ctx.is_tail = true;
|
||||||
|
emit_expr(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, " + ")?;
|
||||||
|
emit_expr(w, e2.as_ref(), ctx)?;
|
||||||
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -49,9 +49,11 @@ 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,
|
||||||
|
@ -43,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: Vec<Stmt>,
|
pub block: Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
peg::parser! {
|
peg::parser! {
|
||||||
@ -93,14 +93,14 @@ peg::parser! {
|
|||||||
= "{" _ stop() indent() __* a:assignment()+ dedent() __* "}" _ { Expr::Object(a) }
|
= "{" _ stop() indent() __* a:assignment()+ dedent() __* "}" _ { Expr::Object(a) }
|
||||||
|
|
||||||
rule _if() -> GuardedBlock
|
rule _if() -> GuardedBlock
|
||||||
= "if" _ g:expr() b:indented_block() {
|
= "if" _ g:expr() b:block() {
|
||||||
GuardedBlock {
|
GuardedBlock {
|
||||||
guard: g,
|
guard: g,
|
||||||
block: b,
|
block: b,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rule elif() -> GuardedBlock
|
rule elif() -> GuardedBlock
|
||||||
= "elif" _ g:expr() b:indented_block() {
|
= "elif" _ g:expr() b:block() {
|
||||||
GuardedBlock {
|
GuardedBlock {
|
||||||
guard: g,
|
guard: g,
|
||||||
block: b
|
block: b
|
||||||
@ -333,11 +333,11 @@ 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: Expr::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: vec![Stmt::Funcall(Expr::Funcall("foobar".to_string(), vec![]))]
|
block: Expr::Block(vec![Stmt::Funcall(Expr::Funcall("foobar".to_string(), vec![]))])
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
Some(Expr::Block(vec![Stmt::Funcall(Expr::Funcall("quux".to_string(), vec![]))])),
|
Some(Expr::Block(vec![Stmt::Funcall(Expr::Funcall("quux".to_string(), vec![]))])),
|
||||||
|
Loading…
Reference in New Issue
Block a user