'use' now how to load extra programs; cached

This commit is contained in:
John Alanbrook 2024-03-21 11:33:36 -05:00
parent 51f3b5abeb
commit f5d610cbed
11 changed files with 115 additions and 196 deletions

View file

@ -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);

View file

@ -590,10 +590,8 @@ 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);

View file

@ -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";

View file

@ -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,37 +96,30 @@ console.doc = {
globalThis.global = globalThis;
function use(file)
{
if (use.files[file]) return use.files[file];
console.info(`running ${file}`);
var c = io.slurp(file);
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);
}
function eval_env(script, env, file)
function use(file, env, script)
{
file = Resources.find_script(file);
console.info(`loading up ${file}`);
var st = profile.now();
env ??= {};
file ??= "SCRIPT";
console.spam(`eval ${file}`);
script = `(function() { ${script}; }).call(this);\n`;
return os.eval_env(file,script,env);
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;
}
use.cache = {};
global.check_registers = function(obj)
{
if (typeof obj.update === 'function')
@ -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];

View file

@ -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() {
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 }

View file

@ -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 ...");

View file

@ -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);
}

View file

@ -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);

View file

@ -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) {

View file

@ -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

View file

@ -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 */