From 9291e65c1150d265a5d48cf5e696fab24e16f14b Mon Sep 17 00:00:00 2001 From: Dane Johnson Date: Thu, 14 Nov 2024 13:09:54 -0600 Subject: [PATCH] Use injected js, trampolines for curried functions --- src/emitter.rs | 24 +++++++++++++++++------- src/js/deeinject.js | 10 ++++++++++ src/main.rs | 3 +-- 3 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 src/js/deeinject.js diff --git a/src/emitter.rs b/src/emitter.rs index 2902cdc..5868d1c 100644 --- a/src/emitter.rs +++ b/src/emitter.rs @@ -37,6 +37,13 @@ impl <'a> LexicalContext<'a> { } } +/// Embeds the pre-written js +pub fn emit_injector(w: &mut dyn Write) -> std::io::Result<()>{ + let bytes = include_bytes!("./js/deeinject.js"); + write!(w, "{}", String::from_utf8_lossy(bytes))?; + Ok(()) +} + pub fn emit_all(w: &mut dyn Write, ast: &Vec, ctx: &mut LexicalContext) -> std::io::Result<()> { let is_tail = ctx.is_tail; ctx.is_tail = false; @@ -113,14 +120,17 @@ pub fn emit_expr(w: &mut dyn Write, expr: &parser::Expr, ctx: &mut LexicalContex write!(w, "{}", atom)?; } parser::Expr::Funcall(id, args) => { - write!(w, "{}", munge(id))?; - if args.is_empty() { - write!(w, "()")?; - } - for arg in args { - write!(w, "(")?; - emit_expr(w, arg, ctx)?; + if let Some((last, butlast)) = args.split_last() { + write!(w, "T({}, ", munge(id))?; + for expr in butlast { + emit_expr(w, expr, ctx)?; + write!(w, ", ")?; + } + emit_expr(w, last, ctx)?; write!(w, ")")?; + } else { + write!(w, "{}", munge(id))?; + write!(w, "()")?; } } parser::Expr::Funcdef(arg, body) => { diff --git a/src/js/deeinject.js b/src/js/deeinject.js new file mode 100644 index 0000000..e8fd097 --- /dev/null +++ b/src/js/deeinject.js @@ -0,0 +1,10 @@ +const print = console.log + +function T(f, ...args) { + let res = f; + for (arg of args) { + res = res(arg); + } + return res; +} + diff --git a/src/main.rs b/src/main.rs index 1706de6..96b078e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -53,8 +53,7 @@ fn script(cli: &Cli) { println!("{:#?}", tree); } else if cli.ecmascript { let mut out = io::stdout(); - // TODO remove this hack - writeln!(out, "const print = console.log;").ok(); + emitter::emit_injector(&mut out).ok(); let mut toplevel = emitter::LexicalContext::toplevel(); emitter::emit_all(&mut out, &tree, &mut toplevel).ok(); } else {