diff --git a/demo/real.dee b/demo/real.dee index 491fb7c..d40875a 100644 --- a/demo/real.dee +++ b/demo/real.dee @@ -1,9 +1,10 @@ ## Obligatory -fizzbuzz <- x -> - if x % 15 = 0 print("fizzbuzz") - elif x % 3 = 0 print("fizz") - elif x % 5 = 0 print("buzz") - else print(x) - if x < 100 fizzbuzz(x + 1) ## TODO add looping construct(s) - -fizzbuzz(1) +fizzbuzz <- -> + loop(range(100), x -> + if x % 15 = 0 print("fizzbuzz") + elif x % 3 = 0 print("fizz") + elif x % 5 = 0 print("buzz") + else print(x) + ) + +fizzbuzz() diff --git a/src/emitter.rs b/src/emitter.rs index 5868d1c..a00dc7c 100644 --- a/src/emitter.rs +++ b/src/emitter.rs @@ -120,18 +120,28 @@ pub fn emit_expr(w: &mut dyn Write, expr: &parser::Expr, ctx: &mut LexicalContex write!(w, "{}", atom)?; } parser::Expr::Funcall(id, args) => { - if let Some((last, butlast)) = args.split_last() { - write!(w, "T({}, ", munge(id))?; - for expr in butlast { - emit_expr(w, expr, ctx)?; - write!(w, ", ")?; + write!(w, "{}", munge(id))?; + if args.is_empty() { + write!(w, "()")?; + } else if ctx.contains(id) { + // 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)?; write!(w, ")")?; - } else { - write!(w, "{}", munge(id))?; - write!(w, "()")?; } + } parser::Expr::Funcdef(arg, body) => { 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, " == ")?; 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)?; - write!(w, " < ")?; + write!(w, " {} ", op)?; emit_expr(w, e2.as_ref(), ctx)?; } _ => todo!(), diff --git a/src/js/deeinject.js b/src/js/deeinject.js index e8fd097..824c909 100644 --- a/src/js/deeinject.js +++ b/src/js/deeinject.js @@ -1,10 +1,16 @@ const print = console.log -function T(f, ...args) { - let res = f; - for (arg of args) { - res = res(arg); +function loop(seq, f) { + for (el of seq) { + f(el) } - return res; +} + +function range(x) { + const ret = [] + for (let i = 0; i < x; i++) { + ret.push(i); + } + return ret } diff --git a/src/parser.rs b/src/parser.rs index 063bd77..be6daa2 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -21,7 +21,7 @@ pub enum Expr { Div(Box, Box), Mod(Box, Box), Equal(Box, Box), - Lt(Box, Box), + Relop(String, Box, Box), } pub type Block = Vec; @@ -60,8 +60,9 @@ peg::parser! { e:expr() stop() { Stmt::BareExpr(e) } rule expr() -> Expr = precedence! { 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:(@) "+" _ e2:@ { Expr::Plus(Box::new(e1), Box::new(e2)) } @@ -87,10 +88,12 @@ peg::parser! { = i:$(letter() (letter() / digit() / ['?'|'.'|'-'])*) _ { i.to_string() } rule assignment() -> Stmt = i:id() "<-" _ e:expr() stop() { Stmt::Assignment(i, e) } + rule relop() -> String + = r:$("<" / ">" / "<=" / ">=") _ { r.to_string() } rule num() -> f64 = n:$(digit()+ "."? digit()* / "." digit()+) _ { n.parse().unwrap() } rule funcall() -> Expr - = i:id() "(" _ e:(expr() ** ("," _)) ")" _ { Expr::Funcall(i, e) } + = i:id() "(" _ e:(expr() ** ("," _)) __* ")" _ { Expr::Funcall(i, e) } rule funcdef() -> Expr = i:id()? "->" _ b:(block()) { Expr::Funcdef(i, b) } rule conditional() -> Stmt