feat: auto-invoke let main in JS backend

The JS backend now detects `let main = fn() => ...` patterns and
auto-invokes them at the end of the generated code, matching the
interpreter's behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-20 20:24:47 -05:00
parent 64f33e4e4b
commit e46afd98eb
2 changed files with 39 additions and 0 deletions

View File

@@ -187,6 +187,20 @@ impl JsBackend {
}
}
// Check for `let main = fn() => ...` pattern (not tracked in self.functions)
let has_let_main = program.declarations.iter().any(|d| {
if let Declaration::Let(l) = d {
l.name.name == "main" && matches!(&l.value, Expr::Lambda { .. })
} else {
false
}
});
if has_let_main && !self.functions.contains("main") && !has_main_call {
self.writeln("");
self.writeln("// Entry point (let main)");
self.writeln("main();");
}
Ok(self.output.clone())
}

View File

@@ -4286,6 +4286,31 @@ c")"#;
assert!(js.contains("Lux.None"), "JS should contain Lux.None for List.get: {}", js);
}
#[test]
fn test_let_main_js_codegen() {
use crate::codegen::js_backend::JsBackend;
use crate::parser::Parser;
use crate::lexer::Lexer;
let source = r#"
let main = fn() => {
print("hello from let main")
}
"#;
let tokens = Lexer::new(source).tokenize().unwrap();
let program = Parser::new(tokens).parse_program().unwrap();
let mut backend = JsBackend::new();
let js = backend.generate(&program).unwrap();
// Should contain the let binding
assert!(js.contains("const main"), "JS should contain 'const main': {}", js);
// Should auto-invoke main()
assert!(js.contains("main();"), "JS should auto-invoke main(): {}", js);
// Should NOT contain main_lux (let bindings aren't mangled)
assert!(!js.contains("main_lux"), "let main should not be mangled: {}", js);
}
#[test]
fn test_invalid_escape_sequence() {
let result = eval(r#"let x = "\z""#);