From b71c72db8b282d179030a2e28e8022f9e6ef3698 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Fri, 30 May 2025 18:05:02 -0500 Subject: [PATCH] remove actors being created via cmd line args --- scripts/cmd.cm | 261 ----------------------------------------- scripts/engine.cm | 58 ++++++--- source/cell.c | 18 +-- source/cell.h | 10 +- source/jsffi.c | 12 +- source/qjs_actor.c | 15 +-- source/qjs_sdl_video.c | 27 ++--- tests/overling.ce | 15 +-- tests/qr_drag.ce | 1 - tests/spawner.ce | 14 +-- tests/underling.ce | 5 +- 11 files changed, 85 insertions(+), 351 deletions(-) delete mode 100644 scripts/cmd.cm diff --git a/scripts/cmd.cm b/scripts/cmd.cm deleted file mode 100644 index 0313aa7c..00000000 --- a/scripts/cmd.cm +++ /dev/null @@ -1,261 +0,0 @@ -var io = use('io') -var util = use('util') - -var dumpfolder = ".prosperon"; - -io.mkdir(dumpfolder) - -var Cmdline = {}; - -Cmdline.cmds = []; -Cmdline.orders = {}; -Cmdline.register_cmd = function (flag, fn, doc) { - Cmdline.cmds.push({ - flag: flag, - fn: fn, - doc: doc, - }); -}; - -Cmdline.register_order = function (order, fn, doc, usage = "") { - Cmdline.orders[order] = fn; - fn.doc = doc; - fn.usage = `${order} ${usage}`; -}; - -Cmdline.register_order( - "makedoc", - function() { - var doc = use('doc') - - var gs = ['console', 'prosperon', 'actor', 'use'] - - for (var g of gs) - io.slurpwrite(`.src/docs/api/${g}.md`, doc.writeDocFile(globalThis[g], g)) - - var coredocs = io.enumerate("scripts/modules", 0) - coredocs = coredocs.filter(x => io.match("**/*.js", x)).map(x => x.name()) - - var APIPATH = '.src/docs/api/modules/' - - for (var m of coredocs) { - var u = use(m) - var path = `${APIPATH}${m}.md` - io.slurpwrite(path, doc.writeDocFile(u, m)) - } - - var TYPEPATH = '.src/docs/api/types/' - for (var c in prosperon.c_types) - io.slurpwrite(`${TYPEPATH}${c}.md`, doc.writeDocFile(prosperon.c_types[c], c)) - - var DULLPATH = '.src/docs/dull/' - var mixins = ['Object', 'String', 'Array', 'Map', 'WeakMap', 'Symbol','Set', 'WeakSet', 'ArrayBuffer', 'Function'] - for (var m of mixins) { - var path = `${DULLPATH}${m}.md` - io.slurpwrite(path, doc.writeDocFile(globalThis[m].prototype, m)) - } - - var dullgpath = '.src/docs/dull/globals/' - var globals = ['Object', 'String', 'Array', 'Symbol', 'Number', 'Error','Function', 'Math'] - for (var m of globals) { - var path = `${dullgpath}${m}.md` - io.slurpwrite(path, doc.writeDocFile(globalThis[m], m)) - } - "Make documentation." -}) - -Cmdline.register_order( - "play", - function (argv) { - var app - if (io.exists("main.js")) - app = actor.spawn("main.js") - else - app = actor.spawn("nogame.js") - - var loop = use('loop') - while(1) loop.step(); - }, - "Play the game present in this folder.", -); - -Cmdline.register_order( - "about", - function (argv) { - if (!argv[0]) { - log.print("About your game"); - log.print(`Prosperon version ${prosperon.version}`); - log.print(`Total entities ${ur._list.length}`); - } - switch (argv[0]) { - case "entities": - for (var i of ur._list) log.print(i); - break; - } - }, - "Get information about this game.", -); - -Cmdline.register_order( - "api", - function (obj) { - var doc = use('doc') - doc.write_modules() - doc.write_c_types() - }, - "Print the API for an object as markdown. Give it a file to save the output to.", - "OBJECT", -); - -Cmdline.register_order( - "input", - function (pawn) { - use("editor.js"); - log.print(`## Input for ${pawn}`); - eval(`log.print(input.print_md_kbm(${pawn}));`); - }, - "Print input documentation for a given object as markdown. Give it a file to save the output to", - "OBJECT ?FILE?", -); - -Cmdline.print_order = function (fn) { - if (typeof fn === "string") fn = Cmdline.orders[fn]; - - if (!fn) return; - log.print(`Usage: prosperon ${fn.usage}` + "\n"); - log.print(fn.doc + "\n"); -}; - -function parse_args(argv) -{ - var args = {}; - for (var i = 0; i < argv.length; i++) { - if (argv[i].startsWith("--")) { - var key = argv[i].slice(2); - if (i + 1 < argv.length && !argv[i + 1].startsWith("--")) { - args[key] = argv[i + 1]; - i++; // Skip the value - } else { - args[key] = true; // Flag without value - } - } - } - return args; -} - -function unparse_args(args) { - var argv = []; - for (var key in args) { - if (args.hasOwnProperty(key)) { - argv.push("--" + key); // Add the flag with "--" prefix - if (args[key] !== true) { - argv.push(args[key]); // Add the value if it's not a boolean true flag - } - } - } - return argv; -} - -Cmdline.register_order( - "spawn", - function(argv) { - prosperon.args = parse_args(argv) - if (!prosperon.args.cwd) prosperon.args.cwd = '.' - io.mount(prosperon.args.cwd) - - // Store all remaining non-flag arguments - var remaining_args = [] - var skip_next = false - for (var i = 0; i < argv.length; i++) { - if (skip_next) { - skip_next = false - continue - } - if (argv[i].startsWith("--")) { - // Check if this flag has a value - if (i + 1 < argv.length && !argv[i + 1].startsWith("--")) { - skip_next = true - } - continue - } - remaining_args.push(argv[i]) - } - - // Add remaining arguments to prosperon.args - prosperon.args.remaining = remaining_args - - if (!prosperon.args.program) - os.exit() - }, - "Spawn a new prosperon actor.", - "TOPIC" -); - -Cmdline.register_order( - "help", - function (order) { - if (!util.isEmpty(order)) { - var orfn = Cmdline.orders[order]; - - if (!orfn) { - log.warn(`No command named ${order}.`); - return; - } - - Cmdline.print_order(orfn); - return; - } - - Cmdline.print_order("help"); - - for (var cmd of Object.keys(Cmdline.orders).sort()) log.print(cmd + "\n"); - - Cmdline.orders.version(); - }, - "Give help with a specific command.", - "TOPIC", -); - -Cmdline.register_order( - "version", - function () { - log.print(`Prosperon version ${prosperon.version} [${prosperon.revision}]` + "\n"); - }, - "Display Prosperon info.", -); - -function cmd_args(cmds) { - // Remove the leading 'prosperon' - cmds.shift(); - - // If there are no arguments left, assume we want to spawn main.js - if (!cmds[0]) { - // => effectively do: prosperon spawn --program main.js - cmds.unshift("main.js"); - cmds.unshift("--program"); - cmds.unshift("spawn"); - } else if (!Cmdline.orders[cmds[0]]) { - // If the first token isn't a recognized command, treat it as either - // a directory containing main.js, or a script to run directly. - var arg0 = cmds.shift(); - if (io.is_directory(arg0)) { - var script = cmds[0] ? cmds.shift() : "main.js"; - cmds.unshift(script); - cmds.unshift("--program"); - cmds.unshift(arg0); - cmds.unshift("--cwd"); - } else { - cmds.unshift(arg0); - cmds.unshift("--program"); - } - cmds.unshift("spawn"); - } - - Cmdline.orders[cmds[0]](cmds.slice(1)); -} - -return { - process: cmd_args, - encode: parse_args, - decode: unparse_args, -} diff --git a/scripts/engine.cm b/scripts/engine.cm index e9b47e70..0852df95 100644 --- a/scripts/engine.cm +++ b/scripts/engine.cm @@ -1,6 +1,6 @@ (function engine() { - globalThis.cell = prosperon - cell.DOC = cell.hidden.DOCSYM +globalThis.cell = prosperon +cell.DOC = cell.hidden.DOCSYM var MOD_EXT = '.cm' var ACTOR_EXT = '.ce' @@ -24,7 +24,10 @@ function caller_data(depth = 0) return {file,line} } +cell.args = cell.hidden.init +cell.args ??= {} cell.id ??= "newguy" + function console_rec(line, file, msg) { return `[${cell.id.slice(0,5)}] [${file}:${line}]: ${msg}\n` @@ -90,6 +93,17 @@ var nota = hidden.nota delete cell.hidden var os = use_embed('os') + + + +os.on = function(e) +{ + log.console(JSON.stringify(e)) + log.error(e) + + disrupt() +} + var js = use_embed('js') var io = use_embed('io') @@ -123,6 +137,8 @@ var fnname = "base" script = `(function ${fnname}() { ${script}; })` js.eval(BASEPATH, script)() + + var inProgress = {} var loadingStack = [] @@ -438,18 +454,22 @@ $_.receiver = function receiver(fn) { } $_.receiver[cell.DOC] = "registers a function that will receive all messages..." -$_.start = function start(cb, prg, arg) { +$_.start = function start(cb, program, arg) { if (dying) { log.warn(`Cannot start an underling in the same turn as we're stopping`) return } var id = util.guid() + var startup = { + id, + overling: $_, + root, + arg, + program + } greeters[id] = cb - var argv = ["./cell", "spawn", "--id", id, "--overling", json.encode($_), "--root", json.encode(root)] - if (prg) argv = argv.concat(['--program', prg]) - if (arg) argv = argv.concat(cmd.encode(arg)) underlings.add(id) - actor_mod.createactor(argv) + actor_mod.createactor(startup) } $_.start[cell.DOC] = "The start function creates a new actor..." @@ -489,6 +509,13 @@ $_.couple = function couple(actor) { } $_.couple[cell.DOC] = "causes this actor to stop when another actor stops." +function disrupt() +{ + dying = true + if (overling) actor_prep(overling, {type:'disrupt', actor: $_}) + actor_mod.destroy() +} + function actor_prep(actor, send) { message_queue.push({actor,send}); } @@ -593,9 +620,6 @@ Object.defineProperty(globalThis, 'send', { enumerable: true }); -var cmd = use('cmd') -cmd.process(cell.argv.slice()) - if (!cell.args.id) cell.id = util.guid() else cell.id = cell.args.id @@ -617,10 +641,9 @@ function turn(msg) actor_mod.register_actor(cell.id, turn, cell.args.main) -if (cell.args.overling) overling = json.decode(cell.args.overling) - -if (cell.args.root) root = json.decode(cell.args.root) -else root = $_ +overling = cell.args.overling +root = cell.args.root +root ??= $_ if (overling) actor_prep(overling, {type:'greet', actor: $_}) @@ -628,10 +651,11 @@ if (!cell.args.program) os.exit(1) function destroyself() { - log.spam(`Got the message to destroy self.`) dying = true for (var i of underlings) $_.stop(create_actor({id:i})) + + if (overling) actor_prep(overling, {type:'stop', actor: $_}) actor_mod.destroy() } @@ -729,8 +753,8 @@ if (progDir && progDir !== '.') { } var progContent = io.slurp(prog) -var prog_script = `(function ${cell.args.program.name()}_start($_) { ${progContent} })` -var val = js.eval(cell.args.program, prog_script)($_) +var prog_script = `(function ${cell.args.program.name()}_start($_, arg) { ${progContent} })` +var val = js.eval(cell.args.program, prog_script)($_, ) if (val) throw new Error('Program must not return anything'); diff --git a/source/cell.c b/source/cell.c index ba337548..065c327a 100644 --- a/source/cell.c +++ b/source/cell.c @@ -224,11 +224,10 @@ int prosperon_mount_core(void) return ret; } -cell_rt *create_actor(int argc, char **argv, void (*hook)(JSContext*)) +cell_rt *create_actor(void *wota, void (*hook)(JSContext*)) { cell_rt *actor = calloc(sizeof(*actor), 1); - actor->cmd.argc = argc; - actor->cmd.argv = argv; + actor->init_wota = wota; actor->cycle_fn = JS_UNDEFINED; actor->idx_buffer = JS_UNDEFINED; actor->message_handle = JS_UNDEFINED; @@ -714,9 +713,8 @@ void script_startup(cell_rt *prt, void (*hook)(JSContext*)) data[stat.filesize] = 0; /* Call hook function if provided before evaluating engine */ - if (hook) { + if (hook) hook(js); - } /* Called with actor->mutex locked by create_actor(). */ JSValue v = JS_Eval(js, data, (size_t)stat.filesize, ENGINE, JS_EVAL_FLAG_STRICT); @@ -1559,10 +1557,14 @@ int main(int argc, char **argv) /* Create the initial actor from the main command line. */ /* Adjust argc and argv to skip --profile if present */ - int actor_argc = argc - (script_start - 1); char **actor_argv = argv + (script_start - 1); - actor_argv[0] = argv[0]; // Keep the program name - create_actor(actor_argc, actor_argv, NULL); + + WotaBuffer startwota; + wota_buffer_init(&startwota, 5); + wota_write_record(&startwota, 1); + wota_write_text(&startwota, "program"); + wota_write_text(&startwota, actor_argv[1]); // program name + create_actor(startwota.data,NULL); // this can fall off because the actor takes care of freeing the wota data /* Start the thread that pumps ready actors, one per logical core. */ for (int i = 0; i < cores; i++) { diff --git a/source/cell.h b/source/cell.h index 00dca5a3..0d378cf0 100644 --- a/source/cell.h +++ b/source/cell.h @@ -29,19 +29,15 @@ typedef struct { MODULEFN fn; } ModuleEntry; -typedef struct { - int argc; - char **argv; -} cmdargs; - typedef struct cell_rt { - cmdargs cmd; JSContext *context; JSValue cycle_fn; JSValue idx_buffer; JSValue on_exception; JSValue message_handle; JSValue unneeded; + + void *init_wota; ModuleEntry *module_registry; JSValue *js_swapchains; @@ -78,7 +74,7 @@ typedef struct cell_rt { extern SDL_ThreadID main_thread; extern SDL_TLSID prosperon_id; -cell_rt *create_actor(int argc, char **argv, void (*hook)(JSContext*)); +cell_rt *create_actor(void *wota, void (*hook)(JSContext*)); const char *register_actor(const char *id, cell_rt *actor, int mainthread); void actor_free(cell_rt *actor); const char *send_message(const char *id, void *msg); diff --git a/source/jsffi.c b/source/jsffi.c index 84f5c3fc..73b58af7 100644 --- a/source/jsffi.c +++ b/source/jsffi.c @@ -1525,6 +1525,7 @@ JSC_CCALL(os_value_id, #include "qjs_crypto.h" #include "qjs_time.h" #include "qjs_http.h" +#include "qjs_wota.h" //JSValue js_imgui_use(JSContext *js); #define MISTLINE(NAME) (ModuleEntry){#NAME, js_##NAME##_use} @@ -1606,11 +1607,6 @@ void ffi_load(JSContext *js) JS_FreeValue(js,jsnumber); JS_FreeValue(js,number_proto); - JSValue args = JS_NewArray(js); - for (int i = 0; i < rt->cmd.argc; i++) - JS_SetPropertyUint32(js,args, i, JS_NewString(js,rt->cmd.argv[i])); - - JS_SetPropertyStr(js,prosp,"argv", args); //JS_SetPropertyStr(js,prosp, "version", JS_NewString(js,CELL_VERSION)); //JS_SetPropertyStr(js,prosp,"revision",JS_NewString(js,CELL_COMMIT)); @@ -1630,6 +1626,12 @@ void ffi_load(JSContext *js) JS_SetPropertyStr(js, prosp, "hidden", hidden_fn); + if (rt->init_wota) { + JS_SetPropertyStr(js, hidden_fn, "init", wota2value(js, rt->init_wota)); + // init wota can now be freed + free(rt->init_wota); + } + JS_FreeValue(js,globalThis); cell_rt *actor = JS_GetContextOpaque(js); diff --git a/source/qjs_actor.c b/source/qjs_actor.c index 60e8a8eb..b1bb7c83 100644 --- a/source/qjs_actor.c +++ b/source/qjs_actor.c @@ -77,19 +77,8 @@ JSValue actor2js(JSContext *js, cell_rt *actor) } JSC_CCALL(os_createactor, - int margc = JS_ArrayLength(js, argv[0]); - - char **margv = malloc(margc*sizeof(char*)); - - for (int i = 0; i < margc; i++) { - JSValue val = JS_GetPropertyUint32(js, argv[0], i); - const char *cstr = JS_ToCString(js,val); - margv[i] = strdup(cstr); - JS_FreeCString(js,cstr); - JS_FreeValue(js,val); - } - - create_actor(margc, margv, NULL); + void *startup = value2wota(js, argv[0], JS_UNDEFINED); + create_actor(startup, NULL); ) JSC_CCALL(os_mailbox_push, diff --git a/source/qjs_sdl_video.c b/source/qjs_sdl_video.c index 3dfb84f5..ad577f64 100644 --- a/source/qjs_sdl_video.c +++ b/source/qjs_sdl_video.c @@ -14,10 +14,6 @@ #include #include "qjs_sdl.h" -// External function declarations -extern cell_rt *create_actor(int argc, char **argv, void (*hook)(JSContext *)); -extern const char *register_actor(const char *id, cell_rt *rt, int main_thread); - // SDL Window free function void SDL_Window_free(JSRuntime *rt, SDL_Window *w) { @@ -1799,6 +1795,8 @@ static void video_actor_hook(JSContext *js) { JS_FreeValue(js, prosperon); } +#include "qjs_wota.h" + JSValue js_sdl_video_use(JSContext *js) { if (!SDL_Init(SDL_INIT_VIDEO)) return JS_ThrowInternalError(js, "Unable to initialize video subsystem: %s", SDL_GetError()); @@ -1807,18 +1805,15 @@ JSValue js_sdl_video_use(JSContext *js) { char id[64]; snprintf(id, sizeof(id), "video_%llu", (unsigned long long)SDL_GetTicks()); - // Prepare argv for create_actor - // We need to create the actor on the main thread - const char *argv[] = { - "./prosperon", - "spawn", - "--id", id, - "--program", "_sdl_video.js", - "--main", "1" - }; - int argc = 8; + JSValue startup = JS_NewObject(js); + JS_SetPropertyStr(js,startup, "id", JS_NewStringLen(js,id,64)); + JS_SetPropertyStr(js,startup, "program", JS_NewString(js,"_sdl_video.js")); + JS_SetPropertyStr(js,startup,"main",JS_NewBool(js,1)); - // Create the actor with the hook to set up endowments - cell_rt *actor = create_actor(argc, (char**)argv, video_actor_hook); + void *wota = value2wota(js,startup, JS_UNDEFINED); + + JS_FreeValue(js,startup); + + cell_rt *actor = create_actor(wota, video_actor_hook); return actor2js(js,actor); } diff --git a/tests/overling.ce b/tests/overling.ce index 10589e1c..96c722c5 100644 --- a/tests/overling.ce +++ b/tests/overling.ce @@ -1,13 +1,8 @@ $_.start(e => { - switch(e.type) { - case "actor_started": - log.console(json.encode(e)) - $_.connection(e => log.console(json.encode(e)), e.actor) // get connection info +}, "underling", ['stop']) - send(e.actor, {message: "Hello!"}) - - $_.couple(e.actor) +$_.start(e => { +}, "underling", ['disrupt']) - $_.stop(e.actor) - } -}, "tests/underling"); +$_.start(e => { +}, "underling", ['kill']) diff --git a/tests/qr_drag.ce b/tests/qr_drag.ce index 4464ad06..e3d6693d 100644 --- a/tests/qr_drag.ce +++ b/tests/qr_drag.ce @@ -1,4 +1,3 @@ -// bunnymark var render = use('render') var os = use('os') var actor = use('actor') diff --git a/tests/spawner.ce b/tests/spawner.ce index d47daf1d..f7108e55 100644 --- a/tests/spawner.ce +++ b/tests/spawner.ce @@ -1,12 +1,2 @@ - -function spawnem() -{ - for (var i = 0; i < 10; i++) - $_.start(_ => {}, "tests/spawnee") -} - -with ([1,2,3]) { - log.console(toString()) -} - -$_.delay(spawnem, 3) \ No newline at end of file +for (var i = 0; i < 10; i++) + $_.start(_ => {}, "spawnee") diff --git a/tests/underling.ce b/tests/underling.ce index 3fc660d0..18ddda2d 100644 --- a/tests/underling.ce +++ b/tests/underling.ce @@ -1,4 +1,7 @@ -var os = use('os') + +switch(arg[0]) { + case +} $_.receiver(e => { log.console(`got message: ${json.encode(e)}`)