2727 margin : 0 ;
2828 padding : 0 ;
2929 border : none;
30- + fieldset {margin-top : .5rem ;}
30+ + fieldset {margin-top : .5rem ;}
3131}
3232pre {
3333 overflow-y : scroll;
@@ -47,30 +47,48 @@ <h1>agda2lambox</h1>
4747 < button id ="run " disabled > Run</ button >
4848 < button id ="reload " disabled > Reload</ button >
4949 < button id ="clear "> Clear</ button >
50+ < input type ="file " id ="file " />
51+ </ fieldset >
52+ < fieldset >
53+ < label for ="useinput "> Input</ label >
54+ < input type ="checkbox " id ="useinput ">
55+ < input type ="text " id ="input ">
56+ < select id ="encoder ">
57+ < option value ="bool "> Bool</ option >
58+ </ select >
59+ </ fieldset >
60+ < fieldset >
61+ Output
5062 < select id ="decoder ">
5163 < option value ="nat "> Nat</ option >
5264 < option value ="bool "> Bool</ option >
5365 < option value ="listnat "> List Nat</ option >
5466 < option value ="listbool "> List Bool</ option >
5567 < option value ="string "> String (List Nat)</ option >
5668 </ select >
57- < input type ="file " id ="file " />
69+ </ fieldset >
70+ < fieldset >
71+ Function
72+ < select id ="program "> </ select >
5873 </ fieldset >
5974</ header >
6075< pre > < code id ="output "> </ code > </ pre >
6176< script type ="module ">
6277const on = ( t , e , f ) => t . addEventListener ( e , f )
6378
64- run . disabled = true
65- reload . disabled = true
79+ run . disabled = reload . disabled = true
80+ input . disabled = encoder . disabled = ! useinput . checked
81+ on ( useinput , "change" , ( ) => input . disabled = encoder . disabled = ! useinput . checked )
6682
67- let wasm = null
68- let mem = null
83+ let wasm = null
84+ let mem_ptr = null
85+ let mem = null
86+ let exposed = null
6987
7088on ( file , "change" , load )
7189on ( reload , "click" , load )
7290on ( run , "click" , exec )
73- on ( clear , "click" , ( ) => { output . innerHTML = "" } )
91+ on ( clear , "click" , ( ) => output . innerHTML = "" )
7492
7593async function load ( ) {
7694 if ( file . files . length == 0 ) return
@@ -84,13 +102,30 @@ <h1>agda2lambox</h1>
84102 wasm =
85103 await blob . arrayBuffer ( )
86104 . then ( buf => {
87- log ( "Compiling..." )
88- return WebAssembly . compile ( buf )
89- } )
105+ log ( "Compiling..." )
106+ return WebAssembly . compile ( buf )
107+ } )
90108 . then ( mod => new WebAssembly . Instance ( mod ) )
91109
110+ mem_ptr = wasm . exports . mem_ptr
111+ mem = wasm . exports . memory . buffer
112+
92113 log ( `Compiled!` )
93114
115+ exposed =
116+ Object . keys ( wasm . exports )
117+ . filter ( key => typeof wasm . exports [ key ] == 'function' )
118+
119+ // update available function list
120+ program . textContent = ''
121+ exposed . forEach ( fn => {
122+ let opt = document . createElement ( 'option' )
123+ opt . value = fn
124+ // show arity
125+ opt . textContent = `${ fn } (${ wasm . exports [ fn ] . length } )`
126+ program . appendChild ( opt )
127+ } )
128+
94129 run . disabled = false
95130 reload . disabled = false
96131
@@ -100,15 +135,24 @@ <h1>agda2lambox</h1>
100135}
101136
102137async function exec ( ) {
103- log ( "Running main_function()" )
138+ log ( `Running ${ program . value } ` )
139+
140+ let fn = wasm . exports [ program . value ]
104141
105142 try {
106- wasm . exports . main_function ( )
143+ if ( useinput . checked ) {
144+ let val = eval ( input . value )
145+ let enc = encoders [ encoder . value ]
146+ let res = enc ( val )
147+ fn ( res )
148+ }
149+ else {
150+ fn ( )
151+ }
107152
108- mem = new Uint32Array ( wasm . exports . memory . buffer )
109153 let res = wasm . exports . result . value
110154 let dec = decoders [ decoder . value ]
111- // mem = new Uint32Array(wasm.exports.memory.buffer)
155+
112156 log ( `Result: ${ pretty ( dec ( res ) ) } ` )
113157 } catch ( e ) {
114158 log ( `Failed to run: ${ e } ` , true )
@@ -137,7 +181,19 @@ <h1>agda2lambox</h1>
137181
138182// custom decoders -------------------------
139183
140- const bool = value => ( value >> 1 ) == 1
184+ /* "CertiCoq-Wasm’s representation of
185+ a 𝜆ANF constructor value 𝐶(𝑣s) is based on the one used by
186+ CertiCoq’s C backend [ 41, §4.1], which in turn is based on the
187+ one used by the OCaml compiler. For efficiency, we represent
188+ nullary constructor values as unboxed i32 values (using 31
189+ bits), while non-nullary constructor values are boxed: they
190+ are represented by an address starting from which linear
191+ memory contains the code of the constructor, followed by
192+ the arguments. The least significant bit of the i32 is used to
193+ distinguish the two."
194+ */
195+
196+ const bool = value => ( value >> 1 ) == 1
141197
142198const nat = value => {
143199 let acc = 0
@@ -170,6 +226,24 @@ <h1>agda2lambox</h1>
170226 , listbool : list ( bool )
171227 , string
172228 }
229+
230+ // custom encoders -------------------------------
231+
232+ /*
233+ NOTE: for now, encoders happily write in the memory buffer,
234+ and update the mem_ptr.
235+ TODO: proper memory mgmt, where the linear memory is expanded if
236+ we run out of memory.
237+
238+ - All encoders take a JS value as input,
239+ - They write it in memory starting from mem_ptr.
240+ - They update mem_ptr to point to the next available location.
241+ - They return a value to be given to programs.
242+ (Likely to be the a pointer, but not necessarily).
243+ */
244+ const encoders =
245+ { bool : v => v << 1 | 1
246+ }
173247</ script >
174248 </ body >
175249</ html >
0 commit comments