feat: add extern fn declarations for JS FFI
Adds `extern fn` syntax for declaring external JavaScript functions: extern fn getElementById(id: String): Element extern fn getContext(el: Element, kind: String): CanvasCtx = "getContext" pub extern fn alert(msg: String): Unit Changes across 11 files: - Lexer: `extern` keyword - AST: `ExternFnDecl` struct + `Declaration::ExternFn` variant - Parser: parse `extern fn` with optional `= "jsName"` override - Typechecker: register extern fn type signatures - Interpreter: ExternFn value with clear error on call - JS backend: emit extern fn calls using JS name (no _lux suffix) - C backend: silently skips extern fns - Formatter, linter, modules, symbol_table: handle new variant Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -71,6 +71,8 @@ pub struct JsBackend {
|
||||
var_substitutions: HashMap<String, String>,
|
||||
/// Effects actually used in the program (for tree-shaking runtime)
|
||||
used_effects: HashSet<String>,
|
||||
/// Extern function names mapped to their JS names
|
||||
extern_fns: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl JsBackend {
|
||||
@@ -93,6 +95,7 @@ impl JsBackend {
|
||||
has_handlers: false,
|
||||
var_substitutions: HashMap::new(),
|
||||
used_effects: HashSet::new(),
|
||||
extern_fns: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +115,14 @@ impl JsBackend {
|
||||
Declaration::Type(t) => {
|
||||
self.collect_type(t)?;
|
||||
}
|
||||
Declaration::ExternFn(ext) => {
|
||||
let js_name = ext
|
||||
.js_name
|
||||
.clone()
|
||||
.unwrap_or_else(|| ext.name.name.clone());
|
||||
self.extern_fns.insert(ext.name.name.clone(), js_name);
|
||||
self.functions.insert(ext.name.name.clone());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -2723,6 +2734,10 @@ impl JsBackend {
|
||||
|
||||
/// Mangle a Lux name to a valid JavaScript name
|
||||
fn mangle_name(&self, name: &str) -> String {
|
||||
// Extern functions use their JS name directly (no mangling)
|
||||
if let Some(js_name) = self.extern_fns.get(name) {
|
||||
return js_name.clone();
|
||||
}
|
||||
format!("{}_lux", name)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user