From f546ed47df76cd2fe5fdd032ac067653852db420 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Tue, 28 Apr 2026 14:00:44 -0500 Subject: [PATCH] Add getpid, exec_bg, spawn_thread, sleep_secs builtins; fix fs_write arity --- bin/el/src/main.rs | 55 ++++++++++++++++++++++++++++++++++++ crates/el-types/src/types.rs | 10 ++++++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/bin/el/src/main.rs b/bin/el/src/main.rs index 22432a8..240d969 100644 --- a/bin/el/src/main.rs +++ b/bin/el/src/main.rs @@ -2411,6 +2411,61 @@ fn dispatch_builtin( BuiltinResult::Handled } + // ── Process / thread builtins ───────────────────────────────────────── + + "getpid" => { + stack.push(Value::Int(std::process::id() as i64)); + BuiltinResult::Handled + } + + "exec_bg" => { + let cmd_str = match stack.pop().unwrap_or(Value::Nil) { + Value::Str(s) => s, + _ => { stack.push(Value::Int(-1)); return BuiltinResult::Handled; } + }; + let mut parts = cmd_str.split_whitespace(); + let prog = match parts.next() { + Some(p) => p.to_string(), + None => { stack.push(Value::Int(-1)); return BuiltinResult::Handled; } + }; + let args_vec: Vec = parts.map(|s| s.to_string()).collect(); + let pid = std::process::Command::new(&prog) + .args(&args_vec) + .spawn() + .map(|child| child.id() as i64) + .unwrap_or(-1); + stack.push(Value::Int(pid)); + BuiltinResult::Handled + } + + "spawn_thread" => { + let fn_name = match stack.pop().unwrap_or(Value::Nil) { + Value::Str(s) => s, + _ => { stack.push(Value::Nil); return BuiltinResult::Handled; } + }; + let instr_arc = SERVE_INSTRUCTIONS.with(|si| si.borrow().clone()); + let fn_arc = SERVE_FN_TABLE.with(|sf| sf.borrow().clone()); + if let (Some(instr_arc), Some(fn_arc)) = (instr_arc, fn_arc) { + std::thread::spawn(move || { + if let Some(&entry) = fn_arc.get(&fn_name) { + run_sub_interpreter(&instr_arc, &fn_arc, entry); + } + }); + } + stack.push(Value::Nil); + BuiltinResult::Handled + } + + "sleep_secs" => { + let n = match stack.pop().unwrap_or(Value::Nil) { + Value::Int(n) => n as u64, + _ => 1, + }; + std::thread::sleep(std::time::Duration::from_secs(n)); + stack.push(Value::Nil); + BuiltinResult::Handled + } + // ── String utility builtins ─────────────────────────────────────────── "str_replace" => { diff --git a/crates/el-types/src/types.rs b/crates/el-types/src/types.rs index 69bef62..be19342 100644 --- a/crates/el-types/src/types.rs +++ b/crates/el-types/src/types.rs @@ -192,9 +192,13 @@ impl TypeEnv { for name in &["fs_read"] { env.functions.insert(name.to_string(), str_fn(vec![s.clone()], s.clone())); } - for name in &["fs_write","fs_append","fs_exists","fs_mkdir","fs_remove","fs_is_dir"] { + for name in &["fs_exists","fs_mkdir","fs_remove","fs_is_dir"] { env.functions.insert(name.to_string(), str_fn(vec![u.clone()], b.clone())); } + // fs_write and fs_append take (path, content) — two arguments + for name in &["fs_write","fs_append"] { + env.functions.insert(name.to_string(), str_fn(vec![s.clone(), s.clone()], b.clone())); + } env.functions.insert("fs_list".into(), str_fn(vec![s.clone()], Type::Unknown)); env.functions.insert("fs_list_recursive".into(), str_fn(vec![s.clone()], Type::Unknown)); env.functions.insert("path_join".into(), str_fn(vec![s.clone(), s.clone()], s.clone())); @@ -234,8 +238,12 @@ impl TypeEnv { env.functions.insert("args".into(), str_fn(vec![], Type::Unknown)); env.functions.insert("exit".into(), str_fn(vec![i.clone()], Type::Void)); env.functions.insert("sleep_ms".into(), str_fn(vec![i.clone()], Type::Void)); + env.functions.insert("sleep_secs".into(), str_fn(vec![i.clone()], Type::Void)); env.functions.insert("timestamp".into(), str_fn(vec![], s.clone())); env.functions.insert("readline".into(), str_fn(vec![s.clone()], s.clone())); + env.functions.insert("getpid".into(), str_fn(vec![], i.clone())); + env.functions.insert("exec_bg".into(), str_fn(vec![s.clone()], i.clone())); + env.functions.insert("spawn_thread".into(), str_fn(vec![s.clone()], Type::Void)); // ANSI color builtins for name in &["color_cyan","color_green","color_red","color_yellow","color_bold","color_dim"] {