diff --git a/web/aslp.js b/web/aslp.js index b0e3a7a..41366e4 100644 --- a/web/aslp.js +++ b/web/aslp.js @@ -22,6 +22,7 @@ const inputError = get('#inputerror'); const goButton = get('#go'); const debugInput = get('#debug'); +const vectorCheckbox = get('#vectors'); const outputArea = get('#output'); const loadingText = get('#loading'); const downloadButton = get('#dl'); @@ -39,6 +40,25 @@ const parseIntSafe = (s, radix) => { return x; }; +/** Wraps the given async function, enforcing mutual exclusion across calls to this function. */ +const mutex = asyncfn => { + let prev = Promise.resolve(); + + const go = prev => async (...args) => { + try { await prev; } + finally { return asyncfn(...args); } + }; + + const wrapped = (...args) => { + // successive calls to the wrapped function are forced + // to wait for the completion of the (directly) prior call. + prev = go(prev)(...args); + return prev; + }; + + return wrapped; +}; + const _write = (isError) => s => requestAnimationFrame(() => { if (!s) return; @@ -115,7 +135,8 @@ export const shareLink = () => { * SEMANTICS BUTTON CLICK AND OUTPUT WRITING */ -export const submit = async () => { +export const submit = mutex(async () => { + // console.log('a') clearOutput(); try { @@ -128,7 +149,13 @@ export const submit = async () => { copyArea.value = url.toString(); - const arg = { opcode: previousOpcode, debug: parseInt(debugInput.value) }; + const flag = bool => bool ? '+' : '-'; + + const arg = { + opcode: previousOpcode, + debug: parseInt(debugInput.value), + flags: [`${flag(vectorCheckbox.checked)}dis:vectors`], // TODO: generalise to more flags + }; await worker.dis(arg); } catch (e) { @@ -141,8 +168,9 @@ export const submit = async () => { dl.disabled = false; clearButton.disabled = false; shareButton.disabled = false; + // console.log('b') } -}; +}); /** @@ -260,6 +288,7 @@ const init = async () => { if (urlData.get('bytes') != null) bytesInput.value = urlData.get('bytes'); if (urlData.get('asm') != null) asmInput.value = urlData.get('asm'); if (urlData.get('debug') != null) debugInput.value = urlData.get('debug'); + if (urlData.get('vectors') != null) vectorCheckbox.checked = urlData.get('vectors') === 'on'; } catch (exn) { console.error('exception during url loading:', exn); } diff --git a/web/index.html b/web/index.html index 821e2bd..ade8be7 100644 --- a/web/index.html +++ b/web/index.html @@ -30,7 +30,11 @@ margin-bottom: 0.5em; } - input[type="radio"], label, summary { + fieldset { + width: fit-content; + } + + input[type="radio"], label[for], summary { cursor: pointer; } @@ -70,15 +74,23 @@

ASLp Web

- Debug options -

- -

+ Additional options +
+

+
+ +
+

+

+
+ +

+

diff --git a/web/js.ml b/web/js.ml index 63c943e..22f86e1 100644 --- a/web/js.ml +++ b/web/js.ml @@ -36,7 +36,8 @@ let () = (object%js (* TODO: support stdin from javascript for repl, possibly converting asli repl to lwt *) method init (out : string -> unit) (err : string -> unit) = init (fun () -> "") out err - method printException (exn : exn) = Printexc.to_string exn; + method formatException (exn : exn) = Printexc.to_string exn + method printException (exn : exn) = output_string stderr (Printexc.to_string exn) method marshal = Lib.marshal (env ()) method unmarshal (x : Lib.js_uint8Array) = (cachedenv := Some (Lib.unmarshal x)) @@ -45,5 +46,7 @@ let () = method dis (x: string) = dis x method setDebugLevel i = (LibASL.Dis.debug_level := i) method setPrettyPrint (x : bool) = (print_pp := x) + method setFlags (flags: Js.js_string Js.t Js.js_array Js.t) = + Array.iter (fun x -> LibASL.Flags.set_flag @@ Js.to_string x) (Js.to_array flags) end) in () diff --git a/web/worker.js b/web/worker.js index 88d3692..bfeaaae 100644 --- a/web/worker.js +++ b/web/worker.js @@ -7,6 +7,7 @@ const formatOCamlExceptions = f => (...args) => { if (e instanceof Array) { // convert ocaml representation of errors into // javascript representation. + // XXX: deferring via setTimeout avoids returning this to the caller. setTimeout(() => { throw e; }, 0); } else { throw e; @@ -55,8 +56,11 @@ const methods = { unmarshal(arraybuf); }), - dis: formatOCamlExceptions(({ opcode, debug }) => { + dis: formatOCamlExceptions((args) => { + const { opcode, debug, flags } = args; libASL_web.setDebugLevel(debug); + libASL_web.setFlags(flags); + console.log('worker dis:', args); libASL_web.dis(opcode); }),