diff --git a/Cargo.toml b/Cargo.toml index 8a28b5a..cf542a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,3 +19,4 @@ wasm-bindgen-futures = "0.4.50" serde = {version = "1.0", features = ["derive"]} serde_json = "1.0" console_error_panic_hook = "0.1.7" +# talc = "4.4.3" diff --git a/assets/agent.ld b/assets/agent.ld new file mode 100644 index 0000000..4052cc3 --- /dev/null +++ b/assets/agent.ld @@ -0,0 +1,31 @@ +fn agent (val) -> receive { + (:set, new) -> agent (new) + (:get, pid) -> { + send (pid, (:response, val)) + agent (val) + } + (:update, f) -> agent (f (val)) +} + +fn agent/set (pid, val) -> { + send (pid, (:set, val)) + val +} + +fn agent/get (pid) -> { + send (pid, (:get, self ())) + receive { + (:response, val) -> val + } +} + +fn agent/update (pid, f) -> { + send (pid, (:update, f)) + agent/get (pid) +} + +let myagent = spawn! (fn () -> agent (42)) + +print! ("incrementing agent value to", agent/update (myagent, inc)) + +:done! diff --git a/assets/test_prelude.ld b/assets/test_prelude.ld index e59380c..4b8d707 100644 --- a/assets/test_prelude.ld +++ b/assets/test_prelude.ld @@ -416,7 +416,7 @@ fn print! { "Sends a text representation of Ludus values to the console." (...args) -> { let line = do args > map (string, _) > join (_, " ") - base :print! (args) + & base :print! (args) update! (console, append (_, line)) :ok } diff --git a/may_2025_thoughts.md b/may_2025_thoughts.md index 780e809..7a2cf51 100644 --- a/may_2025_thoughts.md +++ b/may_2025_thoughts.md @@ -1175,3 +1175,4 @@ That leaves the following list: * One thing I hadn't quite grokked before is that we need to have a way of running the i/o events. Perhaps the simplest way to do this is to just to do it every so often, regardless of how long the ludus event loop is taking. That way even if things are getting weird in the VM, i/o still happens regularly. * The return to a `slurp` call is interesting. * I think the thing to do is to write to a slurp buffer/box as well. + diff --git a/pkg/ludus.js b/pkg/ludus.js index e964c7d..504895f 100644 --- a/pkg/ludus.js +++ b/pkg/ludus.js @@ -13,18 +13,15 @@ worker.onmessage = async (e) => { throw Error("bad json from Ludus") } for (const msg of msgs) { - console.log("Main: message received from worker:", msg); switch (msg.verb) { case "complete": { - console.log("completed ludus run!") - console.log("with", msg.data) + console.log("ludus completed with => ", msg.data) res = msg.data running = false break } case "console": { - console.log("console msg from msg.data") - console.log(msg.data) + console.log("ludus says => ", msg.data) break } } diff --git a/pkg/rudus.d.ts b/pkg/rudus.d.ts index 12ab49a..48d7cb8 100644 --- a/pkg/rudus.d.ts +++ b/pkg/rudus.d.ts @@ -14,8 +14,8 @@ export interface InitOutput { readonly __wbindgen_malloc: (a: number, b: number) => number; readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; readonly __wbindgen_export_6: WebAssembly.Table; - readonly closure347_externref_shim: (a: number, b: number, c: any) => void; - readonly closure371_externref_shim: (a: number, b: number, c: any, d: any) => void; + readonly closure327_externref_shim: (a: number, b: number, c: any) => void; + readonly closure340_externref_shim: (a: number, b: number, c: any, d: any) => void; readonly __wbindgen_start: () => void; } diff --git a/pkg/rudus.js b/pkg/rudus.js index ccdb85c..dd00cba 100644 --- a/pkg/rudus.js +++ b/pkg/rudus.js @@ -17,22 +17,6 @@ function handleError(f, args) { } } -function logError(f, args) { - try { - return f.apply(this, args); - } catch (e) { - let error = (function () { - try { - return e instanceof Error ? `${e.message}\n\nStack:\n${e.stack}` : e.toString(); - } catch(_) { - return ""; - } - }()); - console.error("wasm-bindgen: imported JS function that was not marked as `catch` threw an error:", error); - throw e; - } -} - const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } ); if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }; @@ -70,8 +54,6 @@ const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' function passStringToWasm0(arg, malloc, realloc) { - if (typeof(arg) !== 'string') throw new Error(`expected a string argument, found ${typeof(arg)}`); - if (realloc === undefined) { const buf = cachedTextEncoder.encode(arg); const ptr = malloc(buf.length, 1) >>> 0; @@ -100,7 +82,7 @@ function passStringToWasm0(arg, malloc, realloc) { ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len); const ret = encodeString(arg, view); - if (ret.read !== arg.length) throw new Error('failed to pass whole string'); + offset += ret.written; ptr = realloc(ptr, len, offset, 1) >>> 0; } @@ -122,12 +104,6 @@ function isLikeNone(x) { return x === undefined || x === null; } -function _assertBoolean(n) { - if (typeof(n) !== 'boolean') { - throw new Error(`expected a boolean argument, found ${typeof(n)}`); - } -} - const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined') ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry(state => { @@ -234,19 +210,12 @@ export function ludus(src) { return ret; } -function _assertNum(n) { - if (typeof(n) !== 'number') throw new Error(`expected a number argument, found ${typeof(n)}`); -} function __wbg_adapter_22(arg0, arg1, arg2) { - _assertNum(arg0); - _assertNum(arg1); - wasm.closure347_externref_shim(arg0, arg1, arg2); + wasm.closure327_externref_shim(arg0, arg1, arg2); } -function __wbg_adapter_50(arg0, arg1, arg2, arg3) { - _assertNum(arg0); - _assertNum(arg1); - wasm.closure371_externref_shim(arg0, arg1, arg2, arg3); +function __wbg_adapter_52(arg0, arg1, arg2, arg3) { + wasm.closure340_externref_shim(arg0, arg1, arg2, arg3); } async function __wbg_load(module, imports) { @@ -291,7 +260,7 @@ function __wbg_get_imports() { const ret = arg0.call(arg1, arg2); return ret; }, arguments) }; - imports.wbg.__wbg_error_7534b8e9a36f1ab4 = function() { return logError(function (arg0, arg1) { + imports.wbg.__wbg_error_7534b8e9a36f1ab4 = function(arg0, arg1) { let deferred0_0; let deferred0_1; try { @@ -301,8 +270,8 @@ function __wbg_get_imports() { } finally { wasm.__wbindgen_free(deferred0_0, deferred0_1, 1); } - }, arguments) }; - imports.wbg.__wbg_io_4b41f8089de924df = function() { return logError(function (arg0, arg1) { + }; + imports.wbg.__wbg_io_4b41f8089de924df = function(arg0, arg1) { let deferred0_0; let deferred0_1; try { @@ -313,8 +282,8 @@ function __wbg_get_imports() { } finally { wasm.__wbindgen_free(deferred0_0, deferred0_1, 1); } - }, arguments) }; - imports.wbg.__wbg_log_86d603e98cc11395 = function() { return logError(function (arg0, arg1) { + }; + imports.wbg.__wbg_log_86d603e98cc11395 = function(arg0, arg1) { let deferred0_0; let deferred0_1; try { @@ -324,18 +293,29 @@ function __wbg_get_imports() { } finally { wasm.__wbindgen_free(deferred0_0, deferred0_1, 1); } - }, arguments) }; - imports.wbg.__wbg_log_9e426f8e841e42d3 = function() { return logError(function (arg0, arg1) { + }; + imports.wbg.__wbg_log_9e426f8e841e42d3 = function(arg0, arg1) { console.log(getStringFromWasm0(arg0, arg1)); - }, arguments) }; - imports.wbg.__wbg_new_23a2665fac83c611 = function() { return logError(function (arg0, arg1) { + }; + imports.wbg.__wbg_log_edeb598b620f1ba2 = function(arg0, arg1) { + let deferred0_0; + let deferred0_1; + try { + deferred0_0 = arg0; + deferred0_1 = arg1; + console.log(getStringFromWasm0(arg0, arg1)); + } finally { + wasm.__wbindgen_free(deferred0_0, deferred0_1, 1); + } + }; + imports.wbg.__wbg_new_23a2665fac83c611 = function(arg0, arg1) { try { var state0 = {a: arg0, b: arg1}; var cb0 = (arg0, arg1) => { const a = state0.a; state0.a = 0; try { - return __wbg_adapter_50(a, state0.b, arg0, arg1); + return __wbg_adapter_52(a, state0.b, arg0, arg1); } finally { state0.a = a; } @@ -345,65 +325,65 @@ function __wbg_get_imports() { } finally { state0.a = state0.b = 0; } - }, arguments) }; - imports.wbg.__wbg_new_8a6f238a6ece86ea = function() { return logError(function () { + }; + imports.wbg.__wbg_new_8a6f238a6ece86ea = function() { const ret = new Error(); return ret; - }, arguments) }; - imports.wbg.__wbg_newnoargs_105ed471475aaf50 = function() { return logError(function (arg0, arg1) { + }; + imports.wbg.__wbg_newnoargs_105ed471475aaf50 = function(arg0, arg1) { const ret = new Function(getStringFromWasm0(arg0, arg1)); return ret; - }, arguments) }; - imports.wbg.__wbg_now_8dddb61fa4928554 = function() { return logError(function () { + }; + imports.wbg.__wbg_now_8dddb61fa4928554 = function() { const ret = Date.now(); return ret; - }, arguments) }; - imports.wbg.__wbg_queueMicrotask_97d92b4fcc8a61c5 = function() { return logError(function (arg0) { + }; + imports.wbg.__wbg_queueMicrotask_97d92b4fcc8a61c5 = function(arg0) { queueMicrotask(arg0); - }, arguments) }; - imports.wbg.__wbg_queueMicrotask_d3219def82552485 = function() { return logError(function (arg0) { + }; + imports.wbg.__wbg_queueMicrotask_d3219def82552485 = function(arg0) { const ret = arg0.queueMicrotask; return ret; - }, arguments) }; - imports.wbg.__wbg_random_57c118f142535bb6 = function() { return logError(function () { + }; + imports.wbg.__wbg_random_57c118f142535bb6 = function() { const ret = Math.random(); return ret; - }, arguments) }; - imports.wbg.__wbg_resolve_4851785c9c5f573d = function() { return logError(function (arg0) { + }; + imports.wbg.__wbg_resolve_4851785c9c5f573d = function(arg0) { const ret = Promise.resolve(arg0); return ret; - }, arguments) }; - imports.wbg.__wbg_stack_0ed75d68575b0f3c = function() { return logError(function (arg0, arg1) { + }; + imports.wbg.__wbg_stack_0ed75d68575b0f3c = function(arg0, arg1) { const ret = arg1.stack; const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); const len1 = WASM_VECTOR_LEN; getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); - }, arguments) }; - imports.wbg.__wbg_static_accessor_GLOBAL_88a902d13a557d07 = function() { return logError(function () { + }; + imports.wbg.__wbg_static_accessor_GLOBAL_88a902d13a557d07 = function() { const ret = typeof global === 'undefined' ? null : global; return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); - }, arguments) }; - imports.wbg.__wbg_static_accessor_GLOBAL_THIS_56578be7e9f832b0 = function() { return logError(function () { + }; + imports.wbg.__wbg_static_accessor_GLOBAL_THIS_56578be7e9f832b0 = function() { const ret = typeof globalThis === 'undefined' ? null : globalThis; return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); - }, arguments) }; - imports.wbg.__wbg_static_accessor_SELF_37c5d418e4bf5819 = function() { return logError(function () { + }; + imports.wbg.__wbg_static_accessor_SELF_37c5d418e4bf5819 = function() { const ret = typeof self === 'undefined' ? null : self; return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); - }, arguments) }; - imports.wbg.__wbg_static_accessor_WINDOW_5de37043a91a9c40 = function() { return logError(function () { + }; + imports.wbg.__wbg_static_accessor_WINDOW_5de37043a91a9c40 = function() { const ret = typeof window === 'undefined' ? null : window; return isLikeNone(ret) ? 0 : addToExternrefTable0(ret); - }, arguments) }; - imports.wbg.__wbg_then_44b73946d2fb3e7d = function() { return logError(function (arg0, arg1) { + }; + imports.wbg.__wbg_then_44b73946d2fb3e7d = function(arg0, arg1) { const ret = arg0.then(arg1); return ret; - }, arguments) }; - imports.wbg.__wbg_then_48b406749878a531 = function() { return logError(function (arg0, arg1, arg2) { + }; + imports.wbg.__wbg_then_48b406749878a531 = function(arg0, arg1, arg2) { const ret = arg0.then(arg1, arg2); return ret; - }, arguments) }; + }; imports.wbg.__wbindgen_cb_drop = function(arg0) { const obj = arg0.original; if (obj.cnt-- == 1) { @@ -411,13 +391,12 @@ function __wbg_get_imports() { return true; } const ret = false; - _assertBoolean(ret); return ret; }; - imports.wbg.__wbindgen_closure_wrapper7663 = function() { return logError(function (arg0, arg1, arg2) { - const ret = makeMutClosure(arg0, arg1, 348, __wbg_adapter_22); + imports.wbg.__wbindgen_closure_wrapper974 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 328, __wbg_adapter_22); return ret; - }, arguments) }; + }; imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { const ret = debugString(arg1); const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); @@ -437,12 +416,10 @@ function __wbg_get_imports() { }; imports.wbg.__wbindgen_is_function = function(arg0) { const ret = typeof(arg0) === 'function'; - _assertBoolean(ret); return ret; }; imports.wbg.__wbindgen_is_undefined = function(arg0) { const ret = arg0 === undefined; - _assertBoolean(ret); return ret; }; imports.wbg.__wbindgen_string_get = function(arg0, arg1) { diff --git a/pkg/rudus_bg.wasm b/pkg/rudus_bg.wasm index 1897f95..ca25a5f 100644 Binary files a/pkg/rudus_bg.wasm and b/pkg/rudus_bg.wasm differ diff --git a/pkg/rudus_bg.wasm.d.ts b/pkg/rudus_bg.wasm.d.ts index 9a87573..e2bf686 100644 --- a/pkg/rudus_bg.wasm.d.ts +++ b/pkg/rudus_bg.wasm.d.ts @@ -9,6 +9,6 @@ export const __wbindgen_free: (a: number, b: number, c: number) => void; export const __wbindgen_malloc: (a: number, b: number) => number; export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; export const __wbindgen_export_6: WebAssembly.Table; -export const closure347_externref_shim: (a: number, b: number, c: any) => void; -export const closure371_externref_shim: (a: number, b: number, c: any, d: any) => void; +export const closure327_externref_shim: (a: number, b: number, c: any) => void; +export const closure340_externref_shim: (a: number, b: number, c: any, d: any) => void; export const __wbindgen_start: () => void; diff --git a/pkg/worker.js b/pkg/worker.js index 3631a53..33812a6 100644 --- a/pkg/worker.js +++ b/pkg/worker.js @@ -1,12 +1,11 @@ import init, {ludus} from "./rudus.js"; -console.log("Worker: starting Ludus VM.") export function io (out) { if (out.length > 0) postMessage(out) return new Promise((resolve, _) => { onmessage = (e) => { - console.log(e.data) + // console.log("Worker: from Ludus:", e.data) resolve(JSON.stringify(e.data)) } }) @@ -17,18 +16,19 @@ let loaded_wasm = false async function run(e) { if (!loaded_wasm) { await init() + console.log("Worker: Ludus has been initialized.") loaded_wasm = true } let msgs = e.data for (const msg of msgs) { if (msg.verb === "run" && typeof msg.data === 'string') { - console.log("running ludus!") + // console.log("running ludus!") onmessage = () => {} - let result = await ludus(msg.data) - console.log(result) + console.log("Worker: Beginning new Ludus run.") + await ludus(msg.data) onmessage = run } else { - console.log("Did not get valid startup message. Instead got:") + console.log("Worker: Did not get valid startup message. Instead got:") console.log(e.data) } } @@ -36,5 +36,4 @@ async function run(e) { onmessage = run -console.log("Worker: Ludus VM is running.") diff --git a/src/base.rs b/src/base.rs index b553a6b..2dcf86c 100644 --- a/src/base.rs +++ b/src/base.rs @@ -242,7 +242,12 @@ pub fn last(ordered: &Value) -> Value { } } -// TODO: fix this: x is a list of all the args passed to Ludus's print! +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_namespace = console)] + fn log(msg: String); +} + pub fn print(x: &Value) -> Value { let Value::List(args) = x else { unreachable!("internal Ludus error") @@ -252,7 +257,8 @@ pub fn print(x: &Value) -> Value { .map(|val| format!("{val}")) .collect::>() .join(" "); - println!("{out}"); + // println!("{out}"); + log(out); Value::Keyword("ok") } diff --git a/src/io.rs b/src/io.rs index 0a36535..6f1e8b0 100644 --- a/src/io.rs +++ b/src/io.rs @@ -118,10 +118,9 @@ pub async fn do_io (msgs: Vec) -> Vec { let outbox = format!("[{}]", msgs.iter().map(|msg| msg.to_json()).collect::>().join(",")); let inbox = io (outbox).await; let inbox = inbox.as_string().expect("response should be a string"); - log(format!("response is: {inbox}")); let inbox: Vec = serde_json::from_str(inbox.as_str()).expect("response from js should be valid"); if !inbox.is_empty() { - log("got messages in ludus!".to_string()); + log("ludus received messages".to_string()); for msg in inbox.iter() { log(format!("{}", msg)); } diff --git a/src/lib.rs b/src/lib.rs index e4e1cea..6cf7881 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,11 +4,16 @@ use wasm_bindgen::prelude::*; use std::rc::Rc; use std::cell::RefCell; + const DEBUG_SCRIPT_COMPILE: bool = false; const DEBUG_SCRIPT_RUN: bool = false; const DEBUG_PRELUDE_COMPILE: bool = false; const DEBUG_PRELUDE_RUN: bool = false; +// #[cfg(target_family = "wasm")] +// #[global_allocator] +// static ALLOCATOR: talc::TalckWasm = unsafe { talc::TalckWasm::new_global() }; + mod io; mod ast; @@ -91,11 +96,9 @@ fn prelude() -> HashMap<&'static str, Value> { compiler.compile(); let chunk = compiler.chunk; - log("compiled prelude"); let stub_zoo = Rc::new(RefCell::new(Zoo::new())); let mut prld_sync = Creature::new(chunk, stub_zoo, DEBUG_PRELUDE_RUN); prld_sync.interpret(); - log("run prelude synchronously"); let prelude = prld_sync.result.unwrap().unwrap(); match prelude { Value::Dict(hashmap) => *hashmap, @@ -111,17 +114,15 @@ extern "C" { #[wasm_bindgen] pub async fn ludus(src: String) -> String { + log("Ludus: starting ludus run."); console_error_panic_hook::set_once(); - log("successfully entered ludus fn in Rust"); let src = src.to_string().leak(); - log(src); let (tokens, lex_errs) = lexer().parse(src).into_output_errors(); if !lex_errs.is_empty() { return format!("{:?}", lex_errs); } let tokens = tokens.unwrap(); - log("successfully tokenized source"); let (parse_result, parse_errors) = parser() .parse(Stream::from_iter(tokens).map((0..src.len()).into(), |(t, s)| (t, s))) @@ -130,14 +131,9 @@ pub async fn ludus(src: String) -> String { return format!("{:?}", parse_errors); } - // ::sigh:: The AST should be 'static - // This simplifies lifetimes, and - // in any event, the AST should live forever let parsed: &'static Spanned = Box::leak(Box::new(parse_result.unwrap())); - log("successfully parsed source"); let prelude = prelude(); - log("successfully loaded prelude"); let postlude = prelude.clone(); // let prelude = imbl::HashMap::new(); @@ -158,12 +154,8 @@ pub async fn ludus(src: String) -> String { prelude.clone(), DEBUG_SCRIPT_COMPILE, ); - // let base = base::make_base(); - // compiler.emit_constant(base); - // compiler.bind("base"); compiler.compile(); - log("successfully compiled source"); if DEBUG_SCRIPT_COMPILE { println!("=== source code ==="); println!("{src}"); @@ -178,15 +170,8 @@ pub async fn ludus(src: String) -> String { let vm_chunk = compiler.chunk; let mut world = World::new(vm_chunk, prelude.clone(), DEBUG_SCRIPT_RUN); - let console = prelude - .get("console") - .expect("prelude must have a console") - .clone(); - log("loaded world and console"); world.run().await; let result = world.result.clone().unwrap(); - log("ran script"); - log(format!("{:?}", result).as_str()); let console = postlude.get("console").unwrap(); let Value::Box(console) = console else { diff --git a/src/world.rs b/src/world.rs index d0c7426..7a6767a 100644 --- a/src/world.rs +++ b/src/world.rs @@ -110,27 +110,20 @@ impl Zoo { } fn random_id(&self) -> String { - log("generating random id"); let rand_idx = (random() * 32.0) as usize; - log("random number!"); let idx = self.procs.len(); - log("procs len"); format!("{}_{idx}", ANIMALS[rand_idx]) } fn new_id(&self) -> &'static str { - log("creating new id"); let mut new = self.random_id(); - log("got new ramdom id"); while self.dead.iter().any(|old| *old == new) { new = self.random_id(); } - log(format!("got new id: {}", new).as_str()); new.leak() } pub fn put(&mut self, mut proc: Creature) -> &'static str { - log("putting creature"); if self.empty.is_empty() { let id = self.new_id(); let idx = self.procs.len(); @@ -236,14 +229,14 @@ impl Zoo { } pub fn next(&mut self) -> &'static str { + self.clean_up(); + let starting_idx = self.active_idx; self.active_idx = (self.active_idx + 1) % self.procs.len(); while !self.is_available() { - self.clean_up(); + if self.active_idx == starting_idx { + return "" + } self.active_idx = (self.active_idx + 1) % self.procs.len(); - println!( - "testing process availability: {}", - self.procs[self.active_idx] - ); } match &self.procs[self.active_idx] { Status::Empty | Status::Borrowed => unreachable!(), @@ -331,9 +324,15 @@ impl World { fn next(&mut self) { let mut active = None; swap(&mut active, &mut self.active); - let mut zoo = self.zoo.as_ref().borrow_mut(); - zoo.release(active.unwrap()); + let mut zoo = self.zoo.borrow_mut(); + if let Some(active) = active { + zoo.release(active); + } let new_active_id = zoo.next(); + if new_active_id.is_empty() { + self.active = None; + return; + } let mut new_active_proc = zoo.catch(new_active_id); new_active_proc.reset_reductions(); let mut new_active_opt = Some(new_active_proc); @@ -345,16 +344,21 @@ impl World { self.active = Some(main); } - fn active_id(&mut self) -> &'static str { - self.active.as_ref().unwrap().pid + fn active_id(&mut self) -> Option<&'static str> { + match &self.active { + Some(creature) => Some(creature.pid), + None => None, + } } fn kill_active(&mut self) { - let id = self.active_id(); - self.zoo.as_ref().borrow_mut().kill(id); + if let Some(pid) = self.active_id() { + self.zoo.borrow_mut().kill(pid); + } } fn active_result(&mut self) -> &Option> { + if self.active.is_none() { return &None; } &self.active.as_ref().unwrap().result } @@ -389,12 +393,12 @@ impl World { } async fn maybe_do_io(&mut self) { - if self.last_io + 10.0 > now () { + if self.last_io + 10.0 < now() { let outbox = self.flush_buffers(); let inbox = do_io(outbox).await; self.fill_buffers(inbox); + self.last_io = now(); } - self.last_io = now(); } fn fill_input(&mut self, str: String) { @@ -417,14 +421,17 @@ impl World { pub async fn run(&mut self) { self.activate_main(); loop { + self.maybe_do_io().await; if self.kill_signal { let outbox = self.flush_buffers(); do_io(outbox).await; return; } - self.interpret_active(); + if self.active.is_some() { + self.interpret_active(); + } if self.active_result().is_some() { - if self.active_id() == self.main { + if self.active_id().unwrap() == self.main { let outbox = self.complete_main(); do_io(outbox).await; return; @@ -432,7 +439,6 @@ impl World { self.kill_active(); } self.next(); - self.maybe_do_io().await; } } }