Slightly change call semantics, add looping construct, inline some JS

This commit is contained in:
Dane Johnson 2024-11-14 15:32:46 -06:00
parent 9291e65c11
commit 74f1fdc5ea
4 changed files with 47 additions and 27 deletions

View File

@ -1,9 +1,10 @@
## Obligatory ## Obligatory
fizzbuzz <- x -> fizzbuzz <- ->
loop(range(100), x ->
if x % 15 = 0 print("fizzbuzz") if x % 15 = 0 print("fizzbuzz")
elif x % 3 = 0 print("fizz") elif x % 3 = 0 print("fizz")
elif x % 5 = 0 print("buzz") elif x % 5 = 0 print("buzz")
else print(x) else print(x)
if x < 100 fizzbuzz(x + 1) ## TODO add looping construct(s) )
fizzbuzz(1) fizzbuzz()

View File

@ -120,18 +120,28 @@ pub fn emit_expr(w: &mut dyn Write, expr: &parser::Expr, ctx: &mut LexicalContex
write!(w, "{}", atom)?; write!(w, "{}", atom)?;
} }
parser::Expr::Funcall(id, args) => { parser::Expr::Funcall(id, args) => {
if let Some((last, butlast)) = args.split_last() { write!(w, "{}", munge(id))?;
write!(w, "T({}, ", munge(id))?; if args.is_empty() {
for expr in butlast { write!(w, "()")?;
emit_expr(w, expr, ctx)?; } else if ctx.contains(id) {
write!(w, ", ")?; // Use deelang calling semantics
for arg in args {
write!(w, "(")?;
emit_expr(w, arg, ctx)?;
write!(w, ")")?
}
} else {
// Use JS calling semantics
write!(w, "(")?;
let (last, butlast) = args.split_last().unwrap();
for arg in butlast {
emit_expr(w, arg, ctx)?;
write!(w, ",")?
} }
emit_expr(w, last, ctx)?; emit_expr(w, last, ctx)?;
write!(w, ")")?; write!(w, ")")?;
} else {
write!(w, "{}", munge(id))?;
write!(w, "()")?;
} }
} }
parser::Expr::Funcdef(arg, body) => { parser::Expr::Funcdef(arg, body) => {
if let Some(arg) = arg { if let Some(arg) = arg {
@ -174,9 +184,9 @@ pub fn emit_expr(w: &mut dyn Write, expr: &parser::Expr, ctx: &mut LexicalContex
write!(w, " == ")?; write!(w, " == ")?;
emit_expr(w, e2.as_ref(), ctx)?; emit_expr(w, e2.as_ref(), ctx)?;
} }
parser::Expr::Lt(e1, e2) => { parser::Expr::Relop(op, e1, e2) => {
emit_expr(w, e1.as_ref(), ctx)?; emit_expr(w, e1.as_ref(), ctx)?;
write!(w, " < ")?; write!(w, " {} ", op)?;
emit_expr(w, e2.as_ref(), ctx)?; emit_expr(w, e2.as_ref(), ctx)?;
} }
_ => todo!(), _ => todo!(),

View File

@ -1,10 +1,16 @@
const print = console.log const print = console.log
function T(f, ...args) { function loop(seq, f) {
let res = f; for (el of seq) {
for (arg of args) { f(el)
res = res(arg);
} }
return res; }
function range(x) {
const ret = []
for (let i = 0; i < x; i++) {
ret.push(i);
}
return ret
} }

View File

@ -21,7 +21,7 @@ pub enum Expr {
Div(Box<Expr>, Box<Expr>), Div(Box<Expr>, Box<Expr>),
Mod(Box<Expr>, Box<Expr>), Mod(Box<Expr>, Box<Expr>),
Equal(Box<Expr>, Box<Expr>), Equal(Box<Expr>, Box<Expr>),
Lt(Box<Expr>, Box<Expr>), Relop(String, Box<Expr>, Box<Expr>),
} }
pub type Block = Vec<Stmt>; pub type Block = Vec<Stmt>;
@ -60,7 +60,8 @@ peg::parser! {
e:expr() stop() { Stmt::BareExpr(e) } e:expr() stop() { Stmt::BareExpr(e) }
rule expr() -> Expr = precedence! { rule expr() -> Expr = precedence! {
e1:(@) "=" _ e2:@ { Expr::Equal(Box::new(e1), Box::new(e2)) } e1:(@) "=" _ e2:@ { Expr::Equal(Box::new(e1), Box::new(e2)) }
e1:(@) "<" _ e2:@ { Expr::Lt(Box::new(e1), Box::new(e2)) } --
e1:(@) r:relop() e2:@ { Expr::Relop(r, Box::new(e1), Box::new(e2)) }
-- --
"-" _ e1:@ { Expr::UnaryMinus(Box::new(e1)) } "-" _ e1:@ { Expr::UnaryMinus(Box::new(e1)) }
-- --
@ -87,10 +88,12 @@ peg::parser! {
= i:$(letter() (letter() / digit() / ['?'|'.'|'-'])*) _ { i.to_string() } = i:$(letter() (letter() / digit() / ['?'|'.'|'-'])*) _ { i.to_string() }
rule assignment() -> Stmt rule assignment() -> Stmt
= i:id() "<-" _ e:expr() stop() { Stmt::Assignment(i, e) } = i:id() "<-" _ e:expr() stop() { Stmt::Assignment(i, e) }
rule relop() -> String
= r:$("<" / ">" / "<=" / ">=") _ { r.to_string() }
rule num() -> f64 rule num() -> f64
= n:$(digit()+ "."? digit()* / "." digit()+) _ { n.parse().unwrap() } = n:$(digit()+ "."? digit()* / "." digit()+) _ { n.parse().unwrap() }
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()? "->" _ b:(block()) { Expr::Funcdef(i, b) } = i:id()? "->" _ b:(block()) { Expr::Funcdef(i, b) }
rule conditional() -> Stmt rule conditional() -> Stmt