Handle return value better in JS bindings.

This commit is contained in:
Brad Nelson
2022-11-17 20:42:20 -08:00
parent 9e1aaedf12
commit 279b391a28

View File

@ -25,16 +25,39 @@ r~
var parts = text.split('\n'); var parts = text.split('\n');
var args = parts[0].split(' '); var args = parts[0].split(' ');
var code = '(function(sp) {\n'; var code = '(function(sp) {\n';
for (var i = args.length - 1; i >= 0; --i) { code += 'var results = (function() {\n';
var params = [];
var results = [];
var at_results = false;
for (var i = 0; i < args.length; ++i) {
if (args[i].length === 0 || if (args[i].length === 0 ||
args[i] === '{' || args[i] === '{' ||
args[i] === '}') { args[i] === '}') {
continue; continue;
} }
code += 'var ' + args[i] + ' = i32[sp>>2]; sp -= 4;\n'; if (args[i] === '--') {
at_results = true;
continue;
}
if (at_results) {
results.push(args[i]);
} else {
params.push(args[i]);
}
}
for (var i = params.length - 1; i >= 0; --i) {
code += 'var ' + params[i] + ' = i32[sp>>2]; sp -= 4;\n';
} }
code += parts.slice(1).join('\n'); code += parts.slice(1).join('\n');
code += ' return sp;\n'; code += '})();\n';
if (results.length === 1) {
code += 'sp += 4; i32[sp>>2] = results;\n';
} else {
for (var i = 0; i < results.length; ++i) {
code += 'sp += 4; i32[sp>>2] = results[' + i + '];\n';
}
}
code += 'return sp;\n';
code += '})\n'; code += '})\n';
objects[slot] = eval(code); objects[slot] = eval(code);
return sp; return sp;
@ -42,18 +65,14 @@ r~
~ 1 jseval! ~ 1 jseval!
2 value jsslot 2 value jsslot
: JSWORD| ( "args.." ) : JSWORD: ( "args.." )
create postpone r| jsslot 1 call jsslot , 1 +to jsslot create postpone r~ jsslot 1 call jsslot , 1 +to jsslot
does> @ call ; does> @ call ;
JSWORD| jseval { a n } JSWORD: jseval { a n }
var text = GetString(a, n); var text = GetString(a, n);
eval(text); eval(text);
| ~
: JSWORD: ( "name" )
create jsslot jseval! jsslot , 1 +to jsslot
does> @ call ;
r~ r~
globalObj.ueforth = context; globalObj.ueforth = context;
@ -515,14 +534,11 @@ if (!globalObj.write) {
} }
~ jseval ~ jseval
r| JSWORD: web-type-raw { a n -- yld }
(function(sp) {
var n = i32[sp>>2]; sp -= 4;
var a = i32[sp>>2]; sp -= 4;
if (globalObj.write) { if (globalObj.write) {
var text = GetString(a, n); var text = GetString(a, n);
write(text); write(text);
sp += 4; i32[sp>>2] = 0; return 0;
} else { } else {
var newline = false; var newline = false;
for (var i = 0; i < n; ++i) { for (var i = 0; i < n; ++i) {
@ -533,16 +549,13 @@ r|
if (newline) { if (newline) {
context.Update(); context.Update();
} }
sp += 4; i32[sp>>2] = newline ? -1 : 0; return newline ? -1 : 0;
} }
return sp; ~
})
| JSWORD: web-type-raw ( a n -- yield? )
: web-type ( a n -- ) web-type-raw if yield then ; : web-type ( a n -- ) web-type-raw if yield then ;
' web-type is type ' web-type is type
r| JSWORD: web-key-raw { -- n }
(function(sp) {
context.Update(); context.Update();
if (globalObj.readline && !context.inbuffer.length) { if (globalObj.readline && !context.inbuffer.length) {
var line = unescape(encodeURIComponent(readline())); var line = unescape(encodeURIComponent(readline()));
@ -552,57 +565,48 @@ r|
context.inbuffer.push(13); context.inbuffer.push(13);
} }
if (context.inbuffer.length) { if (context.inbuffer.length) {
sp += 4; i32[sp>>2] = context.inbuffer.shift(); return context.inbuffer.shift();
} else { } else {
sp += 4; i32[sp>>2] = 0; return 0;
} }
return sp; ~
})
| JSWORD: web-key-raw ( -- n )
: web-key ( -- n ) begin yield web-key-raw dup if exit then drop again ; : web-key ( -- n ) begin yield web-key-raw dup if exit then drop again ;
' web-key is key ' web-key is key
r| JSWORD: web-key?-raw { -- f }
(function(sp) {
context.Update(); context.Update();
if (globalObj.readline) { if (globalObj.readline) {
sp += 4; i32[sp>>2] = -1; return -1;
return sp;
} }
sp += 4; i32[sp>>2] = context.inbuffer.length ? -1 : 0; return context.inbuffer.length ? -1 : 0;
return sp; ~
})
| JSWORD: web-key?-raw ( -- f )
: web-key? ( -- f ) yield web-key?-raw ; : web-key? ( -- f ) yield web-key?-raw ;
' web-key? is key? ' web-key? is key?
JSWORD| terminate { retval } JSWORD: terminate { retval }
if (globalObj.quit) { if (globalObj.quit) {
quit(retval); quit(retval);
} else { } else {
Init(); Init();
} }
| ~
r| JSWORD: shouldEcho? { -- f }
(function(sp) {
if (globalObj.write) { if (globalObj.write) {
sp += 4; i32[sp>>2] = 0; // Disable echo. return 0; // Disable echo.
} else { } else {
sp += 4; i32[sp>>2] = -1; // Enable echo. return -1; // Enable echo.
} }
return sp; ~
})
| JSWORD: shouldEcho? ( -- f )
shouldEcho? echo ! shouldEcho? echo !
JSWORD| grmode { mode } JSWORD: grmode { mode }
context.setMode(mode); context.setMode(mode);
| ~
: gr 1 grmode ; : gr 1 grmode ;
: text 0 grmode ; : text 0 grmode ;
JSWORD| rawbox { x y w h c } JSWORD: rawbox { x y w h c }
function HexDig(n) { function HexDig(n) {
return ('0' + n.toString(16)).slice(-2); return ('0' + n.toString(16)).slice(-2);
} }
@ -610,47 +614,35 @@ JSWORD| rawbox { x y w h c }
HexDig((c >> 8) & 0xff) + HexDig((c >> 8) & 0xff) +
HexDig(c & 0xff); HexDig(c & 0xff);
context.ctx.fillRect(x, y, w, h); context.ctx.fillRect(x, y, w, h);
| ~
$ffffff value color $ffffff value color
: box ( x y w h -- ) color rawbox ; : box ( x y w h -- ) color rawbox ;
JSWORD| window { w h } JSWORD: window { w h }
context.canvas.width = w; context.canvas.width = w;
context.canvas.height = h; context.canvas.height = h;
| ~
r| JSWORD: viewport@ { -- w h }
(function(sp) {
if (globalObj.write) { if (globalObj.write) {
sp += 4; i32[sp>>2] = 1; return [1, 1];
sp += 4; i32[sp>>2] = 1;
return sp;
} }
sp += 4; i32[sp>>2] = context.width; return [context.width, context.height];
sp += 4; i32[sp>>2] = context.height; ~
return sp;
})
| JSWORD: viewport@ ( -- w h )
JSWORD| textRatios { tf mp } JSWORD: textRatios { tf mp }
context.text_fraction = tf; context.text_fraction = tf;
context.min_text_portion = mp; context.min_text_portion = mp;
context.Resize(); context.Resize();
| ~
r| JSWORD: mobile { -- f }
(function(sp) { return context.mobile;
sp += 4; i32[sp>>2] = context.mobile; ~
return sp;
})
| JSWORD: mobile ( -- f )
r| JSWORD: keys-height { -- n }
(function(sp) { return context.KEYBOARD_HEIGHT;
sp += 4; i32[sp>>2] = context.KEYBOARD_HEIGHT; ~
return sp;
})
| JSWORD: keys-height ( -- n )
: show-text ( f -- ) : show-text ( f -- )
if if
@ -659,31 +651,31 @@ r|
mobile if 0 keys-height else 0 0 then mobile if 0 keys-height else 0 0 then
then textRatios ; then textRatios ;
JSWORD| translate { x y } JSWORD: translate { x y }
context.ctx.translate(x, y); context.ctx.translate(x, y);
| ~
JSWORD| scale { x y div } JSWORD: scale { x y div }
context.ctx.scale(x / div, y / div); context.ctx.scale(x / div, y / div);
| ~
JSWORD| rotate { angle div } JSWORD: rotate { angle div }
context.ctx.rotate(Math.PI * 2 * angle / div); context.ctx.rotate(Math.PI * 2 * angle / div);
| ~
JSWORD| gpush { } JSWORD: gpush { }
context.ctx.save(); context.ctx.save();
| ~
JSWORD| gpop { } JSWORD: gpop { }
context.ctx.restore(); context.ctx.restore();
| ~
JSWORD| smooth { f } JSWORD: smooth { f }
context.canvas.style.imageRendering = f ? '' : 'pixelated'; context.canvas.style.imageRendering = f ? '' : 'pixelated';
| ~
JSWORD| setItem { value value_len key key_len session } JSWORD: setItem { value value_len key key_len session }
if (session) { if (session) {
sessionStorage.setItem(context.GetRawString(key, key_len), sessionStorage.setItem(context.GetRawString(key, key_len),
context.GetRawString(value, value_len)); context.GetRawString(value, value_len));
@ -691,131 +683,80 @@ JSWORD| setItem { value value_len key key_len session }
localStorage.setItem(context.GetRawString(key, key_len), localStorage.setItem(context.GetRawString(key, key_len),
context.GetRawString(value, value_len)); context.GetRawString(value, value_len));
} }
| ~
r| JSWORD: getItem { dst dst_limit key key_len session -- n }
(function(sp) {
var session = i32[sp>>2]; sp -= 4;
var key_len = i32[sp>>2]; sp -= 4;
var key = i32[sp>>2]; sp -= 4;
var dst_limit = i32[sp>>2]; sp -= 4;
var dst = i32[sp>>2]; sp -= 4;
if (globalObj.write) {
return sp;
}
if (session) { if (session) {
var data = sessionStorage.getItem(context.GetRawString(key, key_len)); var data = sessionStorage.getItem(context.GetRawString(key, key_len));
} else { } else {
var data = localStorage.getItem(context.GetRawString(key, key_len)); var data = localStorage.getItem(context.GetRawString(key, key_len));
} }
if (data === null) { if (data === null) {
sp += 4; i32[sp>>2] = -1; return -1;
return sp;
} }
for (var i = 0; i < dst_limit && i < data.length; ++i) { for (var i = 0; i < dst_limit && i < data.length; ++i) {
u8[dst + i] = data.charCodeAt(i); u8[dst + i] = data.charCodeAt(i);
} }
sp += 4; i32[sp>>2] = data.length; return data.length;
return sp; ~
})
| JSWORD: getItem ( a n a n sess -- n )
r| JSWORD: getKey { key key_limit index session -- n }
(function(sp) {
var session = i32[sp>>2]; sp -= 4;
var index = i32[sp>>2]; sp -= 4;
var key_limit = i32[sp>>2]; sp -= 4;
var key = i32[sp>>2]; sp -= 4;
if (globalObj.write) {
sp += 4; i32[sp>>2] = -1;
return sp;
}
if (session) { if (session) {
var data = sessionStorage.key(index); var data = sessionStorage.key(index);
} else { } else {
var data = localStorage.key(index); var data = localStorage.key(index);
} }
if (data === null) { if (data === null) {
sp += 4; i32[sp>>2] = -1; return -1;
return sp;
} }
for (var i = 0; i < key_limit && i < data.length; ++i) { for (var i = 0; i < key_limit && i < data.length; ++i) {
u8[key + i] = data.charCodeAt(i); u8[key + i] = data.charCodeAt(i);
} }
sp += 4; i32[sp>>2] = data.length; return i;
return sp; ~
})
| JSWORD: getKey ( a n sess -- n )
r| JSWORD: keyCount { session -- n }
(function(sp) {
var session = i32[sp>>2]; sp -= 4;
if (globalObj.write) {
sp += 4; i32[sp>>2] = -1;
return sp;
}
if (session) { if (session) {
var len = sessionStorage.length; var len = sessionStorage.length;
} else { } else {
var len = localStorage.length; var len = localStorage.length;
} }
sp += 4; i32[sp>>2] = len; return len;
return sp; ~
})
| JSWORD: keyCount ( sess -- n )
JSWORD| release { handle } JSWORD: release { handle }
context.ReleaseHandle(handle); context.ReleaseHandle(handle);
| ~
r| JSWORD: newAudioContext { -- h }
(function(sp) {
var i = context.AllotHandle(); var i = context.AllotHandle();
sp += 4; i32[sp>>2] = i;
context.handles[i] = new AudioContext(); context.handles[i] = new AudioContext();
return sp; return i;
}) ~
| JSWORD: newAudioContext ( -- h )
r| JSWORD: createOscillator { audio_ctx -- h }
(function(sp) {
var audio_ctx = i32[sp>>2]; sp -= 4;
var i = context.AllotHandle(); var i = context.AllotHandle();
sp += 4; i32[sp>>2] = i;
context.handles[i] = context.handles[audio_ctx].createOscillator(); context.handles[i] = context.handles[audio_ctx].createOscillator();
return sp; return i;
}) ~
| JSWORD: createOscillator ( h -- h )
r| JSWORD: createGain { audio_ctx -- h }
(function(sp) {
var audio_ctx = i32[sp>>2]; sp -= 4;
var i = context.AllotHandle(); var i = context.AllotHandle();
sp += 4; i32[sp>>2] = i;
context.handles[i] = context.handles[audio_ctx].createGain(); context.handles[i] = context.handles[audio_ctx].createGain();
return sp; return i;
}) ~
| JSWORD: createGain ( h -- h )
r| JSWORD: createBiquadFilter { audio_ctx -- h }
(function(sp) {
var audio_ctx = i32[sp>>2]; sp -= 4;
var i = context.AllotHandle(); var i = context.AllotHandle();
sp += 4; i32[sp>>2] = i;
context.handles[i] = context.handles[audio_ctx].createBiquadFilter(); context.handles[i] = context.handles[audio_ctx].createBiquadFilter();
return sp; return i;
}) ~
| JSWORD: createBiquadFilter ( h -- h )
r| JSWORD: createBufferSource { audio_ctx -- h }
(function(sp) {
var audio_ctx = i32[sp>>2]; sp -= 4;
var i = context.AllotHandle(); var i = context.AllotHandle();
sp += 4; i32[sp>>2] = i;
context.handles[i] = context.handles[audio_ctx].createBufferSource(); context.handles[i] = context.handles[audio_ctx].createBufferSource();
return sp; return i;
}) ~
| JSWORD: createBufferSource ( h -- h )
forth definitions web forth definitions web