diff --git a/src/codegen/js_backend.rs b/src/codegen/js_backend.rs index b919b07..84523ba 100644 --- a/src/codegen/js_backend.rs +++ b/src/codegen/js_backend.rs @@ -909,13 +909,16 @@ impl JsBackend { let val = self.emit_expr(&let_decl.value)?; let var_name = &let_decl.name.name; - // Check if this is a run expression (often results in undefined) - // We still want to execute it for its side effects - self.writeln(&format!("const {} = {};", var_name, val)); + if var_name == "_" { + // Wildcard binding: just execute for side effects + self.writeln(&format!("{};", val)); + } else { + self.writeln(&format!("const {} = {};", var_name, val)); - // Register the variable for future use - self.var_substitutions - .insert(var_name.clone(), var_name.clone()); + // Register the variable for future use + self.var_substitutions + .insert(var_name.clone(), var_name.clone()); + } Ok(()) } @@ -1040,18 +1043,26 @@ impl JsBackend { name, value, body, .. } => { let val = self.emit_expr(value)?; - let var_name = format!("{}_{}", name.name, self.fresh_name()); - self.writeln(&format!("const {} = {};", var_name, val)); + if name.name == "_" { + // Wildcard binding: just execute for side effects + self.writeln(&format!("{};", val)); + } else { + let var_name = format!("{}_{}", name.name, self.fresh_name()); - // Add substitution - self.var_substitutions - .insert(name.name.clone(), var_name.clone()); + self.writeln(&format!("const {} = {};", var_name, val)); + + // Add substitution + self.var_substitutions + .insert(name.name.clone(), var_name.clone()); + } let body_result = self.emit_expr(body)?; // Remove substitution - self.var_substitutions.remove(&name.name); + if name.name != "_" { + self.var_substitutions.remove(&name.name); + } Ok(body_result) } @@ -1238,10 +1249,15 @@ impl JsBackend { } Statement::Let { name, value, .. } => { let val = self.emit_expr(value)?; - let var_name = format!("{}_{}", name.name, self.fresh_name()); - self.writeln(&format!("const {} = {};", var_name, val)); - self.var_substitutions - .insert(name.name.clone(), var_name.clone()); + if name.name == "_" { + self.writeln(&format!("{};", val)); + } else { + let var_name = + format!("{}_{}", name.name, self.fresh_name()); + self.writeln(&format!("const {} = {};", var_name, val)); + self.var_substitutions + .insert(name.name.clone(), var_name.clone()); + } } } } @@ -1250,15 +1266,19 @@ impl JsBackend { self.emit_expr(result) } - Expr::Record { fields, .. } => { - let field_strs: Result, _> = fields - .iter() - .map(|(name, expr)| { - let val = self.emit_expr(expr)?; - Ok(format!("{}: {}", name.name, val)) - }) - .collect(); - Ok(format!("{{ {} }}", field_strs?.join(", "))) + Expr::Record { + spread, fields, .. + } => { + let mut parts = Vec::new(); + if let Some(spread_expr) = spread { + let spread_code = self.emit_expr(spread_expr)?; + parts.push(format!("...{}", spread_code)); + } + for (name, expr) in fields { + let val = self.emit_expr(expr)?; + parts.push(format!("{}: {}", name.name, val)); + } + Ok(format!("{{ {} }}", parts.join(", "))) } Expr::Tuple { elements, .. } => { diff --git a/src/main.rs b/src/main.rs index 2ed00bf..798e337 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,7 +37,7 @@ use std::borrow::Cow; use std::collections::HashSet; use typechecker::TypeChecker; -const VERSION: &str = "0.1.0"; +const VERSION: &str = env!("CARGO_PKG_VERSION"); const HELP: &str = r#" Lux - A functional language with first-class effects @@ -902,6 +902,7 @@ fn compile_to_c(path: &str, output_path: Option<&str>, run_after: bool, emit_c: .args(["-O2", "-o"]) .arg(&output_bin) .arg(&temp_c) + .arg("-lm") .output(); match compile_result {