Verified Commit 9eb486d5 authored by Camil Staps's avatar Camil Staps 🙂

Add back functionality to store references to Clean values in JavaScript

parent 12da2412
......@@ -42,6 +42,7 @@ where
initUI :: !(JSObj ()) !*JSWorld -> *JSWorld
initUI comp w
# w = (jsGlobal "console.log" .$! (1,2,3)) w
# w = (comp .# "reversed_list" .= jsMakeCleanReference (MyReverse 1000)) w
# (v,w) = (jsGlobal "Math.floor" .$ 17) w
# (jsInitDOMEl,w) = jsWrapFun (initDOMEl comp) w
# w = (comp .# "initDOMEl" .= jsInitDOMEl) w
......@@ -51,7 +52,14 @@ where
where
initDOMEl :: !(JSObj ()) !{!JSVal a} !*JSWorld -> *JSWorld
initDOMEl comp _ w
# w = (comp .# "domEl.value" .= toJS (MyReverse 1000)) w
# (v,w) = jsGetCleanReference (comp .# "reversed_list") w
# v = case v of
Nothing -> "stored value not found?"
Just xs -> toString (last` xs)
with
last` :: ![Int] -> Int
last` xs = last xs
# w = (comp .# "domEl.value" .= toJS v) w
# w = (comp .# "afterInitDOM" .$! ()) w
= w
......@@ -68,8 +76,8 @@ where
# (s,vst) = serialize_in_vst val vst
-> (Ok (ui UITextField, val), vst)
MyReverse::Int -> Int
MyReverse n = last (Rev_n n [1..n])
MyReverse::Int -> [Int]
MyReverse n = Rev_n n [1..n]
where
Rev_n::Int [Int] -> [Int]
Rev_n 1 list = Rev list []
......
......@@ -14,6 +14,9 @@ from StdMaybe import :: Maybe
class toJS a :: !a -> JSVal b
instance toJS Int, Bool, String, (JSVal b), (Maybe b) | toJS b
jsMakeCleanReference :: a -> JSVal b
jsGetCleanReference :: !(JSVal a) !*JSWorld -> *(!Maybe b, !*JSWorld)
jsIsUndefined :: !(JSVal a) -> Bool
jsValToInt :: !(JSVal a) -> Maybe Int
......
......@@ -37,6 +37,21 @@ where
JSSel obj attr -> toString obj+++"["+++toString attr+++"]"
JSSelPath obj path -> toString obj+++"."+++path
jsMakeCleanReference :: a -> JSVal b
jsMakeCleanReference x = share x
jsGetCleanReference :: !(JSVal a) !*JSWorld -> *(!Maybe b, !*JSWorld)
jsGetCleanReference v w = case eval_js_with_return_value (toString v) of
JSCleanRef i -> (Just (fetch i), w)
_ -> (Nothing, w)
where
fetch :: !Int -> a
fetch _ = code {
create
instruction 4
pop_b 1
}
jsIsUndefined :: !(JSVal a) -> Bool
jsIsUndefined v = v=:JSUndefined
......@@ -149,9 +164,6 @@ wrapInitUIFunction f = \args
-> f r
-> abort "failed to get iTasks component from JavaScript\n"
referenceToJS :: !Int -> JSVal a
referenceToJS ref = JSRef ref
addCSSFromUrl :: !String !*JSWorld -> *JSWorld
addCSSFromUrl css w = case add_css css of
True -> w
......@@ -240,10 +252,23 @@ cast_value_from_js _ = code {
pop_a 1
jmp return
:return_ref
pushI 1 | for shiftr%
repl_r_args 0 1
push_b 0
pushI 1
and%
pushI 1
eqI
jmp_true return_clean_ref
shiftr%
fill_r e_iTasks.UI.JS.Interface_kJSRef 0 1 0 0 0
pop_b 1
jmp return
:return_clean_ref
shiftr%
fill_r e_iTasks.UI.JS.Interface_kJSCleanRef 0 1 0 0 0
pop_b 1
jmp return
:return
}
......@@ -253,7 +278,7 @@ where
get_shared_value_index :: !a -> Int
get_shared_value_index _ = code {
pushI 0 | to return the result
instruction 4
instruction 3
pop_a 1
}
......
......@@ -2,14 +2,9 @@
var MAX_INSTRUCTIONS=-1;
const JSWorld={
abc_type: 'JSWorld'
};
function SharedCleanValue(index) {
return {
abc_type: 'SharedCleanValue',
index: index
shared_clean_value_index: index
};
}
......@@ -77,20 +72,21 @@ const abc_interpreter={
shared_clean_values: [], // pointers to the Clean heap
apply_to_clean_value: function (index) {
return function () {
var f=function () {
var args=[];
for (var i=0; i<arguments.length; i++)
args[i]=arguments[i];
abc_interpreter.interpret(SharedCleanValue(index), args);
};
f.shared_clean_value_index=index;
return f;
},
copy_js_to_clean: function (values, asp, hp, hp_free) {
copy_js_to_clean: function (values, store_ptrs, hp, hp_free) {
for (var i=0; i<values.length; i++) {
asp+=8;
//console.log('copy',values[i]);
if (values[i]===null) {
abc_interpreter.memory_array[asp/4]=hp;
abc_interpreter.memory_array[store_ptrs/4]=hp;
abc_interpreter.memory_array[hp/4]=26*8+2; // INT
abc_interpreter.memory_array[hp/4+1]=0;
abc_interpreter.memory_array[hp/4+2]=0;
......@@ -98,7 +94,7 @@ const abc_interpreter={
hp+=16;
hp_free-=2;
} else if (typeof values[i]=='undefined') {
abc_interpreter.memory_array[asp/4]=hp;
abc_interpreter.memory_array[store_ptrs/4]=hp;
abc_interpreter.memory_array[hp/4]=26*8+2; // INT
abc_interpreter.memory_array[hp/4+1]=0;
abc_interpreter.memory_array[hp/4+2]=1;
......@@ -109,7 +105,7 @@ const abc_interpreter={
// TODO use small integers
// TODO check garbage collection
if (Number.isInteger(values[i])) {
abc_interpreter.memory_array[asp/4]=hp;
abc_interpreter.memory_array[store_ptrs/4]=hp;
abc_interpreter.memory_array[hp/4]=26*8+2; // INT
abc_interpreter.memory_array[hp/4+1]=0;
abc_interpreter.memory_array[hp/4+2]=values[i]; // TODO also support >32-bit
......@@ -120,7 +116,7 @@ const abc_interpreter={
throw 'Cannot pass non-integral numbers to Clean yet'; // TODO
}
} else if (typeof values[i]=='boolean') {
abc_interpreter.memory_array[asp/4]=hp;
abc_interpreter.memory_array[store_ptrs/4]=hp;
abc_interpreter.memory_array[hp/4]=11*8+2; // BOOL
abc_interpreter.memory_array[hp/4+1]=0;
abc_interpreter.memory_array[hp/4+2]=values[i] ? 1 : 0;
......@@ -128,7 +124,7 @@ const abc_interpreter={
hp+=16;
hp_free-=2;
} else if (typeof values[i]=='string') {
abc_interpreter.memory_array[asp/4]=hp;
abc_interpreter.memory_array[store_ptrs/4]=hp;
abc_interpreter.memory_array[hp/4]=6*8+2; // _STRING_
abc_interpreter.memory_array[hp/4+1]=0;
abc_interpreter.memory_array[hp/4+2]=values[i].length;
......@@ -142,7 +138,7 @@ const abc_interpreter={
hp+=16+(((values[i].length+7)>>3)<<3);
hp_free-=2+((values[i].length+7)>>3);
} else if (Array.isArray(values[i])) {
abc_interpreter.memory_array[asp/4]=hp;
abc_interpreter.memory_array[store_ptrs/4]=hp;
abc_interpreter.memory_array[hp/4]=2; // fake ARRAY, needed because we use jmp_ap
abc_interpreter.memory_array[hp/4+1]=0;
abc_interpreter.memory_array[hp/4+2]=hp+16;
......@@ -155,26 +151,21 @@ const abc_interpreter={
abc_interpreter.memory_array[hp/4+9]=0;
hp+=40;
hp_free-=5;
var copied=abc_interpreter.copy_js_to_clean(values[i], hp-8, hp+8*values[i].length, hp_free);
var copied=abc_interpreter.copy_js_to_clean(values[i], hp, hp+8*values[i].length, hp_free);
hp=copied.hp;
hp_free=copied.hp_free-values[i].length;
} else if ('abc_type' in values[i]) {
switch (values[i].abc_type) {
case 'SharedCleanValue':
abc_interpreter.memory_array[asp/4]=abc_interpreter.shared_clean_values[values[i].index];
break;
case 'JSWorld':
abc_interpreter.memory_array[asp/4]=(31+17*2)*8; // INT 17
break;
default:
throw ('unknown abc_type '+values[i].abc_type);
}
} else if ('shared_clean_value_index' in values[i]) {
abc_interpreter.memory_array[store_ptrs/4]=hp;
abc_interpreter.memory_array[hp/4]=661*8+2; // DOMNode type
abc_interpreter.memory_array[hp/4+1]=0;
abc_interpreter.memory_array[hp/4+2]=(values[i].shared_clean_value_index<<1)+1;
abc_interpreter.memory_array[hp/4+3]=0;
} else if (typeof values[i]=='object') {
// TODO: check if garbage collection is needed
abc_interpreter.memory_array[asp/4]=hp;
abc_interpreter.memory_array[store_ptrs/4]=hp;
abc_interpreter.memory_array[hp/4]=661*8+2; // DOMNode type
abc_interpreter.memory_array[hp/4+1]=0;
abc_interpreter.memory_array[hp/4+2]=abc_interpreter.shared_js_values.length;
abc_interpreter.memory_array[hp/4+2]=abc_interpreter.shared_js_values.length<<1;
abc_interpreter.memory_array[hp/4+3]=0;
abc_interpreter.shared_js_values.push(values[i]);
hp+=16;
......@@ -183,10 +174,12 @@ const abc_interpreter={
console.log(values[i]);
throw 'Could not pass the above value to Clean';
}
store_ptrs+=8;
}
return {
asp: asp,
store_ptrs: store_ptrs,
hp: hp,
hp_free: hp_free,
};
......@@ -284,17 +277,18 @@ abc_interpreter.loading_promise=fetch('js/app.pbc').then(function(resp){
var string=abc_interpreter.get_clean_string(abc_interpreter.memory_array[asp/4]);
console.log('eval',string);
var result=eval('('+string+')'); // the parentheses are needed for {}, for instance
var copied=abc_interpreter.copy_js_to_clean([result], asp-8, hp, hp_free);
var copied=abc_interpreter.copy_js_to_clean([result], asp, hp, hp_free);
abc_interpreter.interpreter.instance.exports.set_hp(copied.hp);
abc_interpreter.interpreter.instance.exports.set_hp_free(copied.hp_free);
break;
case 3: /* TODO: iTasks.UI.JS.Interface: store_js_value */
throw 'store_js_value';
break;
case 4: /* iTasks.UI.JS.Interface: share */
case 3: /* iTasks.UI.JS.Interface: share */
abc_interpreter.memory_array[bsp/4]=abc_interpreter.shared_clean_values.length;
abc_interpreter.shared_clean_values.push(abc_interpreter.memory_array[asp/4]);
break;
case 4: /* iTasks.UI.JS.Interface: fetch */
var index=abc_interpreter.memory_array[bsp/4];
abc_interpreter.memory_array[asp/4]=abc_interpreter.shared_clean_values[index];
break;
case 10: /* iTasks.UI.JS.Interface: add CSS */
var url=abc_interpreter.get_clean_string(abc_interpreter.memory_array[asp/4]);
var css=document.createElement('link');
......@@ -412,8 +406,12 @@ abc_interpreter.loading_promise=fetch('js/app.pbc').then(function(resp){
var hp=abc_interpreter.interpreter.instance.exports.get_hp();
var hp_free=abc_interpreter.interpreter.instance.exports.get_hp_free();
const copied=abc_interpreter.copy_js_to_clean([JSWorld, args, f], asp, hp, hp_free);
asp=copied.asp;
abc_interpreter.memory_array[asp/4]=(31+17*2)*8; // JSWorld: INT 17
abc_interpreter.memory_array[asp/4+2]=hp;
abc_interpreter.memory_array[asp/4+4]=abc_interpreter.shared_clean_values[f.shared_clean_value_index];
const copied=abc_interpreter.copy_js_to_clean([args], asp+8, hp, hp_free);
asp+=16;
hp=copied.hp;
hp_free=copied.hp_free;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment