hook the things up and discover a possible stop-the-world bug
This commit is contained in:
parent
4eceb62ce5
commit
2f3f362f49
|
@ -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"
|
||||
|
|
31
assets/agent.ld
Normal file
31
assets/agent.ld
Normal file
|
@ -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!
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
4
pkg/rudus.d.ts
vendored
4
pkg/rudus.d.ts
vendored
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
137
pkg/rudus.js
137
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 "<failed to stringify thrown value>";
|
||||
}
|
||||
}());
|
||||
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) {
|
||||
|
|
Binary file not shown.
4
pkg/rudus_bg.wasm.d.ts
vendored
4
pkg/rudus_bg.wasm.d.ts
vendored
|
@ -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;
|
||||
|
|
|
@ -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.")
|
||||
|
||||
|
|
10
src/base.rs
10
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::<Vec<_>>()
|
||||
.join(" ");
|
||||
println!("{out}");
|
||||
// println!("{out}");
|
||||
log(out);
|
||||
Value::Keyword("ok")
|
||||
}
|
||||
|
||||
|
|
|
@ -118,10 +118,9 @@ pub async fn do_io (msgs: Vec<MsgOut>) -> Vec<MsgIn> {
|
|||
let outbox = format!("[{}]", msgs.iter().map(|msg| msg.to_json()).collect::<Vec<_>>().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<MsgIn> = 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));
|
||||
}
|
||||
|
|
27
src/lib.rs
27
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<Ast> = 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 {
|
||||
|
|
52
src/world.rs
52
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<Result<Value, Panic>> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user