Compare commits

..

2 commits

Author SHA1 Message Date
John Alanbrook 570c12e3db Add many C based math and statistic functions 2024-08-02 21:52:50 -04:00
John Alanbrook 05bc965d10 update quickjs 2024-07-25 22:07:22 -05:00
22 changed files with 1399 additions and 851 deletions

View file

@ -512,7 +512,7 @@ Object.copy = function(proto, ...objs)
return c;
}
/* OBJECT DEFININTioNS */
/* OBJECT DEFININTIONS */
Object.defHidden = function(obj, prop)
{
Object.defineProperty(obj, prop, {enumerable:false, writable:true});
@ -657,19 +657,6 @@ Object.defineProperty(Object.prototype, 'push', {
}
});
Object.defineProperty(Object.prototype, 'findIndex', {
value: function(x) {
var i = 0;
for (var key in this) {
if (this[key] === x) return i;
i++;
}
return -1;
}
});
/* STRING DEFS */
Object.defineProperty(String.prototype, 'next', {
@ -763,12 +750,6 @@ Object.defineProperty(String.prototype, 'up_path', {
}
});
Object.defineProperty(String.prototype, 'resolve', {
value: function(path) {
},
});
Object.defineProperty(String.prototype, 'fromlast', {
value: function(val) {
var idx = this.lastIndexOf(val);
@ -836,23 +817,7 @@ Object.defineProperty(String.prototype, 'updir', {
Object.defineProperty(String.prototype, 'trimchr', {
value: function(chars) {
var start = this.length;
var end = 0;
for (var i = 0; i < this.length; i++) {
if (!chars.includes(this[i])) {
start = i;
break;
}
}
for (var i = this.length-1; i >= 0; i--) {
if (!chars.includes(this[i])) {
end = i+1;
break;
}
}
return this.substring(start,end);
return vector.trimchr(this, chars);
}
});
@ -860,11 +825,6 @@ Object.defineProperty(String.prototype, 'uc', { value: function() { return this.
Object.defineProperty(String.prototype, 'lc', {value:function() { return this.toLowerCase(); }});
/* ARRAY DEFS */
Object.defineProperty(Array.prototype, 'aspect', {
value: function() {
return this.x/this.y;
}
});
Object.defineProperty(Array.prototype, 'copy', {
value: function() {
var c = [];
@ -1015,13 +975,6 @@ swizz.forEach(function(x) {
};
make_swizz();
Object.defineProperty(Array.prototype, 'add', {
value: function(b) {
var c = [];
for (var i = 0; i < this.length; i++) { c[i] = this[i] + b[i]; }
return c;
}});
Object.defineProperty(Array.prototype, 'normalized', {
value: function() {
var c = this.slice();
@ -1056,13 +1009,6 @@ Object.defineProperty(Array.prototype, 'doubleup', {
}
});
Object.defineProperty(Array.prototype, 'sub', {
value: function(b) {
var c = [];
for (var i = 0; i < this.length; i++) { c[i] = this[i] - b[i]; }
return c;
}});
Object.defineProperty(Array.prototype, 'mult', {
value: function(arr) {
var c = [];
@ -1076,16 +1022,6 @@ Object.defineProperty(Array.prototype, 'apply', {
}
});
Object.defineProperty(Array.prototype, 'scale', {
value: function(s) {
if (Array.isArray(s)) {
var c = this.slice();
c.forEach(function(x,i) { c[i] = x * s[i]; });
return c;
}
return this.map(function(x) { return x*s; });
}});
Object.defineProperty(Array.prototype, 'sorted', {
value: function() {
return this.toSorted();
@ -1119,7 +1055,6 @@ Object.defineProperty(Array.prototype, 'mapvec', {
return this.map((x,i) => fn(x,b[i]));
}
});
Object.defineProperty(Array.prototype, 'remove', {
value: function(b) {
@ -1257,19 +1192,23 @@ Object.defineProperty(Array.prototype, 'mirrored', {
}
});
Object.defineProperty(Array.prototype, 'lerp', {
value: function(to, t) {
var c = [];
this.forEach(function(x,i) {
c[i] = (to[i] - x) * t + x;
});
return c;
}
});
Math.lerp = vector.lerp;
Math.gcd = vector.gcd;
Math.lcm = vector.lcm;
Math.sum = vector.sum;
Math.mean = vector.mean;
Math.sigma = vector.sigma;
Math.median = vector.median;
Math.lerp = function(s,f,t) { return (f-s)*t + s; };
Math.gcd = function(a,b) { return b === 0 ? a : gcd(b,a%b); }
Math.lcm = function(a,b) { return (a*b)/gcd(a,b); }
Math.variance = function(series) {
var mean = Math.mean(series);
var vnce = 0;
for (var i = 0; i < series.length; i++)
vnce += Math.pow(series[i]-mean, 2);
return vnce/(series.length);
}
Math.ci = function(series) { return 3*Math.sigma(series)/Math.sqrt(series.length); }
Math.grab_from_points = function(pos, points, slop) {
var shortest = slop;
@ -1313,22 +1252,18 @@ Object.defineProperty(Object.prototype, 'lerp',{
return obj;
}});
/* MATH EXTENSioNS */
/* MATH EXTENSIONS */
Object.defineProperty(Number.prototype, 'lerp', {
value: function(to, t) {
var s = this;
return (to - this) * t + this;
}
value: function(to, t) { return Math.lerp(this, to, t); }
});
Object.defineProperty(Number.prototype, 'clamp', {
value: function(from,to) {
return Math.clamp(this,from,to);
}
value: function(from,to) { return Math.clamp(this,from,to); }
});
Math.clamp = function (x, l, h) { return x > h ? h : x < l ? l : x; }
Math.clamp = vector.clamp;
Math.random_range = function(min,max) { return Math.random() * (max-min) + min; };
Math.random_range = vector.random_range;
Math.rand_int = function(max) { return Math.floor(Math.random()*max); };
Math.snap = function(val, grid) {
@ -1340,33 +1275,17 @@ Math.snap = function(val, grid) {
return d+i;
}
Math.angledist = function (a1, a2) {
a1 = a1%1;
a2 = a2%1;
var dist = a2 - a1;
if (dist == 0) return dist;
if (dist > 0) {
if (dist > 0.5) return dist-1;
return dist;
}
if (dist < -0.5) return dist+1;
return dist;
};
Math.angledist = vector.angledist;
Math.angledist.doc = "Find the shortest angle between two angles.";
Math.TAU = Math.PI*2;
Math.deg2rad = function(deg) { return deg * 0.0174533; };
Math.rad2deg = function(rad) { return rad / 0.0174533; };
Math.deg2rad = function(x) { return x; };
Math.rad2deg = function(x) { return x; };
Math.turn2rad = function(x) { return x*Math.TAU; };
Math.rad2turn = function(x) { return x/Math.TAU; };
Math.turn2deg = function(x) { return x*360; };
Math.deg2turn = function(x) { return x/360; };
Math.randomint = function(max) { return Math.clamp(Math.floor(Math.random() * max), 0, max-1); };
Math.variate = function(n, pct) { return n + (Math.random_range(-pct,pct)*n); }
Math.variate = vector.variate;
/* BOUNDINGBOXES */
var bbox = {};
@ -1501,38 +1420,16 @@ bbox.fromobjs = function(objs)
var Vector = {};
Vector.length = function(v) { return Math.hypot(...v); }
Vector.norm = function(v) {
var len = Vector.length(v);
if (!len) return [0,0];
return [v.x/len, v.y/len];
}
Vector.project = function(a, b) { return vector.project(a,b); }
Vector.dot = function(a, b) { return vector.dot(a,b); },
Vector.norm = vector.norm;
Vector.project = vector.project;
Vector.dot = vector.dot;
Vector.random = function() {
var vec = [Math.random()-0.5, Math.random()-0.5];
return Vector.norm(vec);
}
Vector.midpoint = function(a,b) { return [(a.x+b.x)/2, (a.y+b.y)/2]; }
Vector.distance = function(a,b) { return Math.hypot(b.x-a.x, b.y-a.y); }
Vector.angle_between = function(a,b)
{
var dot = Vector.dot(a,b);
var am = Vector.length(a);
var bm = Vector.length(b);
var cos_a = dot / (am*bm);
var angle = Math.acos(cos_a);
return Math.rad2turn(angle);
}
Vector.angle = function(v) { return Math.rad2turn(Math.atan2(v.y, v.x)); }
Vector.rotate = function(v,angle) {
var r = Vector.length(v);
angle += Vector.angle(v);
angle = Math.turn2rad(angle);
return [r*Math.cos(angle), r*Math.sin(angle)];
}
Vector.angle_between = vector.angle_between;
Vector.rotate = vector.rotate;
Vector.equal = function(v1, v2, tol) {
if (!tol)

View file

@ -17,20 +17,17 @@ var fullrect = [0,0,1,1];
var sprite_addbucket = function(sprite)
{
return;
var pp = sprite.gameobject.drawlayer.toString();
sprite_buckets[pp] ??= {};
sprite_buckets[pp][sprite.path] ??= {};
sprite_buckets[pp][sprite.path][sprite.guid] = sprite;
var layer = sprite.gameobject.drawlayer;
sprite_buckets[layer] ??= {};
sprite_buckets[layer][sprite.path] ??= {};
sprite_buckets[layer][sprite.path][sprite.guid] = sprite;
}
var sprite_rmbucket = function(sprite)
{
return;
var pp = sprite.gameobject.drawlayer.toString();
if (!sprite_buckets[pp]) return;
if (!sprite_buckets[pp][sprite.path]) return;
delete sprite_buckets[pp][sprite.path][sprite.guid];
for (var layer of Object.values(sprite_buckets))
for (var path of Object.values(layer))
delete path[sprite.guid];
}
var sprite = {
@ -59,6 +56,7 @@ var sprite = {
//self.path = playing.path;
self.frame = playing.frames[f].rect;
self.rect = [self.frame.x, self.frame.y, self.frame.w, self.frame.h];
self.update_dimensions();
f = (f+1)%playing.frames.length;
if (f === 0) {
self.anim_done?.();
@ -88,6 +86,8 @@ var sprite = {
this.rect = fullrect;
var anim = SpriteAnim.make(p);
this.update_dimensions();
this.sync();
if (!anim) return;
this.anim = anim;
@ -99,6 +99,7 @@ var sprite = {
return this._p;
},
kill() {
sprite_rmbucket(this);
this.del_anim?.();
this.anim = undefined;
this.gameobject = undefined;
@ -111,7 +112,10 @@ var sprite = {
this.pos = this.pos.scale(x);
},
anchor:[0,0],
sync() { },
sync() {
sprite_rmbucket(this);
sprite_addbucket(this);
},
pick() { return this; },
boundingbox() {
var dim = this.dimensions();
@ -120,17 +124,21 @@ var sprite = {
return bbox.fromcwh(realpos,dim);
},
update_dimensions() {
this._dimensions = [this.texture.width*this.rect[2], this.texture.height*this.rect[3]];
component.sprite_dim_hook?.(this);
},
dimensions() {
var dim = [this.texture.width, this.texture.height];
dim.x *= this.frame.w;
dim.y *= this.frame.h;
return dim;
return this._dimensions;
},
width() { return this.dimensions().x; },
height() { return this.dimensions().y; },
};
globalThis.allsprites = {};
globalThis.sprite_buckets = [];
var sprite_buckets = {};
component.sprite_buckets = function() { return sprite_buckets; }
sprite.doc = {
path: "Path to the texture.",
@ -173,6 +181,7 @@ component.sprite = function(obj) {
sp.guid = prosperon.guid();
allsprites[sp.guid] = sp;
if (component.sprite.make_hook) component.sprite.make_hook(sp);
sprite_addbucket(sp);
return sp;
}

View file

@ -1,5 +1,3 @@
var debug = {};
debug.build = function(fn) { fn(); }
debug.fn_break = function(fn,obj = globalThis) {
@ -211,13 +209,6 @@ debug.api.print_doc = function(name)
return mdoc;
}
debug.kill = function()
{
assert = function() {};
debug.build = function() {};
debug.fn_break = function() {};
}
return {
debug,
Gizmos,

View file

@ -29,7 +29,7 @@ Object.defineProperty(String.prototype, "folder", {
globalThis.Resources = {};
Resources.rm_fn = function(fn, text)
Resources.rm_fn = function rm_fn(fn, text)
{
var reg = new RegExp(fn.source + "\\s*\\(");
var match;
@ -48,7 +48,7 @@ Resources.rm_fn = function(fn, text)
}
Resources.rm_fn.doc = "Remove calls to a given function from a given text script.";
Resources.replpath = function (str, path) {
Resources.replpath = function replpath(str, path) {
if (!str) return str;
if (str[0] === "/") return str.rm(0);
@ -66,19 +66,24 @@ Resources.replpath = function (str, path) {
return str;
};
Resources.replstrs = function (path) {
Resources.replstrs = function replstrs(path) {
if (!path) return;
var script = io.slurp(path);
var regexp = /"[^"\s]*?\.[^"\s]+?"/g;
var stem = path.dir();
// remove console statements
script = Resources.rm_fn(/console\.(spam|info|warn|error)/, script);
script = Resources.rm_fn(/profile\.(cache|frame|endcache|endframe)/, script);
script = Resources.rm_fn(/assert/, script);
//script = script.replace(/console\.(.*?)\(.*?\)/g, '');
//script = script.replace(/assert\(.*?\)/g, '');
if (!console.enabled)
script = Resources.rm_fn(/console\.(spam|info|warn|error)/, script);
if (!profile.enabled)
script = Resources.rm_fn(/profile\.(cache|frame|endcache|endframe)/, script);
if (!debug.enabled) {
script = Resources.rm_fn(/assert/, script);
script = Resources.rm_fn(/debug\.(build|fn_break)/, script);
}
script = script.replace(regexp, function (str) {
var newstr = Resources.replpath(str.trimchr('"'), path);
return `"${newstr}"`;
@ -218,7 +223,7 @@ globalThis.global = globalThis;
var use_cache = {};
globalThis.use = function(file, env = {}, script) {
globalThis.use = function use(file, env = {}, script) {
file = Resources.find_script(file);
profile.cache("USE", file);
@ -233,6 +238,7 @@ globalThis.use = function(file, env = {}, script) {
use_cache[file] = fn;
var ret = fn.call(env);
profile.endcache();
return ret;
}
@ -249,21 +255,36 @@ function stripped_use (file, env = {}, script) {
var fn = os.eval(file, script);
var ret = fn.call(env);
profile.endcache();
return ret;
}
function bare_use(file)
{
var script = io.slurp(file);
if (!script) return;
script = `(function() { var self = this; ${script}; })`;
Object.assign(globalThis, os.eval(file, script).call(globalThis));
}
profile.enabled = false;
globalThis.debug = {};
profile.enabled = true;
console.enabled = true;
debug.enabled = true;
bare_use("scripts/base.js");
bare_use("scripts/profile.js");
prosperon.release = function()
{
profile.enabled = false;
console.enabled = false;
debug.enabled = false;
}
bare_use("preconfig.js");
if (!profile.enabled)
use = stripped_use;

View file

@ -1,5 +1,11 @@
globalThis.entityreport = {};
var timer_update = function(dt)
{
this.fn();
}
function obj_unique_name(name, obj) {
name = name.replaceAll('.', '_');
if (!(name in obj)) return name;
@ -68,7 +74,7 @@ var entity = {
delay(fn, seconds) {
var timers = this.timers;
var stop = function() {
timers.remove(stop);
delete timers[guid];
execute = undefined;
stop = undefined;
rm?.();
@ -91,7 +97,8 @@ var entity = {
}
var rm = Register.update.register(update);
timers.push(stop);
var guid = prosperon.guid();
timers[guid] = (stop);
return stop;
},
@ -146,7 +153,7 @@ var entity = {
ent.components = {};
ent.objects = {};
ent.timers = [];
ent.timers = {};
if (!text)
ent.ur = emptyur;
@ -339,8 +346,8 @@ dup(diff) {
this.__kill = true;
console.spam(`Killing entity of type ${this.ur}`);
for (var t of this.timers) t();
this.timers = [];
this.timers.forEach(x => x());
delete this.timers;
Event.rm_obj(this);
input.do_uncontrol(this);

View file

@ -202,8 +202,6 @@ mum.image = function(path, data = {})
else
data.height = tex.height;
if (!data.width) data.width = tex.width;
if (!data.height) data.height = tex.height;

View file

@ -108,7 +108,7 @@ var make_emitter = function()
var e = Object.create(emitter);
e.ssbo = render.make_textssbo();
e.shape = shape.centered_quad;
e.shader = render.make_shader("shaders/baseparticle.cg");
e.shader = "shaders/baseparticle.cg";
e.dead = [];
return e;
}

View file

@ -1,15 +1,32 @@
var t_units = ["ns", "us", "ms", "s", "m", "h"];
var t_units = ["ns", "us", "ms", "s", "ks", "Ms"];
profile.cpu = function(fn, times = 1, q = "unnamed") {
var start = profile.now();
for (var i = 0; i < times; i++)
fn();
function calc_cpu(fn, times, diff=0)
{
var series = [];
for (var i = 0; i < times; i++) {
var st = profile.now();
fn(i);
series.push(profile.now()-st-diff);
}
return series;
}
function empty_fn() {}
profile.cpu = function profile_cpu(fn, times = 1, q = "unnamed") {
profile.gather_stop();
var empty = calc_cpu(empty_fn, 100000);
var mean = Math.mean(empty);
var series = calc_cpu(fn,times, mean);
var elapsed = profile.now() - start;
var avgt = profile.best_t(elapsed/times);
var elapsed = Math.sum(series);
var avgt = profile.best_t(elapsed/series.length);
var totalt = profile.best_t(elapsed);
say(`profile [${q}]: ${profile.best_t(avgt)} average [${profile.best_t(totalt)} for ${times} loops]`);
say(`profile [${q}]: ${avgt} ± ${profile.best_t(Math.ci(series))} [${totalt} for ${times} loops]`);
start_prof_gather();
}
profile.ms = function(t) { return t/1000000; }
@ -35,27 +52,33 @@ function add_callgraph(fn, line, time) {
var hittar = 500;
var hitpct = 0.2;
var start_gather = profile.now();
function start_prof_gather()
{
profile.gather(hittar, function() {
var time = profile.now()-st;
var err = new Error();
var stack = err.stack.split("\n");
stack = stack.slice(1);
stack = stack.map(x => x.slice(7).split(' '));
var fns = stack.map(x => x[0]).filter(x=>x);
var lines = stack.map(x => x[1]).filter(x => x);
lines = lines.map(x => x.slice(1,x.length-1));
for (var i = 0; i < fns.length; i++)
add_callgraph(fns[i], lines[i], time);
st = profile.now();
profile.gather_rate(Math.variate(hittar,hitpct));
});
}
if (profile.enabled)
profile.gather(hittar, function() {
var time = profile.now()-st;
var err = new Error();
var stack = err.stack.split("\n");
stack = stack.slice(1);
stack = stack.map(x => x.slice(7).split(' '));
var fns = stack.map(x => x[0]).filter(x=>x);
var lines = stack.map(x => x[1]).filter(x => x);
lines = lines.map(x => x.slice(1,x.length-1));
for (var i = 0; i < fns.length; i++)
add_callgraph(fns[i], lines[i], time);
st = profile.now();
profile.gather_rate(Math.variate(hittar,hitpct));
});
start_prof_gather();
var filecache = {};
function get_line(file, line) {
@ -96,10 +119,12 @@ profile.print_cpu_instr = function()
profile.best_t = function (t) {
var qq = 0;
while (t > 1000 && qq < t_units.length-1) {
t /= 1000;
qq++;
}
return `${t.toPrecision(4)} ${t_units[qq]}`;
};
@ -108,28 +133,29 @@ profile.report = function (start, msg = "[undefined report]") { console.info(`${
var profile_frames = {};
var profile_frame_ts = [];
var profile_cframe = profile_frames;
var profile_frame = 0;
profile.frame = function(title)
var pframe = 0;
profile.frame = function profile_frame(title)
{
profile_frame_ts.push(profile_cframe);
profile_cframe[title] ??= {};
profile_cframe = profile_cframe[title];
profile_cframe._times ??= [];
profile_cframe._times[profile_frame] = profile.now();
profile_cframe._times[pframe] ??= 0;
profile_cframe._times[pframe] = profile.now() - profile_cframe._times[pframe];
}
profile.endframe = function()
profile.endframe = function profile_endframe()
{
if (profile_cframe === profile_frames) return;
profile_cframe._times[profile_frame] = profile.now() - profile_cframe._times[profile_frame];
profile_cframe._times[pframe] = profile.now() - profile_cframe._times[pframe];
profile_cframe = profile_frame_ts.pop();
if (profile_cframe === profile_frames) profile_frame++;
if (profile_cframe === profile_frames) pframe++;
}
var print_frame = function(frame, indent, title)
{
var avg = frame._times.reduce((sum, e) => sum += e)/frame._times.length;
say(indent + `${title} ::::: ${profile.best_t(avg)} (${frame._times.length} hits)`);
say(indent + `${title} ::::: ${profile.best_t(Math.mean(frame._times))} ± ${profile.best_t(Math.ci(frame._times))} (${frame._times.length} hits)`);
for (var i in frame) {
if (i === '_times') continue;
@ -149,14 +175,14 @@ var report_cache = {};
var cachest = 0;
var cachegroup;
var cachetitle;
profile.cache = function(group, title)
profile.cache = function profile_cache(group, title)
{
cachest = profile.now();
cachegroup = group;
cachetitle = title;
}
profile.endcache = function(tag = "")
profile.endcache = function profile_endcache(tag = "")
{
addreport(cachegroup, cachetitle + tag, cachest);
}

View file

@ -316,21 +316,23 @@ var Register = {
add_cb(name, e_event = false) {
var n = {};
var fns = [];
var fns = {};
n.register = function (fn, oname) {
if (!(fn instanceof Function)) return;
var guid = prosperon.guid();
var dofn = function(...args) {
profile.cache(name,oname);
var st = profile.now();
fn(...args);
profile.endcache();
profile.endcache();
}
fns.push(dofn);
fns[guid] = dofn;
return function () {
fns.remove(dofn);
delete fns[guid];
};
};

View file

@ -6,24 +6,24 @@ render.doc = {
var cur = {};
render.use_shader = function(shader)
render.use_shader = function use_shader(shader)
{
if (typeof shader === 'string')
shader = render.make_shader(shader);
shader = make_shader(shader);
if (cur.shader === shader) return;
cur.shader = shader;
cur.globals = {};
cur.bind = undefined;
cur.mesh = undefined;
render.setpipeline(shader.pipe);
shader_globals(cur.shader);
}
render.use_mat = function(mat)
render.use_mat = function use_mat(mat)
{
if (!cur.shader) return;
if (cur.mat === mat) return;
render.shader_apply_material(cur.shader, mat, cur.mat);
shader_apply_material(cur.shader, mat, cur.mat);
cur.mat = mat;
@ -38,7 +38,7 @@ render.use_mat = function(mat)
var models_array = [];
render.set_model = function(t)
function set_model(t)
{
if (cur.shader.vs.unimap.model)
render.setunim4(0, cur.shader.vs.unimap.model.slot, t);
@ -96,7 +96,7 @@ var face_map = {
ccw: 1
}
render.poly_prim = function(verts)
render.poly_prim = function poly_prim(verts)
{
var index = [];
if (verts.length < 1) return undefined;
@ -131,31 +131,15 @@ function shader_directive(shader, name, map)
return ff;
}
function global_uni(uni, stage)
{
cur.globals[stage] ??= {};
if (cur.globals[stage][uni.name]) return true;
switch(uni.name) {
case "time":
cur.globals[stage][uni.name]
render.setuniv(stage, uni.slot, profile.secs(profile.now()));
cur.globals[stage][uni.name] = true;
return true;
case "projection":
render.setuniproj(stage, uni.slot);
cur.globals[stage][uni.name] = true;
return true;
case "view":
render.setuniview(stage, uni.slot);
cur.globals[stage][uni.name] = true;
return true;
case "vp":
render.setunivp(stage, uni.slot);
cur.globals[stage][uni.name] = true;
return true;
}
return false;
var uni_globals = {
time(stage, slot) { render.setuniv(stage, slot, profile.secs(profile.now())); },
projection(stage,slot) { render.setuniproj(stage, slot); },
view(stage,slot) { render.setuniview(stage, slot); },
vp(stage,slot) { render.setunivp(stage,slot); },
}
function set_global_uni(uni, stage) {
uni_globals[uni.name]?.(stage, uni.slot);
}
var setcam = render.set_camera;
@ -170,8 +154,14 @@ render.set_camera = function(cam)
}
var shader_cache = {};
function strip_shader_inputs(shader)
{
for (var a of shader.vs.inputs)
a.name = a.name.slice(2);
}
render.make_shader = function(shader)
function make_shader(shader)
{
if (shader_cache[shader]) return shader_cache[shader];
@ -198,6 +188,7 @@ render.make_shader = function(shader)
profile.endcache(" [cached]");
var shaderobj = json.decode(io.slurp(writejson));
var obj = shaderobj[os.sys()];
strip_shader_inputs(obj);
obj.pipe = render.pipeline(obj);
shader_cache[shader] = obj;
return obj;
@ -314,6 +305,7 @@ render.make_shader = function(shader)
profile.endcache();
var obj = compiled[os.sys()];
strip_shader_inputs(obj);
obj.pipe = render.pipeline(obj);
shader_cache[shader] = obj;
@ -326,11 +318,20 @@ var shader_unisize = {
12: render.setuniv3,
16: render.setuniv4
};
function shader_globals(shader)
{
for (var p in shader.vs.unimap)
set_global_uni(shader.vs.unimap[p], 0);
for (var p in shader.fs.unimap)
set_global_uni(shader.fs.unimap[p], 1);
}
render.shader_apply_material = function(shader, material = {}, old = {})
function shader_apply_material(shader, material = {}, old = {})
{
for (var p in shader.vs.unimap) {
if (global_uni(shader.vs.unimap[p], 0)) continue;
if (!(p in material)) continue;
if (material[p] === old[p]) continue;
assert(p in material, `shader ${shader.name} has no uniform for ${p}`);
var s = shader.vs.unimap[p];
@ -338,7 +339,7 @@ render.shader_apply_material = function(shader, material = {}, old = {})
}
for (var p in shader.fs.unimap) {
if (global_uni(shader.fs.unimap[p], 1)) continue;
if (!(p in material)) continue;
if (material[p] === old[p]) continue;
assert(p in material, `shader ${shader.name} has no uniform for ${p}`);
var s = shader.fs.unimap[p];
@ -355,7 +356,7 @@ render.shader_apply_material = function(shader, material = {}, old = {})
render.setuniv2(0, shader.vs.unimap.diffuse_size.slot, [material.diffuse.width, material.diffuse.height]);
}
render.sg_bind = function(mesh, ssbo)
function sg_bind(mesh, ssbo)
{
if (cur.mesh === mesh && cur.bind) {
cur.bind.inst = 1;
@ -371,13 +372,10 @@ render.sg_bind = function(mesh, ssbo)
if (cur.shader.vs.inputs)
for (var a of cur.shader.vs.inputs) {
if (!(a.name in mesh)) {
if (!(a.name.slice(2) in mesh)) {
console.error(`cannot draw shader ${cur.shader.name}; there is no attrib ${a.name} in the given mesh.`);
return undefined;
} else
bind.attrib.push(mesh[a.name.slice(2)]);
console.error(`cannot draw shader ${cur.shader.name}; there is no attrib ${a.name} in the given mesh.`);
return undefined;
} else
bind.attrib.push(mesh[a.name]);
bind.attrib.push(mesh[a.name]);
}
if (cur.shader.indexed) {
@ -448,15 +446,15 @@ var polyssboshader;
var sprite_ssbo;
render.init = function() {
textshader = render.make_shader("shaders/text_base.cg");
render.spriteshader = render.make_shader("shaders/sprite.cg");
spritessboshader = render.make_shader("shaders/sprite_ssbo.cg");
render.postshader = render.make_shader("shaders/simplepost.cg");
slice9shader = render.make_shader("shaders/9slice.cg");
circleshader = render.make_shader("shaders/circle.cg");
polyshader = render.make_shader("shaders/poly.cg");
parshader = render.make_shader("shaders/baseparticle.cg");
polyssboshader = render.make_shader("shaders/poly_ssbo.cg");
textshader = make_shader("shaders/text_base.cg");
render.spriteshader = make_shader("shaders/sprite.cg");
spritessboshader = make_shader("shaders/sprite_ssbo.cg");
render.postshader = make_shader("shaders/simplepost.cg");
slice9shader = make_shader("shaders/9slice.cg");
circleshader = make_shader("shaders/circle.cg");
polyshader = make_shader("shaders/poly.cg");
parshader = make_shader("shaders/baseparticle.cg");
polyssboshader = make_shader("shaders/poly_ssbo.cg");
textssbo = render.make_textssbo();
poly_ssbo = render.make_textssbo();
sprite_ssbo = render.make_textssbo();
@ -493,47 +491,55 @@ render.init = function() {
}
}
render.sprites = function(gridsize = 1)
render.sprites = function render_sprites(gridsize = 1)
{
/*
profile.frame("bucketing");
var sps = Object.values(allsprites);
var sprite_buckets = {};
var buckets = [];
for (var i = 0; i <= 20; i++)
buckets[i] = {};
for (var sprite of sps) {
var pp = sprite.gameobject.drawlayer;
sprite_buckets[pp] ??= {};
sprite_buckets[pp][sprite.path] ??= {};
sprite_buckets[pp][sprite.path][sprite.guid] = sprite;
render.sprite_hook?.(sprite);
var layer = sprite.gameobject.drawlayer+10;
if (buckets[layer][sprite.path])
buckets[layer][sprite.path].push(sprite);
else
buckets[layer][sprite.path] = [sprite];
}
profile.endframe();
*/
profile.frame("sorting");
var sprite_buckets = component.sprite_buckets();
var buckets = Object.entries(sprite_buckets).sort((a,b) => {
var na = Number(a[0]);
var ba = Number(b[0]);
if (na < ba) return -1;
if (na === ba) return 0;
var nb = Number(b[0]);
if (na < nb) return -1;
return 1;
});
profile.endframe();
profile.frame("drawing");
render.use_shader(spritessboshader);
for (var bucket of buckets) {
for (var img of Object.values(bucket[1])) {
for (var layer of buckets) {
for (var img of Object.values(layer[1])) {
var sparray = Object.values(img);
if (sparray.length === 0) continue;
var ss = sparray[0];
render.use_mat(ss);
render.make_sprite_ssbo(Object.values(sparray), sprite_ssbo);
render.make_sprite_ssbo(sparray, sprite_ssbo);
render.draw(shape.quad, sprite_ssbo, sparray.length);
}
}
profile.endframe();
}
render.circle = function(pos, radius, color) {
check_flush();
render.circle = function render_circle(pos, radius, color) {
flush();
var mat = {
radius: radius,
coord: pos,
@ -544,56 +550,71 @@ render.circle = function(pos, radius, color) {
render.draw(shape.quad);
}
render.poly = function(points, color, transform) {
render.poly = function render_poly(points, color, transform) {
var buffer = render.poly_prim(points);
var mat = { shade: color};
render.use_shader(polyshader);
render.set_model(transform);
set_model(transform);
render.use_mat(mat);
render.draw(buffer);
}
var nextflush = undefined;
var check_flush = function(flush_fn)
function flush()
{
nextflush?.();
nextflush = undefined;
}
function check_flush(flush_fn)
{
if (!flush_fn) {
if (!nextflush) return;
nextflush();
nextflush = undefined;
}
if (!nextflush)
nextflush = flush_fn;
else if (nextflush !== flush_fn) {
nextflush();
nextflush = flush_fn;
}
nextflush();
nextflush = flush_fn;
}
}
var poly_cache = [];
var poly_idx = 0;
var poly_ssbo;
render.flush_poly = function()
function poly_e()
{
if (poly_cache.length === 0) return;
render.use_shader(polyssboshader);
render.use_mat({});
render.make_particle_ssbo(poly_cache, poly_ssbo);
render.draw(shape.centered_quad, poly_ssbo, poly_cache.length);
poly_cache = [];
var e;
poly_idx++;
if (poly_idx > poly_cache.length) {
e = {
transform:os.make_transform(),
color: Color.white
};
poly_cache.push(e);
return e;
}
var e = poly_cache[poly_idx-1];
e.transform.unit();
return e;
}
render.line = function(points, color = Color.white, thickness = 1) {
var transform = os.make_transform();
var dist = Vector.distance(points[0],points[1]);
transform.move(Vector.midpoint(points[0],points[1]));
transform.rotate([0,0,-1], Vector.angle([points[1].x-points[0].x, points[1].y-points[0].y]));
transform.scale = [dist, thickness, 1];
poly_cache.push({
transform:transform,
color:color
});
check_flush(render.flush_poly);
function flush_poly()
{
if (poly_idx === 0) return;
render.use_shader(polyssboshader);
render.use_mat({});
render.make_particle_ssbo(poly_cache.slice(0,poly_idx), poly_ssbo);
render.draw(shape.centered_quad, poly_ssbo, poly_cache.length);
poly_idx = 0;
}
render.line = function render_line(points, color = Color.white, thickness = 1) {
var poly = poly_e();
var dist = vector.distance(points[0],points[1]);
poly.transform.move(vector.midpoint(points[0],points[1]));
poly.transform.rotate([0,0,-1], vector.angle([points[1].x-points[0].x, points[1].y-points[0].y]));
poly.transform.scale = [dist, thickness, 1];
poly.color = color;
check_flush(flush_poly);
}
/* All draw in screen space */
@ -601,7 +622,7 @@ render.point = function(pos,size,color = Color.blue) {
render.circle(pos,size,size,color);
};
render.cross = function(pos, size, color = Color.red, thickness = 1) {
render.cross = function render_cross(pos, size, color = Color.red, thickness = 1) {
var a = [
pos.add([0,size]),
pos.add([0,-size])
@ -614,7 +635,7 @@ render.cross = function(pos, size, color = Color.red, thickness = 1) {
render.line(b,color,thickness);
};
render.arrow = function(start, end, color = Color.red, wingspan = 4, wingangle = 10) {
render.arrow = function render_arrow(start, end, color = Color.red, wingspan = 4, wingangle = 10) {
var dir = end.sub(start).normalized();
var wing1 = [
Vector.rotate(dir, wingangle).scale(wingspan).add(end),
@ -629,39 +650,34 @@ render.arrow = function(start, end, color = Color.red, wingspan = 4, wingangle =
render.line(wing2,color);
};
render.coordinate = function(pos, size, color) {
render.coordinate = function render_coordinate(pos, size, color) {
render.text(JSON.stringify(pos.map(p=>Math.round(p))), pos, size, color);
render.point(pos, 2, color);
}
render.boundingbox = function(bb, color = Color.white) {
render.boundingbox = function render_boundingbox(bb, color = Color.white) {
render.line(bbox.topoints(bb).wrapped(1), color);
}
render.rectangle = function(lowerleft, upperright, color) {
render.rectangle = function render_rectangle(lowerleft, upperright, color) {
var transform = os.make_transform();
var wh = [upperright.x-lowerleft.x, upperright.y-lowerleft.y];
transform.move(Vector.midpoint(lowerleft,upperright));
transform.scale = [wh.x,wh.y,1];
poly_cache.push({
transform:transform,
color:color
});
check_flush(render.flush_poly);
var poly = poly_e();
poly.transform.move(vector.midpoint(lowerleft,upperright));
poly.transform.scale = [wh.x,wh.y,1];
poly.color = color;
check_flush(flush_poly);
};
render.box = function(pos, wh, color = Color.white) {
var transform = os.make_transform();
transform.move(pos);
transform.scale = [wh.x,wh.y,1];
poly_cache.push({
transform:transform,
color:color
});
check_flush(render.flush_poly);
render.box = function render_box(pos, wh, color = Color.white) {
var poly = poly_e();
poly.transform.move(pos);
poly.transform.scale = [wh.x,wh.y,1];
poly.color = color;
check_flush(flush_poly);
};
render.window = function(pos, wh, color) { render.box(pos.add(wh.scale(0.5)),wh,color); };
render.window = function render_window(pos, wh, color) { render.box(pos.add(wh.scale(0.5)),wh,color); };
render.text_bb = function(str, size = 1, wrap = -1, pos = [0,0])
{
@ -693,12 +709,12 @@ render.text = function(str, pos, size = 1, color = Color.white, wrap = -1, ancho
};
render.image = function(tex, pos, scale = [tex.width, tex.height], rotation = 0, color = Color.white) {
check_flush();
flush();
var t = os.make_transform();
t.pos = pos;
t.scale = [scale.x/tex.width,scale.y/tex.height,1];
render.use_shader(render.spriteshader);
render.set_model(t);
set_model(t);
render.use_mat({
shade: color,
diffuse: tex,
@ -729,7 +745,7 @@ render.slice9 = function(tex, pos, bb, scale = [tex.width,tex.height], color = C
border = [bb.l/tex.width, bb.b/tex.height, bb.r/tex.width, bb.t/tex.height];
render.use_shader(slice9shader);
render.set_model(t);
set_model(t);
render.use_mat({
shade: color,
diffuse:tex,
@ -768,16 +784,16 @@ render.flush_text = function()
render.draw(shape.quad, textssbo, amt);
}
render.fontcache = {};
var fontcache = {};
render.set_font = function(path, size) {
var fontstr = `${path}-${size}`;
if (render.font && render.fontcache[fontstr] === render.font) return;
if (!render.fontcache[fontstr]) render.fontcache[fontstr] = os.make_font(path, size);
if (render.font && fontcache[fontstr] === render.font) return;
if (!fontcache[fontstr]) fontcache[fontstr] = os.make_font(path, size);
render.flush_text();
gui.font_set(render.fontcache[fontstr]);
render.font = render.fontcache[fontstr];
gui.font_set(fontcache[fontstr]);
render.font = fontcache[fontstr];
}
render.doc = "Draw shapes in screen space.";
@ -786,15 +802,14 @@ render.cross.doc = "Draw a cross centered at pos, with arm length size.";
render.arrow.doc = "Draw an arrow from start to end, with wings of length wingspan at angle wingangle.";
render.rectangle.doc = "Draw a rectangle, with its corners at lowerleft and upperright.";
render.draw = function(mesh, ssbo, inst = 1)
render.draw = function render_draw(mesh, ssbo, inst = 1)
{
render.sg_bind(mesh, ssbo);
sg_bind(mesh, ssbo);
profile.frame("gpu");
render.spdraw(cur.bind.count, inst);
profile.endframe();
}
// Returns an array in the form of [left, bottom, right, top] in pixels of the camera to render to
// Camera viewport is [left,bottom,right,top] in relative values
function camviewport()
@ -947,7 +962,7 @@ prosperon.render = function()
render.commit();
}
prosperon.process = function() {
prosperon.process = function process() {
profile.frame("frame");
var dt = profile.secs(profile.now()) - frame_t;
frame_t = profile.secs(profile.now());

View file

@ -3,6 +3,7 @@
const HMM_Vec2 v2zero = {0,0};
const HMM_Vec2 v2one = {1,1};
const HMM_Vec3 v3zero = {0,0,0};
const HMM_Vec3 v3one = {1,1,1};
const HMM_Vec4 v4zero = {0,0,0,0};
const HMM_Vec3 vX = {1.0,0.0,0.0};
@ -17,7 +18,7 @@ const HMM_Vec3 vLEFT = {-1,0,0};
const HMM_Vec3 vRIGHT = {1,0,0};
const HMM_Mat4 MAT1 = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
const HMM_Quat QUAT1 = {1,0,0,0};
const HMM_Quat QUAT1 = {0,0,0,1};
/*
* Angle unit conversion functions
@ -262,14 +263,9 @@ HMM_Vec4 HMM_SubV4(HMM_Vec4 Left, HMM_Vec4 Right) {
return Result;
}
HMM_Vec2 HMM_ScaleV2(HMM_Vec2 v, double s)
{
return HMM_V2(v.X*s, v.Y*s);
}
HMM_Vec3 HMM_ScaleV3(HMM_Vec3 v, double s)
HMM_Vec2 HMM_ScaleV2(HMM_Vec2 v, double s)
{
return HMM_V3(v.x*s,v.y*s,v.z*s);
return HMM_V2(v.X*s, v.Y*s);
}
HMM_Vec2 HMM_MulV2(HMM_Vec2 Left, HMM_Vec2 Right) {
@ -529,7 +525,6 @@ float HMM_AngleV4(HMM_Vec4 a, HMM_Vec4 b)
}
HMM_Vec2 HMM_NormV2(HMM_Vec2 A) {
// HMM_MulV2F(A, 1.0/HMM_LenV2(A)+FLOAT_MIN);
return HMM_MulV2F(A, HMM_InvSqrtF(HMM_DotV2(A, A)));
}

View file

@ -416,6 +416,7 @@ typedef union HMM_Mat4 {
extern const HMM_Vec2 v2zero;
extern const HMM_Vec2 v2one;
extern const HMM_Vec3 v3zero;
extern const HMM_Vec3 v3one;
extern const HMM_Vec4 v4zero;
typedef signed int HMM_Bool;
@ -477,7 +478,6 @@ HMM_Vec4 HMM_AddV4(HMM_Vec4 Left, HMM_Vec4 Right);
HMM_Vec2 HMM_SubV2(HMM_Vec2 Left, HMM_Vec2 Right);
HMM_Vec3 HMM_SubV3(HMM_Vec3 Left, HMM_Vec3 Right);
HMM_Vec4 HMM_SubV4(HMM_Vec4 Left, HMM_Vec4 Right);
HMM_Vec3 HMM_ScaleV3(HMM_Vec3 v, double s);
HMM_Vec2 HMM_MulV2(HMM_Vec2 Left, HMM_Vec2 Right);
HMM_Vec2 HMM_MulV2F(HMM_Vec2 Left, float Right);
HMM_Vec3 HMM_MulV3(HMM_Vec3 Left, HMM_Vec3 Right);

View file

@ -1142,6 +1142,25 @@ JSValue js_vector_dot(JSContext *js, JSValue self, int argc, JSValue *argv) { re
JSC_CCALL(vector_project, return vec22js(HMM_ProjV2(js2vec2(argv[0]), js2vec2(argv[1]))))
JSC_CCALL(vector_midpoint,
HMM_Vec2 a = js2vec2(argv[0]);
HMM_Vec2 b = js2vec2(argv[1]);
// HMM_Vec2 c = HMM_AddV2(a,b);
// c = HMM_DivV2F(c, 2);
return vec22js((HMM_Vec2){(a.x+b.x)/2, (a.y+b.y)/2});
)
JSC_CCALL(vector_distance,
HMM_Vec2 a = js2vec2(argv[0]);
HMM_Vec2 b = js2vec2(argv[1]);
return number2js(HMM_DistV2(a,b));
)
JSC_CCALL(vector_angle,
HMM_Vec2 a = js2vec2(argv[0]);
return angle2js(atan2(a.y,a.x));
)
/* Given a series of points p, computes a new series with them expanded on either side by d */
HMM_Vec2 *inflatepoints(HMM_Vec2 *p, float d, int n)
{
@ -1204,11 +1223,251 @@ JSC_CCALL(vector_rotate,
return vec22js(vec);
)
JSC_CCALL(vector_add,
HMM_Vec4 a = js2vec4(argv[0]);
HMM_Vec4 b = js2vec4(argv[1]);
HMM_Vec4 c = HMM_AddV4(a,b);
return vec42js(c);
)
JSC_CCALL(vector_norm,
int len = js_arrlen(argv[0]);
switch(len) {
case 2: return vec22js(HMM_NormV2(js2vec2(argv[0])));
case 3: return vec32js(HMM_NormV3(js2vec3(argv[0])));
case 4: return vec42js(HMM_NormV4(js2vec4(argv[0])));
}
return argv[0];
)
JSC_CCALL(vector_angle_between,
int len = js_arrlen(argv[0]);
switch(len) {
case 2: return angle2js(HMM_AngleV2(js2vec2(argv[0]), js2vec2(argv[1])));
case 3: return angle2js(HMM_AngleV3(js2vec3(argv[0]), js2vec3(argv[1])));
case 4: return angle2js(HMM_AngleV4(js2vec4(argv[0]), js2vec4(argv[1])));
}
return angle2js(0);
)
JSC_CCALL(vector_lerp,
double s = js2number(argv[0]);
double f = js2number(argv[1]);
double t = js2number(argv[2]);
return number2js((f-s)*t+s);
)
int gcd(int a, int b) {
if (b == 0)
return a;
return gcd(b, a % b);
}
JSC_CCALL(vector_gcd,
return number2js(gcd(js2number(argv[0]), js2number(argv[1])));
)
JSC_CCALL(vector_lcm,
double a = js2number(argv[0]);
double b = js2number(argv[1]);
return number2js((a*b)/gcd(a,b));
)
JSC_CCALL(vector_clamp,
double x = js2number(argv[0]);
double l = js2number(argv[1]);
double h = js2number(argv[2]);
return number2js(x > h ? h : x < l ? l : x);
)
JSC_SSCALL(vector_trimchr,
int len = js2number(js_getpropstr(argv[0], "length"));
char *start = str;
while (*start == *str2)
start++;
char *end = str + len-1;
while(*end == *str2)
end--;
ret = JS_NewStringLen(js, start, end-start+1);
)
JSC_CCALL(vector_angledist,
double a1 = js2number(argv[0]);
double a2 = js2number(argv[1]);
a1 = fmod(a1,1);
a2 = fmod(a2,1);
double dist = a2-a1;
if (dist == 0) return number2js(dist);
if (dist > 0) {
if (dist > 0.5) return number2js(dist-1);
return number2js(dist);
}
if (dist < -0.5) return number2js(dist+1);
return number2js(dist);
)
double r2()
{
return (double)rand() / (double)RAND_MAX ;
}
double rand_range(double min, double max) {
return r2() * (max-min) + min;
}
JSC_CCALL(vector_variate,
double n = js2number(argv[0]);
double pct = js2number(argv[1]);
return number2js(n + (rand_range(-pct,pct)*n));
)
JSC_CCALL(vector_random_range, return number2js(rand_range(js2number(argv[0]), js2number(argv[1]))))
JSC_CCALL(vector_mean,
double len = js_arrlen(argv[0]);
double sum;
for (int i = 0; i < len; i++)
sum += js2number(js_getpropidx(argv[0], i));
return number2js(sum/len);
)
JSC_CCALL(vector_sum,
double sum;
int len = js_arrlen(argv[0]);
for (int i = 0; i < len; i++)
sum += js2number(js_getpropidx(argv[0], i));
return number2js(sum);
)
JSC_CCALL(vector_sigma,
int len = js_arrlen(argv[0]);
double sum;
for (int i = 0; i < len; i++)
sum += js2number(js_getpropidx(argv[0], i));
double mean = sum/(double)len;
double sq_diff = 0;
for (int i = 0; i < len; i++) {
double x = js2number(js_getpropidx(argv[0],i));
sq_diff += pow(x-mean, 2);
}
double variance = sq_diff/((double)len);
return number2js(sqrt(variance));
)
JSC_CCALL(vector_median,
int len = js_arrlen(argv[0]);
double arr[len];
double temp;
for (int i = 0; i < len; i++)
arr[i] = js2number(js_getpropidx(argv[0], i));
for (int i = 0; i < len-1; i++) {
for (int j = i+1; j < len; j++) {
if (arr[i] > arr[j]) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
if (len % 2 == 0) return number2js((arr[len/2-1] + arr[len/2])/2.0);
return number2js(arr[len/2]);
)
static const JSCFunctionListEntry js_vector_funcs[] = {
MIST_FUNC_DEF(vector,dot,2),
MIST_FUNC_DEF(vector,project,2),
MIST_FUNC_DEF(vector, dot,2),
MIST_FUNC_DEF(vector, project,2),
MIST_FUNC_DEF(vector, inflate, 2),
MIST_FUNC_DEF(vector, rotate, 2)
MIST_FUNC_DEF(vector, rotate, 2),
MIST_FUNC_DEF(vector, add, 2),
MIST_FUNC_DEF(vector, midpoint, 2),
MIST_FUNC_DEF(vector, distance, 2),
MIST_FUNC_DEF(vector, angle, 1),
MIST_FUNC_DEF(vector, norm, 1),
MIST_FUNC_DEF(vector, angle_between, 2),
MIST_FUNC_DEF(vector, lerp, 3),
MIST_FUNC_DEF(vector, gcd, 2),
MIST_FUNC_DEF(vector, lcm, 2),
MIST_FUNC_DEF(vector, clamp, 3),
MIST_FUNC_DEF(vector, trimchr, 2),
MIST_FUNC_DEF(vector, angledist, 2),
MIST_FUNC_DEF(vector, variate, 2),
MIST_FUNC_DEF(vector, random_range, 2),
MIST_FUNC_DEF(vector, mean, 1),
MIST_FUNC_DEF(vector, sum, 1),
MIST_FUNC_DEF(vector, sigma, 1),
MIST_FUNC_DEF(vector, median, 1)
};
#define JS_HMM_FN(OP, HMM, SIGN) \
JSC_CCALL(array_##OP, \
int len = js_arrlen(self); \
if (!JS_IsArray(js, argv[0])) { \
double n = js2number(argv[0]); \
JSValue arr = JS_NewArray(js); \
for (int i = 0; i < len; i++) \
js_setprop_num(arr, i, number2js(js2number(js_getpropidx(self,i)) SIGN n)); \
return arr; \
} \
switch(len) { \
case 2: \
return vec22js(HMM_##HMM##V2(js2vec2(self), js2vec2(argv[0]))); \
case 3: \
return vec32js(HMM_##HMM##V3(js2vec3(self), js2vec3(argv[0]))); \
case 4: \
return vec42js(HMM_##HMM##V4(js2vec4(self), js2vec4(argv[0]))); \
} \
\
JSValue arr = JS_NewArray(js); \
for (int i = 0; i < len; i++) { \
double a = js2number(js_getpropidx(self,i)); \
double b = js2number(js_getpropidx(argv[0],i)); \
js_setprop_num(arr, i, number2js(a SIGN b)); \
} \
return arr; \
) \
JS_HMM_FN(add, Add, +)
JS_HMM_FN(sub, Sub, -)
JS_HMM_FN(div, Div, /)
JS_HMM_FN(scale, Mul, *)
JSC_CCALL(array_lerp,
int len = js_arrlen(self);
JSValue arr = JS_NewArray(js);
double t = js2number(argv[1]);
for (int i = 0; i < len; i++) {
double from = js2number(js_getpropidx(self, i));
double to = js2number(js_getpropidx(argv[0], i));
js_setprop_num(arr, i, number2js((to - from) * t + from));
}
return arr;
)
static const JSCFunctionListEntry js_array_funcs[] = {
MIST_FUNC_DEF(array, add, 1),
MIST_FUNC_DEF(array, sub, 1),
MIST_FUNC_DEF(array, div,1),
MIST_FUNC_DEF(array, scale, 1),
MIST_FUNC_DEF(array, lerp, 2)
};
JSC_CCALL(game_engine_start, engine_start(argv[0],argv[1], js2number(argv[2]), js2number(argv[3])))
@ -1234,13 +1493,18 @@ static const JSCFunctionListEntry js_input_funcs[] = {
JSC_CCALL(prosperon_phys2d_step, phys2d_update(js2number(argv[0])))
JSC_CCALL(prosperon_window_render, openglRender(js2vec2(argv[0])))
JSC_CCALL(prosperon_guid,
uint8_t bytes[16];
for (int i = 0; i < 16; i++) bytes[i] = rand()%256;
char uuid[37];
snprintf(uuid, 37, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]);
return str2js(uuid);
int bits = 32;
char guid[33];
for (int i = 0; i < 4; i++) {
int r = rand();
for (int j = 0; j < 8; j++) {
guid[i*8+j] = "0123456789abcdef"[r%16];
r /= 16;
}
}
guid[32] = 0;
return str2js(guid);
)
static const JSCFunctionListEntry js_prosperon_funcs[] = {
@ -1320,7 +1584,7 @@ int iiihandle(JSRuntime *rt, void *data)
JSC_CCALL(profile_gather,
int count = js2number(argv[0]);
instr_v = JS_DupValue(js, argv[1]);
JS_SetInterruptHandler(rt, iiihandle, NULL, count);
JS_SetInterruptHandler(rt, iiihandle, NULL);
)
JSC_CCALL(profile_gather_rate,
@ -1328,7 +1592,7 @@ JSC_CCALL(profile_gather_rate,
)
JSC_CCALL(profile_gather_stop,
JS_SetInterruptHandler(rt,NULL,NULL,10000);
JS_SetInterruptHandler(rt,NULL,NULL);
)
static const JSCFunctionListEntry js_profile_funcs[] = {
@ -1613,6 +1877,13 @@ JSC_CCALL(transform_phys2d,
t->rotation = HMM_MulQ(t->rotation, rot);
)
JSC_CCALL(transform_unit,
transform *t = js2transform(self);
t->pos = v3zero;
t->rotation = QUAT1;
t->scale = v3one;
)
static const JSCFunctionListEntry js_transform_funcs[] = {
CGETSET_ADD(transform, pos),
CGETSET_ADD(transform, scale),
@ -1623,6 +1894,7 @@ static const JSCFunctionListEntry js_transform_funcs[] = {
MIST_FUNC_DEF(transform, angle, 1),
MIST_FUNC_DEF(transform, lookat, 1),
MIST_FUNC_DEF(transform, direction, 1),
MIST_FUNC_DEF(transform, unit, 0),
};
JSC_GETSET(dsp_node, pass, boolean)
@ -2741,6 +3013,10 @@ void ffi_load() {
JSSTATIC(damped_spring, cpConstraint_proto)
JSSTATIC(groove, cpConstraint_proto)
JSValue array_proto = js_getpropstr(globalThis, "Array");
array_proto = js_getpropstr(array_proto, "prototype");
JS_SetPropertyFunctionList(js, array_proto, js_array_funcs, 4);
JS_FreeValue(js,globalThis);
}

View file

@ -51,6 +51,12 @@
#define container_of(ptr, type, member) ((type *)((uint8_t *)(ptr) - offsetof(type, member)))
#endif
#if !defined(_MSC_VER) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#define minimum_length(n) static n
#else
#define minimum_length(n) n
#endif
typedef int BOOL;
#ifndef FALSE

View file

@ -136,6 +136,7 @@ static inline slimb_t ceil_div(slimb_t a, slimb_t b)
return a / b;
}
#ifdef USE_BF_DEC
/* b must be >= 1 */
static inline slimb_t floor_div(slimb_t a, slimb_t b)
{
@ -145,6 +146,7 @@ static inline slimb_t floor_div(slimb_t a, slimb_t b)
return (a - b + 1) / b;
}
}
#endif
/* return r = a modulo b (0 <= r <= b - 1. b must be >= 1 */
static inline limb_t smod(slimb_t a, slimb_t b)

View file

@ -30,6 +30,7 @@
#include "cutils.h"
#include "libregexp.h"
#include "libunicode.h"
/*
TODO:
@ -141,32 +142,6 @@ static const uint16_t char_range_s[] = {
0xFEFF, 0xFEFF + 1,
};
BOOL lre_is_space(int c)
{
int i, n, low, high;
n = (countof(char_range_s) - 1) / 2;
for(i = 0; i < n; i++) {
low = char_range_s[2 * i + 1];
if (c < low)
return FALSE;
high = char_range_s[2 * i + 2];
if (c < high)
return TRUE;
}
return FALSE;
}
uint32_t const lre_id_start_table_ascii[4] = {
/* $ A-Z _ a-z */
0x00000000, 0x00000010, 0x87FFFFFE, 0x07FFFFFE
};
uint32_t const lre_id_continue_table_ascii[4] = {
/* $ 0-9 A-Z _ a-z */
0x00000000, 0x03FF0010, 0x87FFFFFE, 0x07FFFFFE
};
static const uint16_t char_range_w[] = {
4,
0x0030, 0x0039 + 1,
@ -186,7 +161,7 @@ typedef enum {
CHAR_RANGE_W,
} CharRangeEnum;
static const uint16_t *char_range_table[] = {
static const uint16_t * const char_range_table[] = {
char_range_d,
char_range_s,
char_range_w,
@ -1513,15 +1488,13 @@ static int re_parse_term(REParseState *s, BOOL is_backward_dir)
if (dbuf_error(&s->byte_code))
goto out_of_memory;
/* the spec tells that if there is no advance when
running the atom after the first quant_min times,
then there is no match. We remove this test when we
are sure the atom always advances the position. */
add_zero_advance_check = re_need_check_advance(s->byte_code.buf + last_atom_start,
s->byte_code.size - last_atom_start);
} else {
add_zero_advance_check = FALSE;
}
/* the spec tells that if there is no advance when
running the atom after the first quant_min times,
then there is no match. We remove this test when we
are sure the atom always advances the position. */
add_zero_advance_check = re_need_check_advance(s->byte_code.buf + last_atom_start,
s->byte_code.size - last_atom_start);
{
int len, pos;

View file

@ -25,10 +25,7 @@
#define LIBREGEXP_H
#include <stddef.h>
#include "libunicode.h"
#define LRE_BOOL int /* for documentation purposes */
#include <stdint.h>
#define LRE_FLAG_GLOBAL (1 << 0)
#define LRE_FLAG_IGNORECASE (1 << 1)
@ -50,43 +47,9 @@ int lre_exec(uint8_t **capture,
int cbuf_type, void *opaque);
int lre_parse_escape(const uint8_t **pp, int allow_utf16);
LRE_BOOL lre_is_space(int c);
/* must be provided by the user */
LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size);
/* must be provided by the user, return non zero if overflow */
int lre_check_stack_overflow(void *opaque, size_t alloca_size);
void *lre_realloc(void *opaque, void *ptr, size_t size);
/* JS identifier test */
extern uint32_t const lre_id_start_table_ascii[4];
extern uint32_t const lre_id_continue_table_ascii[4];
static inline int lre_js_is_ident_first(int c)
{
if ((uint32_t)c < 128) {
return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1;
} else {
#ifdef CONFIG_ALL_UNICODE
return lre_is_id_start(c);
#else
return !lre_is_space(c);
#endif
}
}
static inline int lre_js_is_ident_next(int c)
{
if ((uint32_t)c < 128) {
return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1;
} else {
/* ZWNJ and ZWJ are accepted in identifiers */
#ifdef CONFIG_ALL_UNICODE
return lre_is_id_continue(c) || c == 0x200C || c == 0x200D;
#else
return !lre_is_space(c) || c == 0x200C || c == 0x200D;
#endif
}
}
#undef LRE_BOOL
#endif /* LIBREGEXP_H */

View file

@ -189,9 +189,13 @@ static const uint8_t unicode_prop_Cased1_table[196] = {
};
static const uint8_t unicode_prop_Cased1_index[21] = {
0xb9, 0x02, 0xe0, 0xc0, 0x1d, 0x20, 0xe5, 0x2c,
0x20, 0xb1, 0x07, 0x21, 0xc1, 0xd6, 0x21, 0x4a,
0xf1, 0x01, 0x8a, 0xf1, 0x01,
0xb9, 0x02, 0xe0, // 002B9 at 39
0xc0, 0x1d, 0x20, // 01DC0 at 65
0xe5, 0x2c, 0x20, // 02CE5 at 97
0xb1, 0x07, 0x21, // 107B1 at 129
0xc1, 0xd6, 0x21, // 1D6C1 at 161
0x4a, 0xf1, 0x01, // 1F14A at 192
0x8a, 0xf1, 0x01, // 1F18A at 224 (upper bound)
};
static const uint8_t unicode_prop_Case_Ignorable_table[737] = {
@ -291,15 +295,29 @@ static const uint8_t unicode_prop_Case_Ignorable_table[737] = {
};
static const uint8_t unicode_prop_Case_Ignorable_index[69] = {
0xbe, 0x05, 0x00, 0xfe, 0x07, 0x00, 0x52, 0x0a,
0xa0, 0xc1, 0x0b, 0x00, 0x82, 0x0d, 0x00, 0x3f,
0x10, 0x80, 0xd4, 0x17, 0x40, 0xcf, 0x1a, 0x20,
0xf5, 0x1c, 0x00, 0x80, 0x20, 0x00, 0x16, 0xa0,
0x00, 0xc6, 0xa8, 0x00, 0xc2, 0xaa, 0x60, 0x56,
0xfe, 0x20, 0xb1, 0x07, 0x01, 0x75, 0x10, 0x01,
0xeb, 0x12, 0x21, 0x41, 0x16, 0x01, 0x5c, 0x1a,
0x01, 0x43, 0x1f, 0x01, 0x2e, 0xcf, 0x41, 0x25,
0xe0, 0x01, 0xf0, 0x01, 0x0e,
0xbe, 0x05, 0x00, // 005BE at 32
0xfe, 0x07, 0x00, // 007FE at 64
0x52, 0x0a, 0xa0, // 00A52 at 101
0xc1, 0x0b, 0x00, // 00BC1 at 128
0x82, 0x0d, 0x00, // 00D82 at 160
0x3f, 0x10, 0x80, // 0103F at 196
0xd4, 0x17, 0x40, // 017D4 at 226
0xcf, 0x1a, 0x20, // 01ACF at 257
0xf5, 0x1c, 0x00, // 01CF5 at 288
0x80, 0x20, 0x00, // 02080 at 320
0x16, 0xa0, 0x00, // 0A016 at 352
0xc6, 0xa8, 0x00, // 0A8C6 at 384
0xc2, 0xaa, 0x60, // 0AAC2 at 419
0x56, 0xfe, 0x20, // 0FE56 at 449
0xb1, 0x07, 0x01, // 107B1 at 480
0x75, 0x10, 0x01, // 11075 at 512
0xeb, 0x12, 0x21, // 112EB at 545
0x41, 0x16, 0x01, // 11641 at 576
0x5c, 0x1a, 0x01, // 11A5C at 608
0x43, 0x1f, 0x01, // 11F43 at 640
0x2e, 0xcf, 0x41, // 1CF2E at 674
0x25, 0xe0, 0x01, // 1E025 at 704
0xf0, 0x01, 0x0e, // E01F0 at 736 (upper bound)
};
static const uint8_t unicode_prop_ID_Start_table[1100] = {
@ -444,20 +462,41 @@ static const uint8_t unicode_prop_ID_Start_table[1100] = {
};
static const uint8_t unicode_prop_ID_Start_index[105] = {
0xf6, 0x03, 0x20, 0xa6, 0x07, 0x00, 0xa9, 0x09,
0x20, 0xb1, 0x0a, 0x00, 0xba, 0x0b, 0x20, 0x3b,
0x0d, 0x20, 0xc7, 0x0e, 0x20, 0x49, 0x12, 0x00,
0x9b, 0x16, 0x00, 0xac, 0x19, 0x00, 0xc0, 0x1d,
0x80, 0x80, 0x20, 0x20, 0x70, 0x2d, 0x00, 0x00,
0x32, 0x00, 0xda, 0xa7, 0x00, 0x4c, 0xaa, 0x20,
0xc7, 0xd7, 0x20, 0xfc, 0xfd, 0x20, 0x9d, 0x02,
0x21, 0x96, 0x05, 0x01, 0xf3, 0x08, 0x01, 0xb3,
0x0c, 0x21, 0x73, 0x11, 0x61, 0x34, 0x13, 0x01,
0x1b, 0x17, 0x21, 0x8a, 0x1a, 0x01, 0x34, 0x1f,
0x21, 0xbf, 0x6a, 0x01, 0x23, 0xb1, 0xa1, 0xad,
0xd4, 0x01, 0x6f, 0xd7, 0x01, 0xff, 0xe7, 0x61,
0x5e, 0xee, 0x01, 0xe1, 0xeb, 0x22, 0xb0, 0x23,
0x03,
0xf6, 0x03, 0x20, // 003F6 at 33
0xa6, 0x07, 0x00, // 007A6 at 64
0xa9, 0x09, 0x20, // 009A9 at 97
0xb1, 0x0a, 0x00, // 00AB1 at 128
0xba, 0x0b, 0x20, // 00BBA at 161
0x3b, 0x0d, 0x20, // 00D3B at 193
0xc7, 0x0e, 0x20, // 00EC7 at 225
0x49, 0x12, 0x00, // 01249 at 256
0x9b, 0x16, 0x00, // 0169B at 288
0xac, 0x19, 0x00, // 019AC at 320
0xc0, 0x1d, 0x80, // 01DC0 at 356
0x80, 0x20, 0x20, // 02080 at 385
0x70, 0x2d, 0x00, // 02D70 at 416
0x00, 0x32, 0x00, // 03200 at 448
0xda, 0xa7, 0x00, // 0A7DA at 480
0x4c, 0xaa, 0x20, // 0AA4C at 513
0xc7, 0xd7, 0x20, // 0D7C7 at 545
0xfc, 0xfd, 0x20, // 0FDFC at 577
0x9d, 0x02, 0x21, // 1029D at 609
0x96, 0x05, 0x01, // 10596 at 640
0xf3, 0x08, 0x01, // 108F3 at 672
0xb3, 0x0c, 0x21, // 10CB3 at 705
0x73, 0x11, 0x61, // 11173 at 739
0x34, 0x13, 0x01, // 11334 at 768
0x1b, 0x17, 0x21, // 1171B at 801
0x8a, 0x1a, 0x01, // 11A8A at 832
0x34, 0x1f, 0x21, // 11F34 at 865
0xbf, 0x6a, 0x01, // 16ABF at 896
0x23, 0xb1, 0xa1, // 1B123 at 933
0xad, 0xd4, 0x01, // 1D4AD at 960
0x6f, 0xd7, 0x01, // 1D76F at 992
0xff, 0xe7, 0x61, // 1E7FF at 1027
0x5e, 0xee, 0x01, // 1EE5E at 1056
0xe1, 0xeb, 0x22, // 2EBE1 at 1089
0xb0, 0x23, 0x03, // 323B0 at 1120 (upper bound)
};
static const uint8_t unicode_prop_ID_Continue1_table[660] = {
@ -547,14 +586,27 @@ static const uint8_t unicode_prop_ID_Continue1_table[660] = {
};
static const uint8_t unicode_prop_ID_Continue1_index[63] = {
0xfa, 0x06, 0x00, 0x70, 0x09, 0x00, 0xf0, 0x0a,
0x40, 0x57, 0x0c, 0x00, 0xf0, 0x0d, 0x60, 0xc7,
0x0f, 0x20, 0xea, 0x17, 0x40, 0x05, 0x1b, 0x00,
0x41, 0x20, 0x00, 0x0c, 0xa8, 0x80, 0x37, 0xaa,
0x20, 0x50, 0xfe, 0x20, 0x3a, 0x0d, 0x21, 0x74,
0x11, 0x01, 0x5a, 0x14, 0x21, 0x44, 0x19, 0x81,
0x5a, 0x1d, 0xa1, 0xf5, 0x6a, 0x21, 0x45, 0xd2,
0x41, 0xaf, 0xe2, 0x21, 0xf0, 0x01, 0x0e,
0xfa, 0x06, 0x00, // 006FA at 32
0x70, 0x09, 0x00, // 00970 at 64
0xf0, 0x0a, 0x40, // 00AF0 at 98
0x57, 0x0c, 0x00, // 00C57 at 128
0xf0, 0x0d, 0x60, // 00DF0 at 163
0xc7, 0x0f, 0x20, // 00FC7 at 193
0xea, 0x17, 0x40, // 017EA at 226
0x05, 0x1b, 0x00, // 01B05 at 256
0x41, 0x20, 0x00, // 02041 at 288
0x0c, 0xa8, 0x80, // 0A80C at 324
0x37, 0xaa, 0x20, // 0AA37 at 353
0x50, 0xfe, 0x20, // 0FE50 at 385
0x3a, 0x0d, 0x21, // 10D3A at 417
0x74, 0x11, 0x01, // 11174 at 448
0x5a, 0x14, 0x21, // 1145A at 481
0x44, 0x19, 0x81, // 11944 at 516
0x5a, 0x1d, 0xa1, // 11D5A at 549
0xf5, 0x6a, 0x21, // 16AF5 at 577
0x45, 0xd2, 0x41, // 1D245 at 610
0xaf, 0xe2, 0x21, // 1E2AF at 641
0xf0, 0x01, 0x0e, // E01F0 at 672 (upper bound)
};
#ifdef CONFIG_ALL_UNICODE
@ -676,17 +728,35 @@ static const uint8_t unicode_cc_table[899] = {
};
static const uint8_t unicode_cc_index[87] = {
0x4d, 0x03, 0x00, 0x97, 0x05, 0x20, 0xc6, 0x05,
0x00, 0xe7, 0x06, 0x00, 0x45, 0x07, 0x00, 0x9c,
0x08, 0x00, 0x4d, 0x09, 0x00, 0x3c, 0x0b, 0x00,
0x3d, 0x0d, 0x00, 0x36, 0x0f, 0x00, 0x38, 0x10,
0x20, 0x3a, 0x19, 0x00, 0xcb, 0x1a, 0x20, 0xd3,
0x1c, 0x00, 0xcf, 0x1d, 0x00, 0xe2, 0x20, 0x00,
0x2e, 0x30, 0x20, 0x2b, 0xa9, 0x20, 0xed, 0xab,
0x00, 0x39, 0x0a, 0x01, 0x51, 0x0f, 0x01, 0x73,
0x11, 0x01, 0x75, 0x13, 0x01, 0x2b, 0x17, 0x21,
0x3f, 0x1c, 0x21, 0x9e, 0xbc, 0x21, 0x08, 0xe0,
0x01, 0x44, 0xe9, 0x01, 0x4b, 0xe9, 0x01,
0x4d, 0x03, 0x00, // 0034D at 32
0x97, 0x05, 0x20, // 00597 at 65
0xc6, 0x05, 0x00, // 005C6 at 96
0xe7, 0x06, 0x00, // 006E7 at 128
0x45, 0x07, 0x00, // 00745 at 160
0x9c, 0x08, 0x00, // 0089C at 192
0x4d, 0x09, 0x00, // 0094D at 224
0x3c, 0x0b, 0x00, // 00B3C at 256
0x3d, 0x0d, 0x00, // 00D3D at 288
0x36, 0x0f, 0x00, // 00F36 at 320
0x38, 0x10, 0x20, // 01038 at 353
0x3a, 0x19, 0x00, // 0193A at 384
0xcb, 0x1a, 0x20, // 01ACB at 417
0xd3, 0x1c, 0x00, // 01CD3 at 448
0xcf, 0x1d, 0x00, // 01DCF at 480
0xe2, 0x20, 0x00, // 020E2 at 512
0x2e, 0x30, 0x20, // 0302E at 545
0x2b, 0xa9, 0x20, // 0A92B at 577
0xed, 0xab, 0x00, // 0ABED at 608
0x39, 0x0a, 0x01, // 10A39 at 640
0x51, 0x0f, 0x01, // 10F51 at 672
0x73, 0x11, 0x01, // 11173 at 704
0x75, 0x13, 0x01, // 11375 at 736
0x2b, 0x17, 0x21, // 1172B at 769
0x3f, 0x1c, 0x21, // 11C3F at 801
0x9e, 0xbc, 0x21, // 1BC9E at 833
0x08, 0xe0, 0x01, // 1E008 at 864
0x44, 0xe9, 0x01, // 1E944 at 896
0x4b, 0xe9, 0x01, // 1E94B at 928 (upper bound)
};
static const uint32_t unicode_decomp_table1[699] = {
@ -4484,3 +4554,4 @@ static const uint16_t unicode_prop_len_table[] = {
};
#endif /* CONFIG_ALL_UNICODE */
/* 62 tables / 32261 bytes, 5 index / 345 bytes */

View file

@ -262,11 +262,7 @@ int lre_canonicalize(uint32_t c, BOOL is_unicode)
static uint32_t get_le24(const uint8_t *ptr)
{
#if defined(__x86__) || defined(__x86_64__)
return *(uint16_t *)ptr | (ptr[2] << 16);
#else
return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
#endif
}
#define UNICODE_INDEX_BLOCK_LEN 32
@ -317,6 +313,14 @@ static BOOL lre_is_in_table(uint32_t c, const uint8_t *table,
return FALSE; /* outside the table */
p = table + pos;
bit = 0;
/* Compressed run length encoding:
00..3F: 2 packed lengths: 3-bit + 3-bit
40..5F: 5-bits plus extra byte for length
60..7F: 5-bits plus 2 extra bytes for length
80..FF: 7-bit length
lengths must be incremented to get character count
Ranges alternate between false and true return value.
*/
for(;;) {
b = *p++;
if (b < 64) {
@ -833,6 +837,13 @@ static int unicode_get_cc(uint32_t c)
if (pos < 0)
return 0;
p = unicode_cc_table + pos;
/* Compressed run length encoding:
- 2 high order bits are combining class type
- 0:0, 1:230, 2:extra byte linear progression, 3:extra byte
- 00..2F: range length (add 1)
- 30..37: 3-bit range-length + 1 extra byte
- 38..3F: 3-bit range-length + 2 extra byte
*/
for(;;) {
b = *p++;
type = b >> 6;
@ -1185,6 +1196,15 @@ static int unicode_general_category1(CharRange *cr, uint32_t gc_mask)
p = unicode_gc_table;
p_end = unicode_gc_table + countof(unicode_gc_table);
c = 0;
/* Compressed range encoding:
initial byte:
bits 0..4: category number (special case 31)
bits 5..7: range length (add 1)
special case bits 5..7 == 7: read an extra byte
- 00..7F: range length (add 7 + 1)
- 80..BF: 6-bits plus extra byte for range length (add 7 + 128)
- C0..FF: 6-bits plus 2 extra bytes for range length (add 7 + 128 + 16384)
*/
while (p < p_end) {
b = *p++;
n = b >> 5;
@ -1238,6 +1258,14 @@ static int unicode_prop1(CharRange *cr, int prop_idx)
p_end = p + unicode_prop_len_table[prop_idx];
c = 0;
bit = 0;
/* Compressed range encoding:
00..3F: 2 packed lengths: 3-bit + 3-bit
40..5F: 5-bits plus extra byte for length
60..7F: 5-bits plus 2 extra bytes for length
80..FF: 7-bit length
lengths must be incremented to get character count
Ranges alternate between false and true return value.
*/
while (p < p_end) {
c0 = c;
b = *p++;
@ -1786,3 +1814,97 @@ int unicode_prop(CharRange *cr, const char *prop_name)
}
#endif /* CONFIG_ALL_UNICODE */
/*---- lre codepoint categorizing functions ----*/
#define S UNICODE_C_SPACE
#define D UNICODE_C_DIGIT
#define X UNICODE_C_XDIGIT
#define U UNICODE_C_UPPER
#define L UNICODE_C_LOWER
#define _ UNICODE_C_UNDER
#define d UNICODE_C_DOLLAR
uint8_t const lre_ctype_bits[256] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, S, S, S, S, S, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
S, 0, 0, 0, d, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
X|D, X|D, X|D, X|D, X|D, X|D, X|D, X|D,
X|D, X|D, 0, 0, 0, 0, 0, 0,
0, X|U, X|U, X|U, X|U, X|U, X|U, U,
U, U, U, U, U, U, U, U,
U, U, U, U, U, U, U, U,
U, U, U, 0, 0, 0, 0, _,
0, X|L, X|L, X|L, X|L, X|L, X|L, L,
L, L, L, L, L, L, L, L,
L, L, L, L, L, L, L, L,
L, L, L, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
S, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
#undef S
#undef D
#undef X
#undef U
#undef L
#undef _
#undef d
/* code point ranges for Zs,Zl or Zp property */
static const uint16_t char_range_s[] = {
10,
0x0009, 0x000D + 1,
0x0020, 0x0020 + 1,
0x00A0, 0x00A0 + 1,
0x1680, 0x1680 + 1,
0x2000, 0x200A + 1,
/* 2028;LINE SEPARATOR;Zl;0;WS;;;;;N;;;;; */
/* 2029;PARAGRAPH SEPARATOR;Zp;0;B;;;;;N;;;;; */
0x2028, 0x2029 + 1,
0x202F, 0x202F + 1,
0x205F, 0x205F + 1,
0x3000, 0x3000 + 1,
/* FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;; */
0xFEFF, 0xFEFF + 1,
};
BOOL lre_is_space_non_ascii(uint32_t c)
{
size_t i, n;
n = countof(char_range_s);
for(i = 5; i < n; i += 2) {
uint32_t low = char_range_s[i];
uint32_t high = char_range_s[i + 1];
if (c < low)
return FALSE;
if (c < high)
return TRUE;
}
return FALSE;
}

View file

@ -24,27 +24,13 @@
#ifndef LIBUNICODE_H
#define LIBUNICODE_H
#include <inttypes.h>
#define LRE_BOOL int /* for documentation purposes */
#include <stdint.h>
/* define it to include all the unicode tables (40KB larger) */
#define CONFIG_ALL_UNICODE
#define LRE_CC_RES_LEN_MAX 3
typedef enum {
UNICODE_NFC,
UNICODE_NFD,
UNICODE_NFKC,
UNICODE_NFKD,
} UnicodeNormalizationEnum;
int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
int lre_canonicalize(uint32_t c, LRE_BOOL is_unicode);
LRE_BOOL lre_is_cased(uint32_t c);
LRE_BOOL lre_is_case_ignorable(uint32_t c);
/* char ranges */
typedef struct {
@ -102,12 +88,14 @@ int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len,
int cr_invert(CharRange *cr);
int cr_regexp_canonicalize(CharRange *cr, LRE_BOOL is_unicode);
int cr_regexp_canonicalize(CharRange *cr, int is_unicode);
#ifdef CONFIG_ALL_UNICODE
LRE_BOOL lre_is_id_start(uint32_t c);
LRE_BOOL lre_is_id_continue(uint32_t c);
typedef enum {
UNICODE_NFC,
UNICODE_NFD,
UNICODE_NFKC,
UNICODE_NFKD,
} UnicodeNormalizationEnum;
int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
UnicodeNormalizationEnum n_type,
@ -115,13 +103,80 @@ int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
/* Unicode character range functions */
int unicode_script(CharRange *cr,
const char *script_name, LRE_BOOL is_ext);
int unicode_script(CharRange *cr, const char *script_name, int is_ext);
int unicode_general_category(CharRange *cr, const char *gc_name);
int unicode_prop(CharRange *cr, const char *prop_name);
#endif /* CONFIG_ALL_UNICODE */
int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
int lre_canonicalize(uint32_t c, int is_unicode);
#undef LRE_BOOL
/* Code point type categories */
enum {
UNICODE_C_SPACE = (1 << 0),
UNICODE_C_DIGIT = (1 << 1),
UNICODE_C_UPPER = (1 << 2),
UNICODE_C_LOWER = (1 << 3),
UNICODE_C_UNDER = (1 << 4),
UNICODE_C_DOLLAR = (1 << 5),
UNICODE_C_XDIGIT = (1 << 6),
};
extern uint8_t const lre_ctype_bits[256];
/* zero or non-zero return value */
int lre_is_cased(uint32_t c);
int lre_is_case_ignorable(uint32_t c);
int lre_is_id_start(uint32_t c);
int lre_is_id_continue(uint32_t c);
static inline int lre_is_space_byte(uint8_t c) {
return lre_ctype_bits[c] & UNICODE_C_SPACE;
}
static inline int lre_is_id_start_byte(uint8_t c) {
return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER |
UNICODE_C_UNDER | UNICODE_C_DOLLAR);
}
static inline int lre_is_id_continue_byte(uint8_t c) {
return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER |
UNICODE_C_UNDER | UNICODE_C_DOLLAR |
UNICODE_C_DIGIT);
}
int lre_is_space_non_ascii(uint32_t c);
static inline int lre_is_space(uint32_t c) {
if (c < 256)
return lre_is_space_byte(c);
else
return lre_is_space_non_ascii(c);
}
static inline int lre_js_is_ident_first(uint32_t c) {
if (c < 128) {
return lre_is_id_start_byte(c);
} else {
#ifdef CONFIG_ALL_UNICODE
return lre_is_id_start(c);
#else
return !lre_is_space_non_ascii(c);
#endif
}
}
static inline int lre_js_is_ident_next(uint32_t c) {
if (c < 128) {
return lre_is_id_continue_byte(c);
} else {
/* ZWNJ and ZWJ are accepted in identifiers */
if (c >= 0x200C && c <= 0x200D)
return TRUE;
#ifdef CONFIG_ALL_UNICODE
return lre_is_id_continue(c);
#else
return !lre_is_space_non_ascii(c);
#endif
}
}
#endif /* LIBUNICODE_H */

File diff suppressed because it is too large Load diff

View file

@ -92,6 +92,7 @@ typedef struct JSRefCountHeader {
} JSRefCountHeader;
void quickjs_set_dumpout(FILE *f);
void JS_SetInterruptRate(int count);
#define JS_FLOAT64_NAN NAN
@ -635,7 +636,9 @@ static inline JS_BOOL JS_IsObject(JSValueConst v)
JSValue JS_Throw(JSContext *ctx, JSValue obj);
JSValue JS_GetException(JSContext *ctx);
JS_BOOL JS_HasException(JSContext *ctx);
JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val);
void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, JS_BOOL flag);
void JS_ResetUncatchableError(JSContext *ctx);
JSValue JS_NewError(JSContext *ctx);
JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...);
@ -684,6 +687,10 @@ static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v)
return (JSValue)v;
}
JS_BOOL JS_StrictEq(JSContext *ctx, JSValueConst op1, JSValueConst op2);
JS_BOOL JS_SameValue(JSContext *ctx, JSValueConst op1, JSValueConst op2);
JS_BOOL JS_SameValueZero(JSContext *ctx, JSValueConst op1, JSValueConst op2);
int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */
int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val);
static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val)
@ -726,6 +733,8 @@ JS_BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, JS_BOOL val)
JSValue JS_NewArray(JSContext *ctx);
int JS_IsArray(JSContext *ctx, JSValueConst val);
JSValue JS_NewDate(JSContext *ctx, double epoch_ms);
JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
JSAtom prop, JSValueConst receiver,
JS_BOOL throw_ref_error);
@ -824,6 +833,23 @@ JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len,
JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len);
void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj);
uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj);
typedef enum JSTypedArrayEnum {
JS_TYPED_ARRAY_UINT8C = 0,
JS_TYPED_ARRAY_INT8,
JS_TYPED_ARRAY_UINT8,
JS_TYPED_ARRAY_INT16,
JS_TYPED_ARRAY_UINT16,
JS_TYPED_ARRAY_INT32,
JS_TYPED_ARRAY_UINT32,
JS_TYPED_ARRAY_BIG_INT64,
JS_TYPED_ARRAY_BIG_UINT64,
JS_TYPED_ARRAY_FLOAT32,
JS_TYPED_ARRAY_FLOAT64,
} JSTypedArrayEnum;
JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv,
JSTypedArrayEnum array_type);
JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj,
size_t *pbyte_offset,
size_t *pbyte_length,
@ -855,8 +881,7 @@ void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, JSHostPromiseRejectionTrac
/* return != 0 if the JS code needs to be interrupted */
typedef int JSInterruptHandler(JSRuntime *rt, void *opaque);
void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque, int count);
void JS_SetInterruptRate(int count);
void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque);
/* if can_block is TRUE, Atomics.wait() can be used */
void JS_SetCanBlock(JSRuntime *rt, JS_BOOL can_block);
/* set the [IsHTMLDDA] internal slot */