watr 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- var e=new RegExp([/(?<comment>;;.*|\(;[^]*?;\))/,/"(?<string>(?:\\"|[^"])*?)"/,/(?<param>offset|align|shared|funcref)=?/,/(?<hex>([+-]?nan:)?[+-]?0x[0-9a-f.p+-_]+)/,/(?<number>[+-]?inf|[+-]?nan|[+-]?\d[\d.e_+-]*)/,/(?<instr>[a-z][a-z0-9!#$%&'*+\-./:<=>?@\\^_`|~]+)/,/\$(?<label>[a-z0-9!#$%&'*+\-./:<=>?@\\^_`|~]+)/,/(?<lparen>\()|(?<rparen>\))|(?<nul>[ \t\n]+)|(?<error>.)/].map((e=>e.toString().slice(1,-1))).join("|"),"gi");function t(t){let n={},r={};const a=t.matchAll(e);function i(){const e=a.next();if(e.done)return{value:{value:null,kind:"eof",index:t.length},done:!0};const[n,r]=Object.entries(e.value.groups).filter((e=>null!=e[1]))[0];return{value:{value:r,kind:n,index:e.value.index},done:!1}}function s(){n=r;do{r=i().value}while("nul"===r.kind||"comment"===r.kind);return n}function l(e,t){if(e===r.kind){if(null==t)return s();if(t===r.value)return s()}return null}return{[Symbol.iterator](){return this},next:i,advance:s,peek:function(e,t){return null!=e?null!=t?t===r.value:e===r.kind:r},accept:l,expect:function(e,t){const n=l(e,t);if(!n)throw new SyntaxError("Unexpected token: "+r.value+"\n expected: "+e+(t?' "'+t+'"':"")+"\n but received: "+r.kind+"\n at position: "+r.index);return n},start:s}}function n({start:e,peek:t,accept:n,expect:r}){const a=new TextEncoder("utf-8");function i(){const e=[];for(;;){const t=n("string");if(!t)break;if("\\"===t.value[0]&&t.value[1].match(/[0-9a-f]/i)){const n=t.value.matchAll(/\\([0-9a-f]{1,2})/gi);for(const t of n)e.push(parseInt(t[1],16))}else t.value=t.value.replace(/\\n/,"\n"),e.push(...a.encode(t.value))}return e}function*s(){let e;for(;;)if(e=n("number"))e.value=e.value.replace(/_/g,""),yield{param:e};else if(e=n("hex"))e.value=e.value.replace(/_/g,""),yield{param:e};else if(e=n("string"))yield{param:e};else if(e=n("label"))yield{param:e};else{if(!(e=n("param")))break;{let t;if(t=n("number")){yield{param:e,value:t};continue}if(t=n("hex")){yield{param:e,value:t};continue}yield{param:e}}}}return e(),function e(){const a=n("label");if(a)return{ref:a};if(t("string"))return{data:i()};const l=n("lparen");let o;if(l)o=r("instr");else if(o=n("instr"),!o)return;const u={instr:o,name:n("label"),params:[...s()],children:[]};if(l){let n;for(;!t("eof")&&(n=e());)u.children.push(n);u.params.push(...s()),r("rparen")}else if("block"===o.value||"loop"===o.value){let n;for(;!t("eof")&&!t("instr","end")&&(n=e());)u.children.push(n);r("instr","end")}return u}()}function*r(e){var t;for(t=e,s.setBigInt64(0,t),e=s.getBigInt64(0);;){const t=Number(0x7Fn&e);if(0n===(e>>=7n)&&0==(64&t)||-1n===e&&0!=(64&t)){yield t;break}yield 128|t}}function*a(e){let t=0;const n=Math.ceil(Math.log2(Math.abs(e))),r=e<0;let a=!0;for(;a;)t=127&e,e>>=7,r&&(e|=-(1<<n-7)),0==e&&0==(64&t)||-1==e&&64==(64&t)?a=!1:t|=128,yield t}function*i(e,t=0){let n=0;do{n=127&e,(0!=(e>>=7)||t>0)&&(n|=128),yield n,t--}while(0!=e||t>-1)}var s=new DataView(new BigInt64Array(1).buffer);var l=0x8000000000000000n,o=0x7ff0000000000000n;var u={"type.i32":127,"type.i64":126,"type.f32":125,"type.f64":124,"type.void":64,"type.func":96,"type.funcref":112,"section.custom":0,"section.type":1,"section.import":2,"section.function":3,"section.table":4,"section.memory":5,"section.global":6,"section.export":7,"section.start":8,"section.element":9,"section.code":10,"section.data":11,"import.func":0,"import.table":1,"import.memory":2,"import.global":3,"export.function":0,"export.table":1,"export.memory":2,"export.global":3,"global.const":0,"global.var":1,"global.mut":1,"limits.min":0,"limits.minmax":1,"limits.shared":3},c=["unreachable","nop","block","loop","if","else",,,,,,"end","br","br_if","br_table","return","call","call_indirect",,,,,,,,,"drop","select",,,,,"local.get","local.set","local.tee","global.get","global.set",,,,"i32.load","i64.load","f32.load","f64.load","i32.load8_s","i32.load8_u","i32.load16_s","i32.load16_u","i64.load8_s","i64.load8_u","i64.load16_s","i64.load16_u","i64.load32_s","i64.load32_u","i32.store","i64.store","f32.store","f64.store","i32.store8","i32.store16","i64.store8","i64.store16","i64.store32","memory.size","memory.grow","i32.const","i64.const","f32.const","f64.const","i32.eqz","i32.eq","i32.ne","i32.lt_s","i32.lt_u","i32.gt_s","i32.gt_u","i32.le_s","i32.le_u","i32.ge_s","i32.ge_u","i64.eqz","i64.eq","i64.ne","i64.lt_s","i64.lt_u","i64.gt_s","i64.gt_u","i64.le_s","i64.le_u","i64.ge_s","i64.ge_u","f32.eq","f32.ne","f32.lt","f32.gt","f32.le","f32.ge","f64.eq","f64.ne","f64.lt","f64.gt","f64.le","f64.ge","i32.clz","i32.ctz","i32.popcnt","i32.add","i32.sub","i32.mul","i32.div_s","i32.div_u","i32.rem_s","i32.rem_u","i32.and","i32.or","i32.xor","i32.shl","i32.shr_s","i32.shr_u","i32.rotl","i32.rotr","i64.clz","i64.ctz","i64.popcnt","i64.add","i64.sub","i64.mul","i64.div_s","i64.div_u","i64.rem_s","i64.rem_u","i64.and","i64.or","i64.xor","i64.shl","i64.shr_s","i64.shr_u","i64.rotl","i64.rotr","f32.abs","f32.neg","f32.ceil","f32.floor","f32.trunc","f32.nearest","f32.sqrt","f32.add","f32.sub","f32.mul","f32.div","f32.min","f32.max","f32.copysign","f64.abs","f64.neg","f64.ceil","f64.floor","f64.trunc","f64.nearest","f64.sqrt","f64.add","f64.sub","f64.mul","f64.div","f64.min","f64.max","f64.copysign","i32.wrap_i64","i32.trunc_f32_s","i32.trunc_f32_u","i32.trunc_f64_s","i32.trunc_f64_u","i64.extend_i32_s","i64.extend_i32_u","i64.trunc_f32_s","i64.trunc_f32_u","i64.trunc_f64_s","i64.trunc_f64_u","f32.convert_i32_s","f32.convert_i32_u","f32.convert_i64_s","f32.convert_i64_u","f32.demote_f64","f64.convert_i32_s","f64.convert_i32_u","f64.convert_i64_s","f64.convert_i64_u","f64.promote_f32","i32.reinterpret_f32","i64.reinterpret_f64","f32.reinterpret_i32","f64.reinterpret_i64"],f={get_local:"local.get",set_local:"local.set",tee_local:"local.tee",get_global:"global.get",set_global:"global.set","i32.trunc_s/f32":"i32.trunc_f32_s","i32.trunc_u/f32":"i32.trunc_f32_u","i32.trunc_s/f64":"i32.trunc_f64_s","i32.trunc_u/f64":"i32.trunc_f64_u","i64.extend_s/i32":"i64.extend_i32_s","i64.extend_u/i32":"i64.extend_i32_u","i64.trunc_s/f32":"i64.trunc_f32_s","i64.trunc_u/f32":"i64.trunc_f32_u","i64.trunc_s/f64":"i64.trunc_f64_s","i64.trunc_u/f64":"i64.trunc_f64_u","f32.convert_s/i32":"f32.convert_i32_s","f32.convert_u/i32":"f32.convert_i32_u","f32.convert_s/i64":"f32.convert_i64_s","f32.convert_u/i64":"f32.convert_i64_u","f32.demote/f64":"f32.demote_f64","f64.convert_s/i32":"f64.convert_i32_s","f64.convert_u/i32":"f64.convert_i32_u","f64.convert_s/i64":"f64.convert_i64_s","f64.convert_u/i64":"f64.convert_i64_u","f64.promote/f32":"f64.promote_f32"};for(const[e,t]of c.entries())null!=t&&(u[t]=e);for(const e in f){const t=c.indexOf(f[e]);u[e]=t}var p={};for(const e in u){p[e]=d(e);const[t,n]=e.split(".");null!=n&&(u[t]=u[t]??{},u[t][n]=u[e],p[t]=p[t]??{},p[t][n]=d(e))}var m={"i32.load":4,"i64.load":8,"f32.load":4,"f64.load":8,"i32.load8_s":1,"i32.load8_u":1,"i32.load16_s":2,"i32.load16_u":2,"i64.load8_s":1,"i64.load8_u":1,"i64.load16_s":2,"i64.load16_u":2,"i64.load32_s":4,"i64.load32_u":4,"i32.store":4,"i64.store":8,"f32.store":4,"f64.store":8,"i32.store8":1,"i32.store16":2,"i64.store8":1,"i64.store16":2,"i64.store32":4};function d(e){return function(t,n){return function*(e,t=[],n=[]){for(let e of n)if("number"==typeof e)yield e;else yield*e;yield u[e];for(let n of t)switch(typeof n){case"bigint":yield*r(n);break;case"number":yield*(h[e]??a)(n);break;default:yield*n}}(e,null==t||Array.isArray(t)?t:[t],null==n||Array.isArray(n)?n:[n])}}var h={"f64.const":function*(e){s.setFloat64(0,e);for(let e=8;e--;)yield s.getUint8(e)},"f32.const":function*(e){s.setFloat32(0,e);for(let e=4;e--;)yield s.getUint8(e)}};var _=new TextEncoder("utf-8");function g(e){return[..._.encode(e)]}function v(e,t){return[u.section[e],...i(t.length),...t]}function b(e){return[...i(e.length),...e.flat()]}function y(e){const t=[];let n,r=[];for(const a of e)a!==n&&r.length&&(t.push([...i(r.length),u.type[r[0]]]),r=[]),r.push(a),n=a;return r.length&&t.push([...i(r.length),u.type[r[0]]]),t}function x(e,t,n){return null!=n?[u.limits.shared,...i(e),...i(t)]:null!=t?[u.limits.minmax,...i(e),...i(t)]:[u.limits.min,...i(e)]}v.type=function(e){return v("type",b(e.map((([e,t])=>[u.type.func,...b(e.map((e=>u.type[e]))),...b(t.map((e=>u.type[e])))]))))},v.import=function(e){return v("import",b(e.map((([e,t,n,r])=>[...b(g(e)),...b(g(t)),u.import[n],...{func:()=>r.map((e=>[...i(e)])),memory:()=>x(...r)}[n]()]))))},v.function=function(e){return v("function",b(e.map((e=>[...i(e)]))))},v.table=function(e){return v("table",b(e.map((([e,t,n])=>[u.type[e],...x(t,n)]))))},v.memory=function(e){return v("memory",b(e.map((([e,t])=>x(e,t)))))},v.global=function(e){return v("global",b(e.map((([e,t,n])=>[u.type[t],u.global[e],...n,u.end]))))},v.export=function(e){return v("export",b(e.map((([e,t,n])=>[...b(g(e)),u.export[t],...i(n)]))))},v.start=function(e){return v("start",[...i(e)])},v.element=function(e){return v("element",b(e.map((([e,t,n])=>[...i(e),...t,u.end,...b(n)]))))},v.code=function(e){return v("code",b(e.map((([e,t])=>b([...b(y(e)),...t,u.end])))))},v.data=function(e){return v("data",b(e.map((([e,t,n])=>[...i(e),...t,u.end,...b(n)]))))};var k=class extends Array{log=[];write(e,t){return this.log.push(e,t),this.push(...e),this}get buffer(){return new Uint8Array(this)}};function w(e,t,n){const a=new class{types=[];imports=[];tables=[];memories=[];globals=[];exports=[];starts="";elements=[];codes=[];datas=[];constructor(e){e&&Object.assign(this,e)}get funcs(){return this.codes.filter((e=>!e.imported))}ensureType(e,t){const n=[e.join(" "),t.join(" ")].join(),r=this.types.indexOf(n);return r>=0?r:this.types.push(n)-1}getGlobalIndexOf(e){return this.globals.find((t=>t.name===e)).idx}getFunc(e){return this.codes.find((t=>t.name===e))}getMemory(e){return this.memories.find((t=>t.name===e))}getType(e){return this.types[e]}type(e,t,n){return this.types[e]=this.ensureType(t,n),this}import(e,t,n,r,a,i){if("func"===e){const s=this._func(t,a,i,[],[],!1,!0);this.imports.push({mod:n,field:r,type:e,desc:[s.type_idx]})}else"memory"===e&&this.imports.push({mod:n,field:r,type:e,desc:a});return this}table(e,t,n){return this.tables.push({type:e,min:t,max:n}),this}memory(e,t,n){return this.memories.push({name:e,min:t,max:n}),this}global(e,t,n,r){const a=this.globals.length;return this.globals.push({idx:a,name:e,valtype:n,mut:t,expr:r}),this}export(e,t,n){return this.exports.push({type:e,name:t,export_name:n}),this}start(e){return this.starts=e,this}elem(e,t){return this.elements.push({offset_idx_expr:e,codes:t}),this}_func(e,t=[],n=[],r=[],a=[],i=!1,s=!1){const l=this.ensureType(t,n),o={idx:this.codes.length,name:e,type_idx:l,locals:r,body:a,imported:s};return this.codes.push(o),i&&this.export("func",e,e),o}func(...e){return this._func(...e),this}data(e,t){return this.datas.push({offset_idx_expr:e,bytes:t}),this}build({metrics:e=!0}={}){e&&console.time("module build");const t=new k;return t.write([...g("\0asm"),1,0,0,0]),this.types.length&&t.write(v.type(this.types.map((e=>e.split(",").map((e=>e.split(" ").filter(Boolean))))))),this.imports.length&&t.write(v.import(this.imports.map((e=>[e.mod,e.field,e.type,e.desc])))),this.funcs.length&&t.write(v.function(this.funcs.map((e=>e.type_idx)))),this.elements.length&&t.write(v.table(this.tables.map((e=>[e.type,e.min,e.max])))),this.memories.length&&t.write(v.memory(this.memories.map((e=>[e.min,e.max])))),this.globals.length&&t.write(v.global(this.globals.map((e=>[e.mut,e.valtype,e.expr])))),this.exports.length&&t.write(v.export(this.exports.map((e=>"func"===e.type?[e.export_name,e.type,this.getFunc(e.name).idx]:"memory"===e.type?[e.export_name,e.type,this.getMemory(e.name).idx]:[])))),this.starts.length&&t.write(v.start(this.getFunc(this.starts).idx)),this.elements.length&&t.write(v.element(this.elements.map((e=>[0,e.offset_idx_expr,e.codes.map((e=>this.getFunc(e).idx))])))),this.funcs.length&&t.write(v.code(this.funcs.map((e=>[e.locals,e.body])))),this.datas.length&&t.write(v.data(this.datas.map((e=>[0,e.offset_idx_expr,e.bytes])))),e&&console.timeEnd("module build"),t}}(t),u=new class{globals=[];types=[];funcs=[];constructor(e){e&&Object.assign(this,e)}lookup(e,t){let n;switch(t){case"call":n=this.funcs.map((e=>e.name)).lastIndexOf(e);break;case"type":n=this.types.map((e=>e.name)).lastIndexOf(e);break;default:n=this.globals.map((e=>e.name)).lastIndexOf(e)}return i(n)}}(n),c=[];function f(e,t=u,n="i32"){switch(e.kind){case"number":if("inf"===e.value||"+inf"===e.value)return 1/0;if("-inf"===e.value)return-1/0;if("nan"===e.value||"+nan"===e.value)return NaN;if("-nan"===e.value)return NaN;if("f"===n?.[0])return parseFloat(e.value);case"hex":{let t;return 0===n.indexOf("i64")?(t="-"===e.value[0]?-BigInt(e.value.slice(1)):BigInt(e.value),t):"f"===n[0]?(t=e.value.indexOf("nan")>=0?0===n.indexOf("f32")?function*(e){let t=parseInt(e.split("nan:")[1]);t|=2139095040,"-"===e[0]&&(t|=2147483648),s.setInt32(0,t);for(let e=4;e--;)yield s.getUint8(e)}(e.value):function*(e){let t=BigInt(e.split("nan:")[1]);t|=o,"-"===e[0]&&(t|=l),s.setBigInt64(0,t);for(let e=8;e--;)yield s.getUint8(e)}(e.value):function(e){const t=(e=e.toUpperCase()).indexOf("P");let n,r;-1!==t?(n=e.substring(0,t),r=parseInt(e.substring(t+1))):(n=e,r=0);const a=n.indexOf(".");if(-1!==a){let e=parseInt(n.substring(0,a),16);const t=Math.sign(e);e*=t;const r=n.length-a-1,i=parseInt(n.substring(a+1),16),s=r>0?i/Math.pow(16,r):0;n=0===t?0===s?t:Object.is(t,-0)?-s:s:t*(e+s)}else n=parseInt(n,16);return n*(-1!==t?Math.pow(2,r):1)}(e.value),t):parseInt(e.value)}case"label":return t.lookup(e.value,n);default:return e.value}}class d{locals=[];depth=[];lookup(e,t){let n;switch(t){case"br":case"br_table":case"br_if":n=this.depth.lastIndexOf(e),~n&&(n=this.depth.length-1-n);break;default:n=this.locals.lastIndexOf(e)}return~n?i(n):u.lookup(e,t)}}function h(e,t,n){if(!(e in p)||"function"!=typeof p[e])throw new Error("Unknown instruction: "+e);return[...p[e](t,n)]}function _(e,t=u){const n={offset:0,align:0},s=e.instr.value;switch(s){case"type":return a.getType(e.name.value);case"call_indirect":{const n=[_(e.children.shift(),t),0],r=e.children.flatMap((e=>_(e,t)));return h(s,n,r)}case"memory.grow":{const n=[0],r=e.children.flatMap((e=>_(e,t)));return h(s,n,r)}case"i32.load":case"i64.load":case"f32.load":case"f64.load":case"i32.load8_s":case"i32.load8_u":case"i32.load16_s":case"i32.load16_u":case"i64.load8_s":case"i64.load8_u":case"i64.load16_s":case"i64.load16_u":case"i64.load32_s":case"i64.load32_u":case"i32.store":case"i64.store":case"f32.store":case"f64.store":case"i32.store8":case"i32.store16":case"i64.store8":case"i64.store16":case"i64.store32":{n.align=m[s];for(const t of e.params)n[t.param.value]=f(t.value);const a=[Math.log2(n.align),n.offset].map((e=>"number"==typeof e?i(e):"bigint"==typeof e?r(e):void 0)),l=e.children.flatMap((e=>_(e,t)));return h(s,a,l)}case"func":{const t={name:e.name?.value??u.funcs.length,params:[],results:[]};u.funcs.push(t);for(const n of e.children)switch(n.instr.value){case"param":t.params.push(...n.children.map((e=>e.instr.value)));break;case"result":t.results.push(...n.children.map((e=>e.instr.value)))}return[t.name,t.params,t.results]}case"result":return e.children.flatMap((e=>p.type[e.instr.value]()));case"else":case"then":return e.children.flatMap((e=>_(e,t)));case"if":{const n=e.name?.value??t.depth.length,r=[],a=[];let i;t.depth.push(n);for(const n of e.children)switch(n.instr.value){case"result":r.push(_(n,t));break;case"else":a.push(...p.else());case"then":a.push(_(n,t));break;default:i=_(n,t)}return t.depth.pop(),r.length||r.push(p.type.void()),[...p.if(r.flat(),i),...a.flat(),...p.end()]}case"loop":case"block":{const n=e.name?.value??t.depth.length,r=[],a=[];t.depth.push(n);for(const n of e.children)if("result"===n.instr.value)r.push(_(n,t));else a.push(_(n,t));return t.depth.pop(),r.length||r.push(p.type.void()),[...p[s](),...r.flat().map((e=>[...e])),...a.flat(),...p.end()]}case"br_table":{e.name&&e.params.unshift({param:{value:t.lookup(e.name.value,s)}});const n=e.params.map((e=>f(e.param,t,s))),r=e.children.flatMap((e=>_(e,t)));return h(s,[n.length-1,...n],r)}default:{e.name&&e.params.unshift({param:{value:(s.startsWith("global")?u:t).lookup(e.name.value,s)}});const n=e.params.map((e=>f(e.param,t,s))),r=e.children.flatMap((e=>_(e,t)));return h(s,n,r)}}}return function e(t){switch(t.instr.value){case"module":t.children.forEach((t=>e(t)));break;case"memory":{const e=t.name?.value??a.memories.length,n=t.params.map((e=>f(e.param))).flat();if("export"===t.children?.[0]?.instr.value){const e=t.children[0].params[0].param.value,n=t.children[0].name?.value??0;a.export("memory",n,e)}a.memory(e,...n)}break;case"data":{const e=t.children.shift(),n=t.children.shift().data;a.data(_(e),n)}break;case"start":a.start(t.name.value);break;case"table":{const e=t.params.map((e=>f(e.param)));e.unshift(e.pop()),a.table(...e)}break;case"elem":{const e=t.children.shift(),n=t.children.map((e=>e.ref.value));a.elem(_(e),n)}break;case"import":if("func"===t.children[0].instr.value){const e=t.params.map((e=>f(e.param))),n=_(t.children[0]),r=n.shift();a.import("func",r,...e,...n)}else if("memory"===t.children[0].instr.value){const e=t.children[0],n=t.params.map((e=>f(e.param))),r=e.instr.name,i=e.params.map((e=>f(e.param)));a.import("memory",r,...n,i)}break;case"global":{const e={name:t.name?.value??a.globals.length,vartype:"const",type:t.children[0].instr.value};u.globals.push(e),"mut"===e.type&&(e.vartype="var",e.type=t.children[0].children[0].instr.value);const n=t.children[1];a.global(e.name,e.vartype,e.type,_(n))}break;case"type":{const e={name:t.name?.value??a.types.length,params:[],results:[]};u.types.push(e);for(const n of t.children[0].children)switch(n.instr.value){case"param":e.params.push(...n.children.map((e=>e.instr.value)));break;case"result":e.results.push(...n.children.map((e=>e.instr.value)))}a.type(e.name,e.params,e.results)}break;case"export":{const e={name:t.params[0].param.value};e.type=t.children[0].instr.value,e.internal_name=t.children[0].name.value,a.export(e.type,e.internal_name,e.name)}break;case"func":{const e={name:t.name?.value??u.funcs.length,context:new d,params:[],results:[],locals:[],body:[]};u.funcs.push(e);for(const n of t.children)switch(n.instr.value){case"export":{const t=n.params[0].param.value;a.export("func",e.name,t)}break;case"local":e.locals.push(...n.children.map((e=>e.instr.value))),e.context.locals.push(...n.children.map((()=>n.name?.value)));break;case"param":e.params.push(...n.children.map((e=>e.instr.value))),e.context.locals.push(...n.children.map((()=>n.name?.value)));break;case"result":e.results.push(...n.children.map((e=>e.instr.value)));break;default:e.body.push(n)}c.push((()=>{a.func(e.name,e.params,e.results,e.locals,[...e.body.flatMap((t=>_(t,e.context)))])}))}}}(e),c.forEach((e=>e())),{module:a,global:u}}function I(e,r,a={}){return w(n(t("(module "+e+")")),a.module,a.global).module.build(r).buffer}export{w as compile,I as default,n as parse,t as tokenize};
package/plan.md DELETED
@@ -1,21 +0,0 @@
1
-
2
- ## plan
3
-
4
- * [x] Basic compilation examples from wasm book
5
- * [x] Make sure they're compilable
6
- * [x] Parsing samples from wat-compiler
7
- * [x] Remove subscript, use own parsing loop
8
- * [x] Avoid duplicating function signatures
9
- * [x] Compilation samples from wat-compiler
10
- * [ ] Examples tests - existing & wat-compiler ones (ideally find failing table)
11
- * [x] Normalize tree in parser, not in compiler - keep compiler small & fast
12
- * [x] Basic parsing instructions from mdn & examples
13
- * [x] Benchmark against wabt, wat-compiler
14
- * [x] Build script
15
- * [x] Test: assert function;
16
- * [x] make sure compiler doesn't modify tree
17
-
18
- ## Backlog
19
-
20
- * make repl support switch of compiler
21
- * wat-based wat-compiler
package/repl.html DELETED
@@ -1,44 +0,0 @@
1
- <!DOCTYPE html>
2
-
3
- <style>
4
- *{box-sizing: border-box}
5
- html, body {height: 100%; margin: 0}
6
- </style>
7
-
8
- <body style="display: flex; flex-direction: column;">
9
- <textarea id="wat" style="display: block; flex-grow: 1;">
10
- (module
11
- (global $g0 (mut i32) (i32.const 1))
12
- )
13
- </textarea>
14
- <div id="log" style="height: 50%;"></div>
15
-
16
- <script type="module">
17
- import Wabt from './lib/wabt.js'
18
-
19
- let wabt = await Wabt()
20
- let textarea = document.getElementById('wat'),
21
- errarea = document.getElementById('log')
22
-
23
- textarea.onchange = () => {
24
- compile(textarea.value)
25
- }
26
- compile(textarea.value)
27
-
28
- function compile(code) {
29
- errarea.textContent = ''
30
- try {
31
- var wasmModule = wabt.parseWat('', code)
32
- let wasmBinary = wasmModule.toBinary({log: true})
33
- const mod = new WebAssembly.Module(wasmBinary.buffer)
34
- // const instance = new WebAssembly.Instance(mod)
35
- // console.log(instance)
36
- }
37
- catch (e) {
38
- console.error(e)
39
- errarea.textContent = e
40
- }
41
- }
42
- </script>
43
- </body>
44
-
package/src/compile.js DELETED
@@ -1,456 +0,0 @@
1
- // ref: https://github.com/stagas/wat-compiler/blob/main/lib/const.js
2
- // NOTE: squashing into a string doesn't save up gzipped size
3
- const OP = [
4
- 'unreachable', 'nop', 'block', 'loop', 'if', 'else', ,,,,,
5
- 'end', 'br', 'br_if', 'br_table', 'return', 'call', 'call_indirect', ,,,,,,,,
6
- 'drop', 'select', ,,,,
7
- 'local.get', 'local.set', 'local.tee', 'global.get', 'global.set', ,,,
8
- 'i32.load', 'i64.load', 'f32.load', 'f64.load',
9
- 'i32.load8_s', 'i32.load8_u', 'i32.load16_s', 'i32.load16_u',
10
- 'i64.load8_s', 'i64.load8_u', 'i64.load16_s', 'i64.load16_u', 'i64.load32_s', 'i64.load32_u',
11
- 'i32.store', 'i64.store', 'f32.store', 'f64.store',
12
- 'i32.store8', 'i32.store16', 'i64.store8', 'i64.store16', 'i64.store32',
13
- 'memory.size', 'memory.grow',
14
- 'i32.const', 'i64.const', 'f32.const', 'f64.const',
15
- 'i32.eqz', 'i32.eq', 'i32.ne', 'i32.lt_s', 'i32.lt_u', 'i32.gt_s', 'i32.gt_u', 'i32.le_s', 'i32.le_u', 'i32.ge_s', 'i32.ge_u',
16
- 'i64.eqz', 'i64.eq', 'i64.ne', 'i64.lt_s', 'i64.lt_u', 'i64.gt_s', 'i64.gt_u', 'i64.le_s', 'i64.le_u', 'i64.ge_s', 'i64.ge_u',
17
- 'f32.eq', 'f32.ne', 'f32.lt', 'f32.gt', 'f32.le', 'f32.ge',
18
- 'f64.eq', 'f64.ne', 'f64.lt', 'f64.gt', 'f64.le', 'f64.ge',
19
- 'i32.clz', 'i32.ctz', 'i32.popcnt', 'i32.add', 'i32.sub', 'i32.mul', 'i32.div_s', 'i32.div_u', 'i32.rem_s', 'i32.rem_u', 'i32.and', 'i32.or', 'i32.xor', 'i32.shl', 'i32.shr_s', 'i32.shr_u', 'i32.rotl', 'i32.rotr',
20
- 'i64.clz', 'i64.ctz', 'i64.popcnt', 'i64.add', 'i64.sub', 'i64.mul', 'i64.div_s', 'i64.div_u', 'i64.rem_s', 'i64.rem_u', 'i64.and', 'i64.or', 'i64.xor', 'i64.shl', 'i64.shr_s', 'i64.shr_u', 'i64.rotl', 'i64.rotr',
21
- 'f32.abs', 'f32.neg', 'f32.ceil', 'f32.floor', 'f32.trunc', 'f32.nearest', 'f32.sqrt', 'f32.add', 'f32.sub', 'f32.mul', 'f32.div', 'f32.min', 'f32.max', 'f32.copysign',
22
- 'f64.abs', 'f64.neg', 'f64.ceil', 'f64.floor', 'f64.trunc', 'f64.nearest', 'f64.sqrt', 'f64.add', 'f64.sub', 'f64.mul', 'f64.div', 'f64.min', 'f64.max', 'f64.copysign',
23
- 'i32.wrap_i64',
24
- 'i32.trunc_f32_s', 'i32.trunc_f32_u', 'i32.trunc_f64_s', 'i32.trunc_f64_u', 'i64.extend_i32_s', 'i64.extend_i32_u',
25
- 'i64.trunc_f32_s', 'i64.trunc_f32_u', 'i64.trunc_f64_s', 'i64.trunc_f64_u',
26
- 'f32.convert_i32_s', 'f32.convert_i32_u', 'f32.convert_i64_s', 'f32.convert_i64_u', 'f32.demote_f64',
27
- 'f64.convert_i32_s', 'f64.convert_i32_u', 'f64.convert_i64_s', 'f64.convert_i64_u', 'f64.promote_f32',
28
- 'i32.reinterpret_f32', 'i64.reinterpret_f64', 'f32.reinterpret_i32', 'f64.reinterpret_i64',
29
- ],
30
- SECTION = { type:1, import:2, func:3, table:4, memory:5, global:6, export:7, start:8, elem:9, code:10, data:11 },
31
- TYPE = { i32:0x7f, i64:0x7e, f32:0x7d, f64:0x7c, void:0x40, func:0x60, funcref:0x70 },
32
- KIND = { func: 0, table: 1, memory: 2, global: 3 },
33
- ALIGN = {
34
- 'i32.load': 4, 'i64.load': 8, 'f32.load': 4, 'f64.load': 8,
35
- 'i32.load8_s': 1, 'i32.load8_u': 1, 'i32.load16_s': 2, 'i32.load16_u': 2,
36
- 'i64.load8_s': 1, 'i64.load8_u': 1, 'i64.load16_s': 2, 'i64.load16_u': 2, 'i64.load32_s': 4, 'i64.load32_u': 4, 'i32.store': 4,
37
- 'i64.store': 8, 'f32.store': 4, 'f64.store': 8,
38
- 'i32.store8': 1, 'i32.store16': 2, 'i64.store8': 1, 'i64.store16': 2, 'i64.store32': 4,
39
- }
40
- OP.map((op,i)=>OP[op]=i) // init op names
41
-
42
- // convert wat tree to wasm binary
43
- export default (nodes) => {
44
- // IR. Alias is stored directly to section array by key, eg. section.func.$name = idx
45
- let sections = {
46
- type: [], import: [], func: [], table: [], memory: [], global: [], export: [], start: [], elem: [], code: [], data: []
47
- }, binary = [
48
- 0x00, 0x61, 0x73, 0x6d, // magic
49
- 0x01, 0x00, 0x00, 0x00, // version
50
- ]
51
-
52
- // (func) → [(func)]
53
- if (typeof nodes[0] === 'string' && nodes[0] !== 'module') nodes = [nodes]
54
-
55
- // build nodes in order of sections, to properly initialize indexes/aliases
56
- // must come separate from binary builder: func can define types etc.
57
- for (let name in sections) {
58
- let remaining = []
59
- for (let node of nodes) node[0] === name ? build[name](node, sections) : remaining.push(node)
60
- nodes = remaining
61
- }
62
-
63
- // console.log(sections)
64
- // build binary sections
65
- for (let name in sections) {
66
- let items=sections[name]
67
- if (items.importc) items = items.slice(items.importc) // discard imported functions
68
- if (!items.length) continue
69
- let sectionCode = SECTION[name], bytes = []
70
- if (sectionCode!==8) bytes.push(items.length) // skip start section count
71
- for (let item of items) bytes.push(...item)
72
- binary.push(sectionCode, ...uleb(bytes.length), ...bytes)
73
- }
74
-
75
- return new Uint8Array(binary)
76
- }
77
-
78
- const build = {
79
- // (type $name? (func (param $x i32) (param i64 i32) (result i32 i64)))
80
- // signature part is identical to function
81
- // FIXME: handle non-function types
82
- type([, typeName, decl], ctx) {
83
- if (typeName[0]!=='$') decl=typeName, typeName=null
84
- let params = [], result = [], [kind,...sig] = decl, idx, bytes
85
-
86
- if (kind==='func') {
87
- // collect params
88
- while (sig[0]?.[0] === 'param') {
89
- let [, ...types] = sig.shift()
90
- if (types[0]?.[0] === '$') params[types.shift()] = params.length
91
- params.push(...types.map(t => TYPE[t]))
92
- }
93
-
94
- // collect result type
95
- if (sig[0]?.[0] === 'result') result = sig.shift().slice(1).map(t => TYPE[t])
96
-
97
- // reuse existing type or register new one
98
- bytes = [TYPE.func, ...uleb(params.length), ...params, ...uleb(result.length), ...result]
99
-
100
- idx = ctx.type.findIndex((prevType) => prevType.every((byte, i) => byte === bytes[i]))
101
- if (idx < 0) idx = ctx.type.push(bytes)-1
102
- }
103
-
104
- if (typeName) ctx.type[typeName] = idx
105
-
106
- return [idx, params, result]
107
- },
108
-
109
- // (func $name? ...params result ...body)
110
- func([,...body], ctx) {
111
- let idx=ctx.func.length, // fn index comes after impoted fns
112
- locals=[], // list of local variables
113
- callstack=[]
114
-
115
- // fn name
116
- if (body[0]?.[0] === '$') ctx.func[body.shift()] = idx
117
-
118
- // export binding
119
- if (body[0]?.[0] === 'export') build.export([...body.shift(), ['func', idx]], ctx)
120
-
121
- // register type
122
- let [typeIdx, params, result] = build.type([,['func',...body]], ctx)
123
- // FIXME: try merging with build.type: it should be able to consume body
124
- while (body[0]?.[0] === 'param' || body[0]?.[0] === 'result') body.shift()
125
- ctx.func.push([typeIdx])
126
-
127
- // collect locals
128
- while (body[0]?.[0] === 'local') {
129
- let [, ...types] = body.shift(), name
130
- if (types[0][0]==='$')
131
- params[name=types.shift()] ? err('Ambiguous name '+name) :
132
- locals[name] = params.length + locals.length
133
- locals.push(...types.map(t => TYPE[t]))
134
- }
135
-
136
- // map code instruction into bytes: [args, opCode, immediates]
137
- const instr = ([op, ...nodes]) => {
138
- if (op.length===1) err(`Inline instructions are not supported \`${op+nodes.join('')}\``)
139
-
140
- let opCode = OP[op], argc=0, args=[], imm=[], id
141
-
142
- // NOTE: we could reorganize ops by groups and detect signature as `op in STORE`
143
- // but numeric comparison is faster than generic hash lookup
144
- // FIXME: we often use OP.end or alike: what if we had list of global constants?
145
-
146
- // binary/unary
147
- if (opCode>=69) {
148
- argc = opCode>=167 ||
149
- (opCode<=159 && opCode>=153) ||
150
- (opCode<=145 && opCode>=139) ||
151
- (opCode<=123 && opCode>=121) ||
152
- (opCode<=105 && opCode>=103) ||
153
- opCode==80 || opCode==69 ? 1 : 2
154
- }
155
- // instruction
156
- else {
157
- // (i32.store align=n offset=m at value)
158
- if (opCode>=40&&opCode<=62) {
159
- // FIXME: figure out point in Math.log2 aligns
160
- let o = {align: ALIGN[op], offset: 0}, p
161
- while (nodes[0]?.[0] in o) p = nodes.shift(), o[p[0]] = +p[1]
162
- imm = [Math.log2(o.align), o.offset]
163
- argc = opCode >= 54 ? 2 : 1
164
- }
165
-
166
- // (i32.const 123)
167
- else if (opCode>=65&&opCode<=68) imm = opCode < 67 ? leb(nodes.shift()) : (opCode==67 ? f32 : f64)(nodes.shift())
168
-
169
- // (local.get $id), (local.tee $id x)
170
- else if (opCode>=32&&opCode<=34) {
171
- imm = uleb(nodes[0]?.[0]==='$' ? params[id=nodes.shift()] || locals[id] : nodes.shift())
172
- if (opCode>32) argc = 1
173
- }
174
-
175
- // (global.get id), (global.set id)
176
- else if (opCode==35||opCode==36) {
177
- imm = uleb(nodes[0]?.[0]==='$' ? ctx.global[nodes.shift()] : nodes.shift())
178
- if (opCode>35) argc = 1
179
- }
180
-
181
- // (call id ...nodes)
182
- else if (opCode==16) {
183
- imm = uleb(id = nodes[0]?.[0]==='$' ? ctx.func[nodes.shift()] : nodes.shift());
184
- // FIXME: how to get signature of imported function
185
- [,argc] = ctx.type[ctx.func[id][0]]
186
- }
187
-
188
- // (call_indirect (type $typeName) (idx) ...nodes)
189
- else if (opCode==17) {
190
- let typeId = nodes.shift()[1];
191
- [,argc] = ctx.type[typeId = typeId[0]==='$'?ctx.type[typeId]:typeId]
192
- argc++
193
- imm = uleb(typeId), imm.push(0) // extra immediate indicates table idx (reserved)
194
- }
195
-
196
- // FIXME (memory.grow $idx?)
197
- else if (opCode==63||opCode==64) {
198
- imm = [0]
199
- argc = 1
200
- }
201
-
202
- // (if (result i32)? (local.get 0) (then a b) (else a b)?)
203
- else if (opCode==4) {
204
- callstack.push(opCode)
205
- let [,type] = nodes[0][0]==='result' ? nodes.shift() : [,'void']
206
- imm=[TYPE[type]]
207
- argc = 0, args.push(...instr(nodes.shift()))
208
- let body
209
- if (nodes[0][0]==='then') [,...body] = nodes.shift(); else body = nodes
210
- while (body.length) imm.push(...instr(body.shift()))
211
-
212
- callstack.pop(), callstack.push(OP.else)
213
- if (nodes[0]?.[0]==='else') {
214
- [,...body] = nodes.shift()
215
- imm.push(OP.else, ...body.flatMap(instr))
216
- }
217
- callstack.pop()
218
- imm.push(OP.end)
219
- }
220
-
221
- // (drop arg), (return arg), (end arg)
222
- else if (opCode==0x1a || opCode==0x0f || opCode==0x0b) { argc = 1 }
223
-
224
- // (select a b cond)
225
- else if (opCode==0x1b) { argc = 3 }
226
-
227
- // (block ...), (loop ...)
228
- else if (opCode==2||opCode==3) {
229
- callstack.push(opCode)
230
- if (nodes[0]?.[0]==='$') (callstack[nodes.shift()] = callstack.length)
231
- let [,type] = nodes[0]?.[0]==='result' ? nodes.shift() : [,'void']
232
- imm=[TYPE[type]]
233
- while (nodes.length) imm.push(...instr(nodes.shift()))
234
- imm.push(OP.end)
235
- callstack.pop()
236
- }
237
-
238
- // (br $label result?)
239
- // (br_if $label cond result?)
240
- else if (opCode==0x0c||opCode==0x0d) {
241
- // br index indicates how many callstack items to pop
242
- imm = uleb(nodes[0]?.[0]==='$' ? callstack.length-callstack[nodes.shift()] : nodes.shift())
243
- argc = (opCode==0x0d ? 1 + (nodes.length > 1) : !!nodes.length)
244
- }
245
-
246
- // (br_table 1 2 3 4 0 selector result?)
247
- else if (opCode==0x0e) {
248
- imm = []
249
- while (!Array.isArray(nodes[0])) id=nodes.shift(), imm.push(...uleb(id[0][0]==='$'?callstack.length-callstack[id]:id))
250
- imm.unshift(...uleb(imm.length-1))
251
- argc = 1 + (nodes.length>1)
252
- }
253
-
254
- else if (opCode==null) err(`Unknown instruction \`${op}\``)
255
- }
256
-
257
- // consume arguments
258
- if (nodes.length < argc) err(`Stack arguments are not supported at \`${op}\``)
259
- while (argc--) args.push(...instr(nodes.shift()))
260
- if (nodes.length) err(`Too many arguments for \`${op}\`.`)
261
-
262
- return [...args, opCode, ...imm]
263
- }
264
-
265
- let code = body.flatMap(instr)
266
-
267
- // squash local types
268
- let locTypes = locals.reduce((a, type) => (type==a[a.length-1] ? a[a.length-2]++ : a.push(1,type), a), [])
269
-
270
- ctx.code.push([...uleb(code.length+2+locTypes.length), ...uleb(locTypes.length>>1), ...locTypes, ...code, OP.end])
271
- },
272
-
273
- // (memory min max shared)
274
- // (memory $name min max shared)
275
- // (memory (import "js" "mem") min max shared)
276
- memory([, ...parts], ctx) {
277
- if (parts[0][0]==='$') ctx.memory[parts.shift()] = ctx.memory.length
278
- if (parts[0][0] === 'import') {
279
- let [imp, ...limits] = parts
280
- // (import "js" "mem" (memory 1))
281
- return build.import([...imp, ['memory', ...limits]], ctx)
282
- }
283
-
284
- ctx.memory.push(range(parts))
285
- },
286
-
287
- // (global i32 (i32.const 42))
288
- // (global $id i32 (i32.const 42))
289
- // (global $id (mut i32) (i32.const 42))
290
- // FIXME (global $g1 (import "js" "g1") (mut i32)) ;; import from js
291
- global([, ...args], ctx) {
292
- let name = args[0][0]==='$' && args.shift()
293
- if (name) ctx.global[name] = ctx.global.length
294
-
295
- let [type, init] = args, mut = type[0] === 'mut'
296
-
297
- ctx.global.push([TYPE[mut ? type[1] : type], mut, ...iinit(init)])
298
- },
299
-
300
- // (table 1 2? funcref)
301
- // (table $name 1 2? funcref)
302
- table([, ...args], ctx) {
303
- let name = args[0][0]==='$' && args.shift()
304
- if (name) ctx.table[name] = ctx.table.length
305
-
306
- let lims = range(args)
307
- ctx.table.push([TYPE[args.pop()], ...lims])
308
- },
309
-
310
- // (elem (i32.const 0) $f1 $f2), (elem (global.get 0) $f1 $f2)
311
- elem([, offset, ...elems], ctx) {
312
- const tableIdx = 0 // FIXME: table index can be defined
313
- ctx.elem.push([tableIdx, ...iinit(offset, ctx), ...uleb(elems.length), ...elems.flatMap(el => uleb(el[0]==='$' ? ctx.func[el] : el))])
314
- },
315
-
316
- // (export "name" (kind $name|idx))
317
- export([, name, [kind, idx]], ctx) {
318
- if (idx[0]==='$') idx = ctx[kind][idx]
319
- ctx.export.push([...str(name), KIND[kind], ...uleb(idx)])
320
- },
321
-
322
- // (import "math" "add" (func $add (param i32 i32 externref) (result i32)))
323
- // (import "js" "mem" (memory 1))
324
- // (import "js" "mem" (memory $name 1))
325
- import([, mod, name, ref], ctx) {
326
- // FIXME: forward here from particular nodes instead: definition for import is same, we should DRY import code
327
- // build[ref[0]]([ref[0], ['import', mod, name], ...ref.slice(1)])
328
-
329
- let details, [kind, ...parts] = ref
330
- if (kind==='func') {
331
- // we track imported funcs in func section to share namespace, and skip them on final build
332
- if (parts[0]?.[0]==='$') ctx.func[parts.shift()] = ctx.func.length
333
- let [typeIdx] = build.type([, ['func', ...parts]], ctx)
334
- ctx.func.push(details = uleb(typeIdx))
335
- ctx.func.importc = (ctx.func.importc||0)+1
336
- }
337
- else if (kind==='memory') {
338
- if (parts[0][0]==='$') ctx.memory[parts.shift()] = ctx.memory.length
339
- details = range(parts)
340
- }
341
-
342
- ctx.import.push([...str(mod), ...str(name), KIND[kind], ...details])
343
- },
344
-
345
- // (data (i32.const 0) "\2a")
346
- data([, offset, init], ctx) {
347
- // FIXME: first is mem index
348
- ctx.data.push([0, ...iinit(offset,ctx), ...str(init)])
349
- },
350
-
351
- // (start $main)
352
- start([, name],ctx) {
353
- if (!ctx.start.length) ctx.start.push([name[0]==='$' ? ctx.func[name] : name])
354
- }
355
- }
356
-
357
- // (i32.const 0) - instantiation time initializer
358
- const iinit = ([op, literal], ctx) => op[0]==='f' ?
359
- [OP[op], ...(op=='f32'?f32:f64)(literal), OP.end] :
360
- [OP[op], ...leb(literal[0] === '$' ? ctx.global[literal] : literal), OP.end]
361
-
362
- // build string binary
363
- const str = str => {
364
- str = str[0]==='"' ? str.slice(1,-1) : str
365
- let res = [], i = 0, c, BSLASH=92
366
- // spec https://webassembly.github.io/spec/core/text/values.html#strings
367
- for (;i < str.length;) c=str.charCodeAt(i++), res.push(...uleb(c===BSLASH ? parseInt(str.slice(i,i+=2), 16) : c))
368
- res.unshift(...uleb(res.length))
369
- return res
370
- }
371
-
372
- // build range/limits sequence (non-consuming)
373
- const range = ([min, max, shared]) => isNaN(parseInt(max)) ? [0, ...uleb(min)] : [shared==='shared'?3:1, ...uleb(min), ...uleb(max)]
374
-
375
-
376
- // encoding ref: https://github.com/j-s-n/WebBS/blob/master/compiler/byteCode.js
377
- function leb (number, buffer) {
378
- if (!buffer) buffer = [], number = parseInt(number)
379
-
380
- let byte = number & 0b01111111;
381
- let signBit = byte & 0b01000000;
382
- number = number >> 7;
383
-
384
- if ((number === 0 && signBit === 0) || (number === -1 && signBit !== 0)) {
385
- buffer.push(byte);
386
- return buffer;
387
- } else {
388
- buffer.push(byte | 0b10000000);
389
- return leb(number, buffer);
390
- }
391
- }
392
-
393
- const uleb = (number, buffer) => {
394
- if (!buffer) buffer = [], number = parseInt(number)
395
-
396
- let byte = number & 0b01111111;
397
- number = number >>> 7;
398
-
399
- if (number === 0) {
400
- buffer.push(byte);
401
- return buffer;
402
- } else {
403
- buffer.push(byte | 0b10000000);
404
- return uleb(number, buffer);
405
- }
406
- }
407
-
408
- const byteView = new DataView(new BigInt64Array(1).buffer)
409
-
410
- const F32_SIGN = 0x80000000, F32_NAN = 0x7f800000
411
- function f32 (input, value, idx) {
412
- if (~(idx=input.indexOf('nan:'))) {
413
- value = parseInt(input.slice(idx+4))
414
- value |= F32_NAN
415
- if (input[0] === '-') value |= F32_SIGN
416
- byteView.setInt32(0, value)
417
- }
418
- else {
419
- value=input==='nan'||input==='+nan'?NaN:input==='-nan'?-NaN:input==='inf'||input==='+inf'?Infinity:input==='-inf'?-Infinity:parseFloat(input)
420
- byteView.setFloat32(0, value);
421
- }
422
-
423
- return [
424
- byteView.getUint8(3),
425
- byteView.getUint8(2),
426
- byteView.getUint8(1),
427
- byteView.getUint8(0)
428
- ];
429
- }
430
-
431
- const F64_SIGN = 0x8000000000000000n, F64_NAN = 0x7ff0000000000000n
432
- function f64 (input, value, idx) {
433
- if (~(idx=input.indexOf('nan:'))) {
434
- value = BigInt(input.slice(idx+4))
435
- value |= F64_NAN
436
- if (input[0] === '-') value |= F64_SIGN
437
- byteView.setBigInt64(0, value)
438
- }
439
- else {
440
- value=input==='nan'||input==='+nan'?NaN:input==='-nan'?-NaN:input==='inf'||input==='+inf'?Infinity:input==='-inf'?-Infinity:parseFloat(input)
441
- byteView.setFloat64(0, value);
442
- }
443
-
444
- return [
445
- byteView.getUint8(7),
446
- byteView.getUint8(6),
447
- byteView.getUint8(5),
448
- byteView.getUint8(4),
449
- byteView.getUint8(3),
450
- byteView.getUint8(2),
451
- byteView.getUint8(1),
452
- byteView.getUint8(0)
453
- ];
454
- }
455
-
456
- const err = text => { throw Error(text) }
package/src/parse.js DELETED
@@ -1,31 +0,0 @@
1
- const OPAREN=40, CPAREN=41, OBRACK=91, CBRACK=93, SPACE=32, DQUOTE=34, PERIOD=46,
2
- _0=48, _9=57, SEMIC=59, NEWLINE=32, PLUS=43, MINUS=45, COLON=58
3
-
4
- export default (str) => {
5
- let i = 0, level = [], buf=''
6
-
7
- const commit = () => buf && (
8
- level.push(~buf.indexOf('=') ? buf.split('=') : buf),
9
- buf = ''
10
- )
11
-
12
- const parseLevel = () => {
13
- for (let c, root; i < str.length; ) {
14
- c = str.charCodeAt(i)
15
- if (c === OPAREN) {
16
- if (str.charCodeAt(i+1) === SEMIC) i=str.indexOf(';)', i)+2 // (; ... ;)
17
- else i++, (root=level).push(level=[]), parseLevel(), level=root
18
- }
19
- else if (c === SEMIC) i=str.indexOf('\n', i)+1 // ; ...
20
- else if (c <= SPACE) commit(), i++
21
- else if (c === CPAREN) return commit(), i++
22
- else buf+=str[i++]
23
- }
24
-
25
- commit()
26
- }
27
-
28
- parseLevel()
29
-
30
- return level.length>1 ? level : level[0]
31
- }
package/src/watr.js DELETED
@@ -1,8 +0,0 @@
1
- import compile from './compile.js'
2
- import parse from './parse.js'
3
-
4
- export default src => (
5
- src = typeof src === 'string' ? parse(src) : src,
6
- compile(src)
7
- )
8
- export {compile, parse}