porffor 0.14.0-7bef6473d → 0.14.0-86ac87fa4

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.
@@ -65,6 +65,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
65
65
  importFuncs = [...imports.values()];
66
66
 
67
67
  // fix call indexes for non-imports
68
+ // also fix call_indirect types
68
69
  const delta = importedFuncs.length - importFuncs.length;
69
70
  for (const f of funcs) {
70
71
  f.originalIndex = f.index;
@@ -74,6 +75,16 @@ export default (funcs, globals, tags, pages, data, flags) => {
74
75
  if ((inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) && inst[1] >= importedFuncs.length) {
75
76
  inst[1] -= delta;
76
77
  }
78
+
79
+ if (inst[0] === Opcodes.call_indirect) {
80
+ const params = [];
81
+ for (let i = 0; i < inst[1]; i++) {
82
+ params.push(valtypeBinary, Valtype.i32);
83
+ }
84
+
85
+ const returns = [ valtypeBinary, Valtype.i32 ];
86
+ inst[1] = getType(params, returns);
87
+ }
77
88
  }
78
89
  }
79
90
  }
@@ -101,7 +112,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
101
112
  encodeVector([ [
102
113
  0x00,
103
114
  Opcodes.i32_const, 0, Opcodes.end,
104
- encodeVector(funcs.map(x => x.index))
115
+ ...encodeVector(funcs.map(x => x.index))
105
116
  ] ])
106
117
  );
107
118
 
@@ -15,4 +15,4 @@ export const __Boolean_prototype_toString = (_this: boolean) => {
15
15
  export const __Boolean_prototype_valueOf = (_this: boolean) => {
16
16
  // 1. Return ? ThisBooleanValue(this value).
17
17
  return _this;
18
- };
18
+ };
@@ -0,0 +1,61 @@
1
+ export const __Porffor_symbol_descStore = (op: boolean, value: any): any => {
2
+ const ptr: bytestring = '';
3
+
4
+ if (op) { // write
5
+ const size: number = Porffor.wasm.i32.load(ptr, 0, 0);
6
+ Porffor.wasm.i32.store(ptr, size + 1, 0, 0)
7
+
8
+ // reuse set internals to store description
9
+ __Porffor_set_write(ptr, size, value);
10
+ return size;
11
+ } else { // read
12
+ return __Porffor_set_read(ptr, value);
13
+ }
14
+ };
15
+
16
+ export const Symbol = (description: any): Symbol => {
17
+ // 1-based so always truthy as numeric value
18
+ return __Porffor_symbol_descStore(true, description) + 1;
19
+ };
20
+
21
+ // todo: this should be a getter somehow not a method
22
+ export const __Symbol_prototype_description = (_this: Symbol) => {
23
+ const description: bytestring = __Porffor_symbol_descStore(false,
24
+ Porffor.wasm`local.get ${_this}` - 1);
25
+ return description;
26
+ };
27
+
28
+ export const __Symbol_prototype_toString = (_this: Symbol) => {
29
+ let out: bytestring = '';
30
+
31
+ // Symbol(
32
+ Porffor.wasm.i32.store8(out, 83, 0, 4);
33
+ Porffor.wasm.i32.store8(out, 121, 0, 5);
34
+ Porffor.wasm.i32.store8(out, 109, 0, 6);
35
+ Porffor.wasm.i32.store8(out, 98, 0, 7);
36
+ Porffor.wasm.i32.store8(out, 111, 0, 8);
37
+ Porffor.wasm.i32.store8(out, 108, 0, 9);
38
+ Porffor.wasm.i32.store8(out, 40, 0, 10);
39
+
40
+ const description: bytestring = __Porffor_symbol_descStore(false,
41
+ Porffor.wasm`local.get ${_this}` - 1);
42
+
43
+ const descLen: i32 = description.length;
44
+ let outPtr: i32 = Porffor.wasm`local.get ${out}` + 7;
45
+ let descPtr: i32 = Porffor.wasm`local.get ${description}`;
46
+ const descPtrEnd: i32 = descPtr + descLen;
47
+ while (descPtr < descPtrEnd) {
48
+ Porffor.wasm.i32.store8(outPtr++, Porffor.wasm.i32.load8_u(descPtr++, 0, 4), 0, 4);
49
+ }
50
+
51
+ // )
52
+ Porffor.wasm.i32.store8(Porffor.wasm`local.get ${out}` + descLen, 41, 0, 11);
53
+
54
+ out.length = 8 + descLen;
55
+
56
+ return out;
57
+ };
58
+
59
+ export const __Symbol_prototype_valueOf = (_this: Symbol) => {
60
+ return _this;
61
+ };
@@ -198,7 +198,8 @@ export const BuiltinFuncs = function() {
198
198
  returns: [ valtypeBinary ],
199
199
  wasm: [
200
200
  [ Opcodes.local_get, 0 ]
201
- ]
201
+ ],
202
+ constr: true
202
203
  };
203
204
 
204
205
  // just return given (default 0) for (new) Object() as we somewhat supports object just not constructor
@@ -210,7 +211,8 @@ export const BuiltinFuncs = function() {
210
211
  wasm: [
211
212
  // [ Opcodes.local_get, 0 ]
212
213
  ...number(1)
213
- ]
214
+ ],
215
+ constr: true
214
216
  };
215
217
 
216
218
 
@@ -58,10 +58,11 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
58
58
 
59
59
  case 'ArrowFunctionExpression':
60
60
  case 'FunctionDeclaration':
61
+ case 'FunctionExpression':
61
62
  const func = generateFunc(scope, decl);
62
63
 
63
64
  if (decl.type.endsWith('Expression')) {
64
- return number(func.index);
65
+ return number(func.index - importedFuncs.length);
65
66
  }
66
67
 
67
68
  return [];
@@ -139,6 +140,9 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
139
140
  case 'ArrayExpression':
140
141
  return generateArray(scope, decl, global, name);
141
142
 
143
+ case 'ObjectExpression':
144
+ return generateObject(scope, decl, global, name);
145
+
142
146
  case 'MemberExpression':
143
147
  return generateMember(scope, decl, global, name);
144
148
 
@@ -187,7 +191,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
187
191
  if (!Array.isArray(inst)) inst = [ inst ];
188
192
  const immediates = asm.slice(1).map(x => {
189
193
  const int = parseInt(x);
190
- if (Number.isNaN(int)) return scope.locals[x]?.idx;
194
+ if (Number.isNaN(int)) return scope.locals[x]?.idx ?? globals[x].idx;
191
195
  return int;
192
196
  });
193
197
 
@@ -313,10 +317,10 @@ const generateIdent = (scope, decl) => {
313
317
 
314
318
  if (local?.idx === undefined) {
315
319
  // no local var with name
316
- if (Object.hasOwn(importedFuncs, name)) return number(importedFuncs[name]);
317
- if (Object.hasOwn(funcIndex, name)) return number(funcIndex[name]);
318
-
319
320
  if (Object.hasOwn(globals, name)) return [ [ Opcodes.global_get, globals[name].idx ] ];
321
+
322
+ if (Object.hasOwn(importedFuncs, name)) return number(importedFuncs[name] - importedFuncs.length);
323
+ if (Object.hasOwn(funcIndex, name)) return number(funcIndex[name] - importedFuncs.length);
320
324
  }
321
325
 
322
326
  if (local?.idx === undefined && rawName.startsWith('__')) {
@@ -350,9 +354,7 @@ const generateReturn = (scope, decl) => {
350
354
 
351
355
  return [
352
356
  ...generate(scope, decl.argument),
353
- ...(scope.returnType != null ? [] : [
354
- ...getNodeType(scope, decl.argument)
355
- ]),
357
+ ...(scope.returnType != null ? [] : getNodeType(scope, decl.argument)),
356
358
  [ Opcodes.return ]
357
359
  ];
358
360
  };
@@ -1450,6 +1452,10 @@ const countLeftover = wasm => {
1450
1452
  } else count--;
1451
1453
  if (func) count += func.returns.length;
1452
1454
  }
1455
+ } else if (inst[0] === Opcodes.call_indirect) {
1456
+ count--; // funcidx
1457
+ count -= inst[1] * 2; // params * 2 (typed)
1458
+ count += 2; // fixed return (value, type)
1453
1459
  } else count--;
1454
1460
 
1455
1461
  // console.log(count, decompile([ inst ]).slice(0, -1));
@@ -1831,7 +1837,45 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1831
1837
  }
1832
1838
 
1833
1839
  if (idx === undefined) {
1834
- if (scope.locals[name] !== undefined || globals[name] !== undefined || builtinVars[name] !== undefined) return internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, true);
1840
+ if (scope.locals[name] !== undefined || globals[name] !== undefined || builtinVars[name] !== undefined) {
1841
+ const [ local, global ] = lookupName(scope, name);
1842
+ if (!Prefs.indirectCalls || local == null) return internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, true);
1843
+
1844
+ // todo: only works when:
1845
+ // 1. arg count matches arg count of function
1846
+ // 2. function uses typedParams and typedReturns
1847
+
1848
+ funcs.table = true;
1849
+
1850
+ let args = decl.arguments;
1851
+ let argWasm = [];
1852
+
1853
+ for (let i = 0; i < args.length; i++) {
1854
+ const arg = args[i];
1855
+ argWasm = argWasm.concat(generate(scope, arg));
1856
+
1857
+ if (valtypeBinary !== Valtype.i32 && (
1858
+ (builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32) ||
1859
+ (importedFuncs[name] && name.startsWith('profile'))
1860
+ )) {
1861
+ argWasm.push(Opcodes.i32_to);
1862
+ }
1863
+
1864
+ argWasm = argWasm.concat(getNodeType(scope, arg));
1865
+ }
1866
+
1867
+ return typeSwitch(scope, getNodeType(scope, decl.callee), {
1868
+ [TYPES.function]: [
1869
+ ...argWasm,
1870
+ [ global ? Opcodes.global_get : Opcodes.local_get, local.idx ],
1871
+ Opcodes.i32_to_u,
1872
+ [ Opcodes.call_indirect, args.length, 0 ],
1873
+ ...setLastType(scope)
1874
+ ],
1875
+ default: internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, true)
1876
+ });
1877
+ }
1878
+
1835
1879
  return internalThrow(scope, 'ReferenceError', `${unhackName(name)} is not defined`, true);
1836
1880
  }
1837
1881
 
@@ -1860,11 +1904,16 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1860
1904
  const arg = args[i];
1861
1905
  out = out.concat(generate(scope, arg));
1862
1906
 
1863
- if (builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32 && valtypeBinary !== Valtype.i32) {
1864
- out.push(Opcodes.i32_to);
1907
+ if (i >= paramCount) {
1908
+ // over param count of func, drop arg
1909
+ out.push([ Opcodes.drop ]);
1910
+ continue;
1865
1911
  }
1866
1912
 
1867
- if (importedFuncs[name] && name.startsWith('profile')) {
1913
+ if (valtypeBinary !== Valtype.i32 && (
1914
+ (builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32) ||
1915
+ (importedFuncs[name] && name.startsWith('profile'))
1916
+ )) {
1868
1917
  out.push(Opcodes.i32_to);
1869
1918
  }
1870
1919
 
@@ -1909,6 +1958,11 @@ const generateNew = (scope, decl, _global, _name) => {
1909
1958
  }, _global, _name);
1910
1959
  }
1911
1960
 
1961
+ if (
1962
+ (builtinFuncs[name] && !builtinFuncs[name].constr) ||
1963
+ (internalConstrs[name] && builtinFuncs[name].notConstr)
1964
+ ) return internalThrow(scope, 'TypeError', `${name} is not a constructor`);
1965
+
1912
1966
  if (!builtinFuncs[name]) return todo(scope, `new statement is not supported yet`); // return todo(scope, `new statement is not supported yet (new ${unhackName(name)})`);
1913
1967
 
1914
1968
  return generateCall(scope, decl, _global, _name);
@@ -2174,6 +2228,22 @@ const generateVar = (scope, decl) => {
2174
2228
  }
2175
2229
 
2176
2230
  if (x.init) {
2231
+ // if (isFuncType(x.init.type)) {
2232
+ // // let a = function () { ... }
2233
+ // x.init.id = { name };
2234
+
2235
+ // const func = generateFunc(scope, x.init);
2236
+
2237
+ // out.push(
2238
+ // ...number(func.index - importedFuncs.length),
2239
+ // [ global ? Opcodes.global_set : Opcodes.local_set, idx ],
2240
+
2241
+ // ...setType(scope, name, TYPES.function)
2242
+ // );
2243
+
2244
+ // continue;
2245
+ // }
2246
+
2177
2247
  const generated = generate(scope, x.init, global, name);
2178
2248
  if (scope.arrays?.get(name) != null) {
2179
2249
  // hack to set local as pointer before
@@ -2185,6 +2255,7 @@ const generateVar = (scope, decl) => {
2185
2255
  out = out.concat(generated);
2186
2256
  out.push([ global ? Opcodes.global_set : Opcodes.local_set, idx ]);
2187
2257
  }
2258
+
2188
2259
  out.push(...setType(scope, name, getNodeType(scope, x.init)));
2189
2260
  }
2190
2261
 
@@ -2198,6 +2269,7 @@ const generateVar = (scope, decl) => {
2198
2269
  // todo: optimize this func for valueUnused
2199
2270
  const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2200
2271
  const { type, name } = decl.left;
2272
+ const [ local, isGlobal ] = lookupName(scope, name);
2201
2273
 
2202
2274
  if (type === 'ObjectPattern') {
2203
2275
  // hack: ignore object parts of `var a = {} = 2`
@@ -2207,8 +2279,18 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2207
2279
  if (isFuncType(decl.right.type)) {
2208
2280
  // hack for a = function () { ... }
2209
2281
  decl.right.id = { name };
2210
- generateFunc(scope, decl.right);
2211
- return [];
2282
+
2283
+ const func = generateFunc(scope, decl.right);
2284
+
2285
+ return [
2286
+ ...number(func.index - importedFuncs.length),
2287
+ ...(local != null ? [
2288
+ [ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ],
2289
+ [ isGlobal ? Opcodes.global_get : Opcodes.local_get, local.idx ],
2290
+
2291
+ ...setType(scope, name, TYPES.function)
2292
+ ] : [])
2293
+ ];
2212
2294
  }
2213
2295
 
2214
2296
  const op = decl.operator.slice(0, -1) || '=';
@@ -2307,8 +2389,6 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
2307
2389
 
2308
2390
  if (!name) return todo(scope, 'destructuring is not supported yet', true);
2309
2391
 
2310
- const [ local, isGlobal ] = lookupName(scope, name);
2311
-
2312
2392
  if (local === undefined) {
2313
2393
  // todo: this should be a sloppy mode only thing
2314
2394
 
@@ -2457,6 +2537,7 @@ const generateUnary = (scope, decl) => {
2457
2537
  [TYPES.string]: makeString(scope, 'string', false, '#typeof_result'),
2458
2538
  [TYPES.undefined]: makeString(scope, 'undefined', false, '#typeof_result'),
2459
2539
  [TYPES.function]: makeString(scope, 'function', false, '#typeof_result'),
2540
+ [TYPES.symbol]: makeString(scope, 'symbol', false, '#typeof_result'),
2460
2541
 
2461
2542
  [TYPES.bytestring]: makeString(scope, 'string', false, '#typeof_result'),
2462
2543
 
@@ -3147,7 +3228,18 @@ const generateArray = (scope, decl, global = false, name = '$undeclared', initEm
3147
3228
  return makeArray(scope, decl, global, name, initEmpty, valtype)[0];
3148
3229
  };
3149
3230
 
3150
- export const generateMember = (scope, decl, _global, _name) => {
3231
+ const generateObject = (scope, decl, global = false, name = '$undeclared') => {
3232
+ if (decl.properties.length > 0) return todo(scope, 'objects are not supported yet', true);
3233
+
3234
+ return [
3235
+ ...number(1),
3236
+
3237
+ ...number(TYPES.object, Valtype.i32),
3238
+ ...setLastType(scope)
3239
+ ];
3240
+ };
3241
+
3242
+ const generateMember = (scope, decl, _global, _name) => {
3151
3243
  const name = decl.object.name;
3152
3244
  const pointer = scope.arrays?.get(name);
3153
3245
 
@@ -3368,7 +3460,7 @@ const generateFunc = (scope, decl) => {
3368
3460
 
3369
3461
  if (typedInput && decl.returnType) {
3370
3462
  const { type } = extractTypeAnnotation(decl.returnType);
3371
- if (type != null) {
3463
+ if (type != null && !Prefs.indirectCalls) {
3372
3464
  innerScope.returnType = type;
3373
3465
  innerScope.returns = [ valtypeBinary ];
3374
3466
  }
@@ -3586,8 +3678,10 @@ const internalConstrs = {
3586
3678
  }),
3587
3679
 
3588
3680
  // print space
3589
- ...number(32),
3590
- [ Opcodes.call, importedFuncs.printChar ]
3681
+ ...(i !== decl.arguments.length - 1 ? [
3682
+ ...number(32),
3683
+ [ Opcodes.call, importedFuncs.printChar ]
3684
+ ] : [])
3591
3685
  );
3592
3686
  }
3593
3687
 
@@ -3597,6 +3691,8 @@ const internalConstrs = {
3597
3691
  [ Opcodes.call, importedFuncs.printChar ]
3598
3692
  );
3599
3693
 
3694
+ out.push(...number(UNDEFINED));
3695
+
3600
3696
  return out;
3601
3697
  },
3602
3698
  type: TYPES.undefined,
@@ -119,7 +119,7 @@ export const highlightAsm = asm => asm
119
119
  .replace(/(local|global|memory)\.[^\s]*/g, _ => `\x1B[31m${_}\x1B[0m`)
120
120
  .replace(/(i(8|16|32|64)x[0-9]+|v128)(\.[^\s]*)?/g, _ => `\x1B[34m${_}\x1B[0m`)
121
121
  .replace(/(i32|i64|f32|f64|drop)(\.[^\s]*)?/g, _ => `\x1B[36m${_}\x1B[0m`)
122
- .replace(/(return_call|call|br_if|br|return|rethrow|throw)/g, _ => `\x1B[35m${_}\x1B[0m`)
122
+ .replace(/(return_call|call_indirect|call|br_if|br|return|rethrow|throw)/g, _ => `\x1B[35m${_}\x1B[0m`)
123
123
  .replace(/(block|loop|if|end|else|try|catch_all|catch|delegate)/g, _ => `\x1B[95m${_}\x1B[0m`)
124
124
  .replace(/unreachable/g, _ => `\x1B[91m${_}\x1B[0m`)
125
125
  .replace(/ \-?[0-9\.]+/g, _ => ` \x1B[33m${_.slice(1)}\x1B[0m`)
@@ -1622,4 +1622,49 @@ export const BuiltinFuncs = function() {
1622
1622
  locals: [],
1623
1623
  localNames: ["_this","_this#type"],
1624
1624
  };
1625
+ this.__Porffor_symbol_descStore = {
1626
+ wasm: (scope, {allocPage,builtin,}) => [...number(allocPage(scope, 'bytestring: __Porffor_symbol_descStore/ptr', 'i8') * pageSize, 124),[33,4],[32,0],[252,3],[4,64],[32,4],[252,2],[40,0,0],[183],[33,5],[32,4],[252,2],[32,5],[68,0,0,0,0,0,0,240,63],[160],[252,2],[54,0,0],[32,4],[65,18],[32,5],[65,0],[32,2],[32,3],[16, builtin('__Porffor_set_write')],[26],[32,5],[65,0],[15],[5],[32,4],[65,18],[32,2],[32,3],[16, builtin('__Porffor_set_read')],[34,6],[15],[11],[68,0,0,0,0,0,0,0,0],[65,3],[15]],
1627
+ params: [124,127,124,127],
1628
+ typedParams: true,
1629
+ returns: [124,127],
1630
+ typedReturns: true,
1631
+ locals: [124,124,127],
1632
+ localNames: ["op","op#type","value","value#type","ptr","size","#last_type"],
1633
+ };
1634
+ this.Symbol = {
1635
+ wasm: (scope, {builtin,}) => [[68,0,0,0,0,0,0,240,63],[65,1],[32,0],[32,1],[16, builtin('__Porffor_symbol_descStore')],[33,2],[68,0,0,0,0,0,0,240,63],[160],[15]],
1636
+ params: [124,127],
1637
+ typedParams: true,
1638
+ returns: [124],
1639
+ returnType: 6,
1640
+ locals: [127],
1641
+ localNames: ["description","description#type","#last_type"],
1642
+ };
1643
+ this.__Symbol_prototype_description = {
1644
+ wasm: (scope, {builtin,}) => [[68,0,0,0,0,0,0,0,0],[65,1],[32,0],[68,0,0,0,0,0,0,240,63],[161],[65,0],[16, builtin('__Porffor_symbol_descStore')],[33,3],[34,2],[65,18],[15]],
1645
+ params: [124,127],
1646
+ typedParams: true,
1647
+ returns: [124,127],
1648
+ typedReturns: true,
1649
+ locals: [124,127],
1650
+ localNames: ["_this","_this#type","description","#last_type"],
1651
+ };
1652
+ this.__Symbol_prototype_toString = {
1653
+ wasm: (scope, {allocPage,builtin,}) => [...number(allocPage(scope, 'bytestring: __Symbol_prototype_toString/out', 'i8') * pageSize, 124),[34,2],[252,2],[65,211,0],[58,0,4],[32,2],[252,2],[65,249,0],[58,0,5],[32,2],[252,2],[65,237,0],[58,0,6],[32,2],[252,2],[65,226,0],[58,0,7],[32,2],[252,2],[65,239,0],[58,0,8],[32,2],[252,2],[65,236,0],[58,0,9],[32,2],[252,2],[65,40],[58,0,10],[68,0,0,0,0,0,0,0,0],[65,1],[32,0],[68,0,0,0,0,0,0,240,63],[161],[65,0],[16, builtin('__Porffor_symbol_descStore')],[33,4],[34,3],[252,3],[40,1,0],[184],[33,5],[32,2],[68,0,0,0,0,0,0,28,64],[160],[33,6],[32,3],[34,7],[32,5],[160],[33,8],[3,64],[32,7],[32,8],[99],[4,64],[32,6],[32,6],[68,0,0,0,0,0,0,240,63],[160],[33,6],[252,2],[32,7],[32,7],[68,0,0,0,0,0,0,240,63],[160],[33,7],[252,2],[45,0,4],[58,0,4],[12,1],[11],[11],[32,2],[32,5],[160],[252,2],[65,41],[58,0,11],[32,2],[252,3],[68,0,0,0,0,0,0,32,64],[32,5],[160],[34,9],[252,3],[54,1,0],[32,2],[65,18],[15]],
1654
+ params: [124,127],
1655
+ typedParams: true,
1656
+ returns: [124,127],
1657
+ typedReturns: true,
1658
+ locals: [124,124,127,124,124,124,124,124],
1659
+ localNames: ["_this","_this#type","out","description","#last_type","descLen","outPtr","descPtr","descPtrEnd","__length_setter_tmp"],
1660
+ };
1661
+ this.__Symbol_prototype_valueOf = {
1662
+ wasm: (scope, {}) => [[32,0],[65,6],[15]],
1663
+ params: [124,127],
1664
+ typedParams: true,
1665
+ returns: [124,127],
1666
+ typedReturns: true,
1667
+ locals: [],
1668
+ localNames: ["_this","_this#type"],
1669
+ };
1625
1670
  };
package/compiler/index.js CHANGED
@@ -12,14 +12,7 @@ globalThis.decompile = decompile;
12
12
  const logFuncs = (funcs, globals, exceptions) => {
13
13
  console.log('\n' + underline(bold('funcs')));
14
14
 
15
- const startIndex = funcs.sort((a, b) => a.index - b.index)[0].index;
16
15
  for (const f of funcs) {
17
- console.log(`${underline(f.name)} (${f.index - startIndex})`);
18
-
19
- console.log(`params: ${f.params.map((_, i) => Object.keys(f.locals)[Object.values(f.locals).indexOf(Object.values(f.locals).find(x => x.idx === i))]).join(', ')}`);
20
- console.log(`returns: ${f.returns.length > 0 ? true : false}`);
21
- console.log(`locals: ${Object.keys(f.locals).sort((a, b) => f.locals[a].idx - f.locals[b].idx).map(x => `${x} (${f.locals[x].idx})`).join(', ')}`);
22
- console.log();
23
16
  console.log(decompile(f.wasm, f.name, f.index, f.locals, f.params, f.returns, funcs, globals, exceptions));
24
17
  }
25
18
 
@@ -44,12 +37,14 @@ export default (code, flags) => {
44
37
  opt(funcs, globals, pages, tags, exceptions);
45
38
  if (Prefs.profileCompiler) console.log(`3. optimized in ${(performance.now() - t2).toFixed(2)}ms`);
46
39
 
47
- if (Prefs.optFuncs) logFuncs(funcs, globals, exceptions);
40
+ // if (Prefs.optFuncs) logFuncs(funcs, globals, exceptions);
48
41
 
49
42
  const t3 = performance.now();
50
43
  const wasm = assemble(funcs, globals, tags, pages, data, flags);
51
44
  if (Prefs.profileCompiler) console.log(`4. assembled in ${(performance.now() - t3).toFixed(2)}ms`);
52
45
 
46
+ if (Prefs.optFuncs) logFuncs(funcs, globals, exceptions);
47
+
53
48
  if (Prefs.allocLog) {
54
49
  const wasmPages = Math.ceil((pages.size * pageSize) / 65536);
55
50
  const bytes = wasmPages * 65536;
@@ -18,7 +18,7 @@ const compile = async (file, [ _funcs, _globals ]) => {
18
18
  first = source.slice(0, source.indexOf('\n'));
19
19
  }
20
20
 
21
- let args = ['--bytestring', '--todo-time=compile', '--no-aot-pointer-opt', '--no-treeshake-wasm-imports', '--no-rm-unused-types', '--scoped-page-names', '--funsafe-no-unlikely-proto-checks', '--parse-types', '--opt-types'];
21
+ let args = ['--bytestring', '--todo-time=compile', '--no-aot-pointer-opt', '--no-indirect-calls', '--no-treeshake-wasm-imports', '--no-rm-unused-types', '--scoped-page-names', '--funsafe-no-unlikely-proto-checks', '--parse-types', '--opt-types'];
22
22
  if (first.startsWith('// @porf')) {
23
23
  args = args.concat(first.slice('// @porf '.length).split(' '));
24
24
  }
package/compiler/prefs.js CHANGED
@@ -1,4 +1,4 @@
1
- const onByDefault = [ 'bytestring', 'aotPointerOpt', 'treeshakeWasmImports', 'alwaysMemory' ];
1
+ const onByDefault = [ 'bytestring', 'aotPointerOpt', 'treeshakeWasmImports', 'alwaysMemory', 'indirectCalls' ];
2
2
 
3
3
  let cache = {};
4
4
  const obj = new Proxy({}, {
@@ -6,7 +6,7 @@ const obj = new Proxy({}, {
6
6
  // intentionally misses with undefined values cached
7
7
  if (cache[p]) return cache[p];
8
8
 
9
- return cache[p] = (() => {
9
+ const ret = (() => {
10
10
  // fooBar -> foo-bar
11
11
  const name = p[0] === '_' ? p : p.replace(/[A-Z]/g, c => `-${c.toLowerCase()}`);
12
12
  const prefix = name.length === 1 ? '-' : '--';
@@ -19,6 +19,10 @@ const obj = new Proxy({}, {
19
19
  if (onByDefault.includes(p)) return true;
20
20
  return undefined;
21
21
  })();
22
+
23
+ // do not cache in web demo as args are changed live
24
+ if (!globalThis.document) cache[p] = ret;
25
+ return ret;
22
26
  }
23
27
  });
24
28
 
package/compiler/wrap.js CHANGED
@@ -1,22 +1,27 @@
1
+ import { encodeVector, encodeLocal } from './encoding.js';
2
+ import { importedFuncs } from './builtins.js';
1
3
  import compile from './index.js';
2
4
  import decompile from './decompile.js';
3
- import { encodeVector, encodeLocal } from './encoding.js';
4
5
  import { TYPES } from './types.js';
5
6
  import { log } from './log.js';
6
7
  import Prefs from './prefs.js';
7
8
 
8
9
  const bold = x => `\u001b[1m${x}\u001b[0m`;
9
10
 
10
- const porfToJSValue = (memory, funcs, value, type) => {
11
+ const porfToJSValue = ({ memory, funcs, pages }, value, type) => {
11
12
  switch (type) {
12
13
  case TYPES.boolean: return Boolean(value);
13
14
  case TYPES.undefined: return undefined;
14
15
  case TYPES.object: return value === 0 ? null : {};
15
16
 
16
17
  case TYPES.function: {
17
- // wasm func index, including all imports
18
- const func = funcs.find(x => (x.originalIndex ?? x.index) === value);
19
- // if (!func) return value;
18
+ let func;
19
+ if (value < 0) {
20
+ func = importedFuncs[value + importedFuncs.length];
21
+ } else {
22
+ func = funcs.find(x => ((x.originalIndex ?? x.index) - importedFuncs.length) === value);
23
+ }
24
+
20
25
  if (!func) return function () {};
21
26
 
22
27
  // make fake empty func for repl/etc
@@ -61,12 +66,24 @@ const porfToJSValue = (memory, funcs, value, type) => {
61
66
  // console.log(' memory:', Array.from(new Uint8Array(memory.buffer, offset, 9)).map(x => x.toString(16).padStart(2, '0')).join(' '));
62
67
  // console.log(' read:', { value: v, type: t }, '\n');
63
68
 
64
- out.add(porfToJSValue(memory, funcs, v, t));
69
+ out.add(porfToJSValue({ memory, funcs, pages }, v, t));
65
70
  }
66
71
 
67
72
  return out;
68
73
  }
69
74
 
75
+ case TYPES.symbol: {
76
+ const descStore = pages.get('bytestring: __Porffor_symbol_descStore/ptr').ind * pageSize;
77
+ const offset = descStore + 4 + ((value - 1) * 9);
78
+
79
+ const v = (new Float64Array(memory.buffer.slice(offset, offset + 8), 0, 1))[0];
80
+ const t = (new Uint8Array(memory.buffer, offset + 8, 1))[0];
81
+
82
+ const desc = porfToJSValue({ memory, funcs, pages }, v, t);
83
+
84
+ return Symbol(desc);
85
+ }
86
+
70
87
  default: return value;
71
88
  }
72
89
  };
@@ -213,10 +230,11 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
213
230
  exports[func.name] = function() {
214
231
  try {
215
232
  const ret = exp.apply(this, arguments);
216
-
217
233
  if (ret == null) return undefined;
218
234
 
219
- return porfToJSValue(memory, funcs, ret[0], ret[1])
235
+ if (Prefs.rawValue) return { value: ret[0], type: ret[1] };
236
+
237
+ return porfToJSValue({ memory, funcs, pages }, ret[0], ret[1]);
220
238
  } catch (e) {
221
239
  if (e.is && e.is(exceptTag)) {
222
240
  const exceptId = e.getArg(exceptTag, 0);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "porffor",
3
3
  "description": "a basic experimental wip aot optimizing js -> wasm engine/compiler/runtime in js",
4
- "version": "0.14.0-7bef6473d",
4
+ "version": "0.14.0-86ac87fa4",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "scripts": {