From f5d610cbedc33dd81aec0c9007001268d26550fc Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Thu, 21 Mar 2024 11:33:36 -0500 Subject: [PATCH] 'use' now how to load extra programs; cached --- scripts/actor.js | 4 +- scripts/base.js | 8 +-- scripts/debug.js | 15 ---- scripts/engine.js | 139 +++++++++++++++++++++----------------- scripts/entity.js | 23 ++++--- scripts/std.js | 49 ++------------ source/engine/debug/log.c | 8 ++- source/engine/jsffi.c | 30 ++------ source/engine/script.c | 27 ++------ source/engine/script.h | 5 +- source/engine/yugine.c | 3 +- 11 files changed, 115 insertions(+), 196 deletions(-) diff --git a/scripts/actor.js b/scripts/actor.js index f56daf5..00123c7 100644 --- a/scripts/actor.js +++ b/scripts/actor.js @@ -1,12 +1,10 @@ var actor = {}; -var a_db = {}; actor.spawn = function(script, config){ if (typeof script !== 'string') return undefined; console.info(`spawning actor with script ${script}`); - if (!a_db[script]) a_db[script] = io.slurp(script); var padawan = Object.create(actor); - eval_env(a_db[script], padawan, script); + use(script, padawan); if (typeof config === 'object') Object.merge(padawan,config); diff --git a/scripts/base.js b/scripts/base.js index df164b3..8cedcdf 100644 --- a/scripts/base.js +++ b/scripts/base.js @@ -590,11 +590,9 @@ Object.defineProperty(Object.prototype, 'obscure', { Object.defineProperty(Object.prototype, 'mixin', { value: function(obj) { - if (typeof obj === 'string') { - var script = io.slurp(obj); - obj = eval_env(script, this, obj); - } - + if (typeof obj === 'string') + obj = use(obj, this); + if (obj) Object.mixin(this, obj); }, diff --git a/scripts/debug.js b/scripts/debug.js index ca5433c..1ecc90e 100644 --- a/scripts/debug.js +++ b/scripts/debug.js @@ -19,8 +19,6 @@ debug.draw = function() { if (this.draw_bb) game.all_objects(function(x) { debug.boundingbox(x.boundingbox(), Color.debug.boundingbox.alpha(0.05)); }); - - if (this.draw_gizmos) game.all_objects(function(x) { if (!x.icon) return; @@ -66,19 +64,6 @@ var Gizmos = { }, }; -profile.best_t = function(t) { - var qq = 'ns'; - if (t > 1000) { - t /= 1000; - qq = 'us'; - if (t > 1000) { - t /= 1000; -qq = 'ms'; - } - } - return `${t.toPrecision(4)} ${qq}`; -} - profile.cpu = function(fn, times, q) { times ??= 1; q ??= "unnamed"; diff --git a/scripts/engine.js b/scripts/engine.js index 5fe924b..16e3875 100644 --- a/scripts/engine.js +++ b/scripts/engine.js @@ -1,5 +1,41 @@ "use math"; +globalThis.Resources = {}; +Resources.scripts = ["jsoc", "jsc", "jso", "js"]; +Resources.images = ["png", "gif", "jpg", "jpeg"]; +Resources.sounds = ["wav", 'flac', 'mp3', "qoa"]; +Resources.is_image = function(path) { + var ext = path.ext(); + return Resources.images.any(x => x === ext); +} + +function find_ext(file, ext) +{ + if (io.exists(file)) return file; + for (var e of ext) { + var nf = `${file}.${e}`; + if (io.exists(nf)) return nf; + } + return; +} + +Resources.find_image = function(file) { return find_ext(file,Resources.images); } +Resources.find_sound = function(file) { return find_ext(file,Resources.sounds); } +Resources.find_script = function(file) { return find_ext(file,Resources.scripts); } + +profile.best_t = function(t) { + var qq = 'ns'; + if (t > 1000) { + t /= 1000; + qq = 'us'; + if (t > 1000) { + t /= 1000; +qq = 'ms'; + } + } + return `${t.toPrecision(4)} ${qq}`; +} + Object.assign(console, { say(msg) { console.print(msg + "\n"); }, @@ -60,36 +96,29 @@ console.doc = { globalThis.global = globalThis; -function use(file) +function use(file, env, script) { - if (use.files[file]) return use.files[file]; - console.info(`running ${file}`); - - var c = io.slurp(file); + file = Resources.find_script(file); + console.info(`loading up ${file}`); + var st = profile.now(); + env ??= {}; - var script = `(function() { ${c} })();`; - use.files[file] = os.eval_env(file,script,global); - - return use.files[file]; -} -use.files = {}; - -function include(file,that) -{ - if (!that) return; - console.info(`running ${file}`); - var c = io.slurp(file); - eval_env(c, that, file); + if (use.cache[file]) { + var ret = use.cache[file].call(env); + console.info(`CACHE eval ${file} in ${profile.best_t(profile.now()-st)}`); + return; + } + + script ??= io.slurp(file); + script = `(function() { ${script}; })`; + var fn = os.eval(file,script); + use.cache[file] = fn; + var ret = fn.call(env); + console.info(`eval ${file} in ${profile.best_t(profile.now()-st)}`); + return ret; } -function eval_env(script, env, file) -{ - env ??= {}; - file ??= "SCRIPT"; - console.spam(`eval ${file}`); - script = `(function() { ${script}; }).call(this);\n`; - return os.eval_env(file,script,env); -} +use.cache = {}; global.check_registers = function(obj) { @@ -121,28 +150,10 @@ global.check_registers = function(obj) }; } -eval_env.dov = `Counterpart to /load_env/, but with a string.`; - -function feval_env(file, env) -{ - eval_env(io.slurp(file), env, file); -} - -function load_env(file,env) -{ - env ??= global; - var script = io.slurp(file); - eval_env(script, env, file); -} - -load_env.doc = `Load a given file with 'env' as **this**. Does not add to the global namespace.`; - -var load = use; - -Object.assign(global, use("scripts/base.js")); +Object.assign(global, use("scripts/base")); global.obscure('global'); -global.mixin("scripts/render.js"); -global.mixin("scripts/debug.js"); +global.mixin("scripts/render"); +global.mixin("scripts/debug"); var frame_t = profile.secs(profile.now()); var phys_step = 1/60; @@ -162,7 +173,11 @@ var timescale = 1; var gggstart = game.engine_start; game.engine_start = function(s) { - gggstart(function() { world_start(); s(); }, process); + gggstart(function() { + world_start(); + go_init(); + s(); + }, process); } function process() @@ -290,11 +305,11 @@ prosperon.quit = function(){ console.warn(debug.log.time[i].map(x=>profile.ms(x))); }; -global.mixin("scripts/input.js"); -global.mixin("scripts/std.js"); -global.mixin("scripts/diff.js"); -global.mixin("scripts/color.js"); -global.mixin("scripts/gui.js"); +global.mixin("scripts/input"); +global.mixin("scripts/std"); +global.mixin("scripts/diff"); +global.mixin("scripts/color"); +global.mixin("scripts/gui"); var timer = { update(dt) { @@ -322,10 +337,10 @@ var timer = { }, }; -global.mixin("scripts/tween.js"); -global.mixin("scripts/physics.js"); -global.mixin("scripts/ai.js"); -global.mixin("scripts/geometry.js"); +global.mixin("scripts/tween"); +global.mixin("scripts/physics"); +global.mixin("scripts/ai"); +global.mixin("scripts/geometry"); /* Factory for creating registries. Register one with 'X.register', @@ -414,8 +429,8 @@ window.world2screen = function(worldpos) { window.set_icon.doc = "Set the icon of the window using the PNG image at path."; -global.mixin("scripts/spline.js"); -global.mixin("scripts/components.js"); +global.mixin("scripts/spline"); +global.mixin("scripts/components"); window.doc = {}; window.doc.width = "Width of the game window."; @@ -424,8 +439,8 @@ window.doc.dimensions = "Window width and height packaged in an array [width,hei window.doc.title = "Name in the title bar of the window."; window.doc.boundingbox = "Boundingbox of the window, with top and right being its height and width."; -global.mixin("scripts/actor.js"); -global.mixin("scripts/entity.js"); +global.mixin("scripts/actor"); +global.mixin("scripts/entity"); function world_start() { globalThis.world = os.make_gameobject(); @@ -439,7 +454,7 @@ function world_start() { game.cam = world; } -global.mixin("scripts/physics.js"); +global.mixin("scripts/physics"); window.title = `Prosperon v${prosperon.version}`; window.size = [500,500]; diff --git a/scripts/entity.js b/scripts/entity.js index 8684952..f67a71a 100644 --- a/scripts/entity.js +++ b/scripts/entity.js @@ -296,7 +296,7 @@ var gameobject = { } if (ent.ur === 'script') - eval_env(io.slurp(text), ent, ent.ur); + use(text, ent); else apply_ur(ent.ur, ent); @@ -616,16 +616,17 @@ var gameobject = { }, } -var gop = os.make_gameobject().__proto__; -Object.mixin(gop, gameobject); -var gsync = gop.sync; -gop.sync = function() { - gsync.call(this); - this.components.forEach(function(x) { x.sync?.(); }); - this.objects.forEach(function(x) { x.sync(); }); +function go_init() { + var gop = os.make_gameobject().__proto__; + Object.mixin(gop, gameobject); + var gsync = gop.sync; + gop.sync = function() { + gsync.call(this); + this.components.forEach(function(x) { x.sync?.(); }); + this.objects.forEach(function(x) { x.sync(); }); + } } - gameobject.spawn.doc = `Spawn an entity of type 'ur' on this entity. Returns the spawned entity.`; gameobject.doc = { @@ -720,7 +721,7 @@ function apply_ur(u, e) { if (topur.text) { var script = Resources.replstrs(topur.text); - eval_env(script, e, topur.text); + use(topur.text, e, script); } if (topur.data) { @@ -780,3 +781,5 @@ game.loadurs = function() { name: "empty" }; }; + +return { go_init } \ No newline at end of file diff --git a/scripts/std.js b/scripts/std.js index eb52303..d1af99e 100644 --- a/scripts/std.js +++ b/scripts/std.js @@ -39,30 +39,6 @@ os.prefpath = function() { var projectfile = ".prosperon/project.json"; -var Resources = {}; -Resources.scripts = ["jso", "js"]; -Resources.images = ["png", "gif", "jpg", "jpeg"]; -Resources.sounds = ["wav", 'flac', 'mp3', "qoa"]; -Resources.scripts = "js"; -Resources.is_image = function(path) { - var ext = path.ext(); - return Resources.images.any(x => x === ext); -} - -function find_ext(file, ext) -{ - if (io.exists(file)) return file; - for (var e of ext) { - var nf = `${file}.${e}`; - if (io.exists(nf)) return nf; - } - return; -} - -Resources.find_image = function(file) { return find_ext(file,Resources.images); } -Resources.find_sound = function(file) { return find_ext(file,Resources.sounds); } -Resources.find_script = function(file) { return find_ext(file,Resources.scripts); } - Resources.is_sound = function(path) { var ext = path.ext(); return Resources.sounds.any(x => x === ext); @@ -89,6 +65,7 @@ Resources.gif.frames = function(path) { return render.gif_frames(path); } Resources.replpath = function(str, path) { + if (!str) return str; if (str[0] === "/") return str.rm(0); @@ -421,7 +398,7 @@ Cmdline.register_order("api", function(obj) { return; } - load("scripts/editor.js"); + use("scripts/editor.js"); var api = debug.api.print_doc(obj[0]); if (!api) return; @@ -429,15 +406,8 @@ Cmdline.register_order("api", function(obj) { say(api); }, "Print the API for an object as markdown. Give it a file to save the output to.", "OBJECT"); -Cmdline.register_order("compile", function(argv) { - for (var file of argv) { - var comp = io.compile(file); - io.slurpwrite(file + "c", comp); - } -}, "Compile one or more provided files into bytecode.", "FILE ..."); - Cmdline.register_order("input", function(pawn) { - load("scripts/editor.js"); + use("scripts/editor.js"); say(`## Input for ${pawn}`); eval(`say(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?"); @@ -449,17 +419,7 @@ Cmdline.register_order("run", function(script) { return; } - if (io.exists(script)) - try { - if (script.endswith("c")) - io.run_bytecode(script); - else - load(script); - } catch(e) { } - else { - var ret = eval(script); - if (ret) say(ret); - } + say(use(script)); }, "Run a given script. SCRIPT can be the script itself, or a file containing the script", "SCRIPT"); Cmdline.orders.script = Cmdline.orders.run; @@ -515,7 +475,6 @@ function cmd_args(cmdargs) Cmdline.orders[cmds[0]](cmds.slice(1)); } - Cmdline.register_order("clean", function(argv) { say("Cleaning not implemented."); }, "Clean up a given object file.", "JSON ..."); diff --git a/source/engine/debug/log.c b/source/engine/debug/log.c index 0188a88..e6c4476 100644 --- a/source/engine/debug/log.c +++ b/source/engine/debug/log.c @@ -40,8 +40,11 @@ int stdout_lvl = LOG_ERROR; void log_init() { #ifndef NDEBUG - if (!fexists(".prosperon")) - logout = writeout = dump = stdout; + if (!fexists(".prosperon")) { + logout = tmpfile(); + dump = tmpfile(); + writeout = stdout; + } else { logout = fopen(".prosperon/log.txt", "w"); writeout = fopen(".prosperon/transcript.txt", "w"); @@ -98,7 +101,6 @@ void log_print(const char *str) #ifndef NDEBUG fprintf(writeout, str); #endif - printf(str); fflush(stdout); } diff --git a/source/engine/jsffi.c b/source/engine/jsffi.c index 8192090..dca3241 100644 --- a/source/engine/jsffi.c +++ b/source/engine/jsffi.c @@ -748,8 +748,7 @@ JSValue js_os_sys(JSContext *js, JSValue this, int argc, JSValue *argv) JSC_CCALL(os_quit, quit();) JSC_CCALL(os_reindex_static, cpSpaceReindexStatic(space)); JSC_CCALL(os_gc, script_gc()); -JSC_SSCALL(os_eval_env, ret = eval_script_env(str, argv[2], str2)) - +JSC_SSCALL(os_eval, ret = script_eval(str, str2)) JSC_SCALL(os_capture, capture_screen(js2number(argv[1]), js2number(argv[2]), js2number(argv[4]), js2number(argv[5]), str)) JSC_CCALL(os_sprite, @@ -807,7 +806,7 @@ static const JSCFunctionListEntry js_os_funcs[] = { MIST_FUNC_DEF(os, reindex_static, 0), MIST_FUNC_DEF(os, gc, 0), MIST_FUNC_DEF(os, capture, 5), - MIST_FUNC_DEF(os, eval_env, 3), + MIST_FUNC_DEF(os, eval, 2), MIST_FUNC_DEF(os, make_gameobject, 0), MIST_FUNC_DEF(os, make_circle2d, 1), MIST_FUNC_DEF(os, make_poly2d, 1), @@ -1101,26 +1100,6 @@ JSValue js_io_chmod(JSContext *js, JSValue this, int argc, JSValue *argv) JSC_SCALL(io_save_qoa, save_qoa(str)) -JSValue js_io_compile(JSContext *js, JSValue this, int argc, JSValue *argv) { - size_t len; - char *str = js2str(argv[0]); - void *d = script_compile(str, &len); - JSValue ret = JS_NewArrayBufferCopy(js,d,len); - JS_FreeCString(js,str); - free(d); - return ret; -} - -JSValue js_io_run_bytecode(JSContext *js, JSValue this, int argc, JSValue *argv) { - size_t len; - char *str = js2str(argv[0]); - void *d = slurp_file(str, &len); - JSValue ret = script_run_bytecode(d, len); - JS_FreeCString(js,str); - free(d); - return ret; -} - JSC_SCALL(io_pack_engine, pack_engine(str)) static const JSCFunctionListEntry js_io_funcs[] = { @@ -1136,7 +1115,7 @@ static const JSCFunctionListEntry js_io_funcs[] = { MIST_FUNC_DEF(io, slurpbytes, 1), MIST_FUNC_DEF(io, slurpwrite, 2), MIST_FUNC_DEF(io, save_qoa,1), - MIST_FUNC_DEF(io, pack_engine, 1) + MIST_FUNC_DEF(io, pack_engine, 1), }; JSC_CCALL(debug_draw_gameobject, gameobject_draw_debug(js2gameobject(argv[0]));) @@ -1580,6 +1559,8 @@ void ffi_load() { QJSCLASSPREP(ptr); + QJSGLOBALCLASS(os); + QJSCLASSPREP_FUNCS(gameobject); QJSCLASSPREP_FUNCS(dsp_node); QJSCLASSPREP_FUNCS(emitter); @@ -1591,7 +1572,6 @@ void ffi_load() { QJSCLASSPREP_FUNCS(window); QJSCLASSPREP_FUNCS(drawmodel); - QJSGLOBALCLASS(os); QJSGLOBALCLASS(nota); QJSGLOBALCLASS(input); QJSGLOBALCLASS(io); diff --git a/source/engine/script.c b/source/engine/script.c index a14b68a..abcc099 100644 --- a/source/engine/script.c +++ b/source/engine/script.c @@ -23,7 +23,7 @@ void script_startup() { size_t len; char *eng = slurp_text("scripts/engine.js", &len); - eval_script_env("scripts/engine.js", JS_GetGlobalObject(js), eng); + script_eval("scripts/engine.js", eng); free(eng); } @@ -39,25 +39,6 @@ void script_stop() void script_gc() { JS_RunGC(rt); } -uint8_t *script_compile(const char *file, size_t *len) { - size_t file_len; - char *script = slurp_text(file, &file_len); - JSValue obj = JS_Eval(js, script, file_len, file, JS_EVAL_FLAG_COMPILE_ONLY | JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAGS); - free(script); - uint8_t *out = JS_WriteObject(js, len, obj, JS_WRITE_OBJ_BYTECODE); - JS_FreeValue(js,obj); - return out; -} - -JSValue script_run_bytecode(uint8_t *code, size_t len) -{ - JSValue b = JS_ReadObject(js, code, len, JS_READ_OBJ_BYTECODE); - JSValue ret = JS_EvalFunction(js, b); - js_print_exception(ret); - JS_FreeValue(js,b); - return ret; -} - void js_stacktrace() { #ifndef NDEBUG script_evalf("console.stack();"); @@ -77,11 +58,11 @@ void script_evalf(const char *format, ...) JS_FreeValue(js,obj); } -JSValue eval_script_env(const char *file, JSValue env, const char *script) +JSValue script_eval(const char *file, const char *script) { - JSValue v = JS_EvalThis(js, env, script, strlen(script), file, JS_EVAL_FLAGS); + JSValue v = JS_Eval(js, script, strlen(script), file, JS_EVAL_FLAGS | JS_EVAL_FLAG_COMPILE_ONLY); js_print_exception(v); - return v; + return JS_EvalFunction(js, v); } void script_call_sym(JSValue sym, int argc, JSValue *argv) { diff --git a/source/engine/script.h b/source/engine/script.h index a8d46c7..3bbc8a5 100644 --- a/source/engine/script.h +++ b/source/engine/script.h @@ -20,13 +20,10 @@ void out_memusage(const char *f); void js_stacktrace(); void script_evalf(const char *format, ...); -JSValue eval_script_env(const char *file, JSValue env, const char *script); +JSValue script_eval(const char *file, const char *script); void script_call_sym(JSValue sym, int argc, JSValue *argv); void script_gc(); -JSValue script_run_bytecode(uint8_t *code, size_t len); -uint8_t *script_compile(const char *file, size_t *len); - #endif diff --git a/source/engine/yugine.c b/source/engine/yugine.c index e6430c0..7f43949 100644 --- a/source/engine/yugine.c +++ b/source/engine/yugine.c @@ -58,6 +58,7 @@ static JSValue c_process_fn; void c_init() { mainwin.start = 1; window_resize(sapp_width(), sapp_height()); + phys2d_init(); render_init(); set_icon("icons/moon.gif"); particle_init(); @@ -201,7 +202,7 @@ int main(int argc, char **argv) { signal(SIGABRT, seghandle); signal(SIGFPE, seghandle); #endif - phys2d_init(); + resources_init(); stm_setup(); /* time */