porffor 0.2.0-fbab1de → 0.2.0-fde989a

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.
@@ -170,25 +170,6 @@ export const BuiltinFuncs = function() {
170
170
  ]
171
171
  };
172
172
 
173
- // todo: return false for NaN
174
- this.Boolean = {
175
- params: [ valtypeBinary ],
176
- locals: [],
177
- returns: [ valtypeBinary ],
178
- returnType: 'boolean',
179
- wasm: [
180
- [ Opcodes.local_get, 0 ],
181
- ...(valtype === 'f64' ? [
182
- ...number(0),
183
- [ Opcodes.f64_ne ]
184
- ] : [
185
- ...Opcodes.eqz,
186
- [ Opcodes.i32_eqz ]
187
- ]),
188
- Opcodes.i32_from
189
- ]
190
- };
191
-
192
173
  // just return given (default 0) for (new) Object() as we somewhat supports object just not constructor
193
174
  this.Object = {
194
175
  params: [ valtypeBinary ],
@@ -699,6 +680,49 @@ export const BuiltinFuncs = function() {
699
680
  };
700
681
 
701
682
 
683
+ this.__Porffor_type = {
684
+ params: [ valtypeBinary, Valtype.i32 ],
685
+ typedParams: true,
686
+ locals: [ Valtype.i32, Valtype.i32 ],
687
+ returns: [ valtypeBinary ],
688
+ returnType: process.argv.includes('-bytestring') ? '_bytestring' : 'string',
689
+ wasm: (scope, { TYPE_NAMES, typeSwitch, makeString }) => {
690
+ const bc = {};
691
+ for (const x in TYPE_NAMES) {
692
+ bc[x] = makeString(scope, TYPE_NAMES[x], false, '#Porffor_type_result');
693
+ }
694
+
695
+ return typeSwitch(scope, [ [ Opcodes.local_get, 1 ] ], bc);
696
+ }
697
+ };
698
+
699
+ const localIsOneOf = (getter, arr, valtype = valtypeBinary) => {
700
+ const out = [];
701
+
702
+ for (let i = 0; i < arr.length; i++) {
703
+ out.push(...getter, ...number(arr[i], valtype), valtype === Valtype.f64 ? [ Opcodes.f64_eq ] : [ Opcodes.i32_eq ]);
704
+ if (i !== 0) out.push([ Opcodes.i32_or ]);
705
+ }
706
+
707
+ return out;
708
+ };
709
+
710
+ this.__Porffor_pointer = {
711
+ params: [ valtypeBinary, Valtype.i32 ],
712
+ typedParams: true,
713
+ locals: [ Valtype.i32, Valtype.i32 ],
714
+ returns: [ valtypeBinary ],
715
+ wasm: (scope, { TYPES }) => [
716
+ ...localIsOneOf([ [ Opcodes.local_get, 1 ] ], [ TYPES.string, TYPES._array, TYPES._bytestring ], Valtype.i32),
717
+ [ Opcodes.if, valtypeBinary ],
718
+ [ Opcodes.local_get, 0 ],
719
+ [ Opcodes.else ],
720
+ ...number(NaN),
721
+ [ Opcodes.end ]
722
+ ]
723
+ };
724
+
725
+
702
726
  this.__SIMD_i32x4_load = {
703
727
  params: [ Valtype.i32 ],
704
728
  locals: [],
@@ -160,7 +160,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
160
160
 
161
161
  case 'TaggedTemplateExpression': {
162
162
  const funcs = {
163
- asm: str => {
163
+ __Porffor_asm: str => {
164
164
  let out = [];
165
165
 
166
166
  for (const line of str.split('\n')) {
@@ -196,19 +196,19 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
196
196
  return out;
197
197
  },
198
198
 
199
- __internal_print_type: str => {
200
- const type = getType(scope, str) - TYPES.number;
199
+ __Porffor_bs: str => [
200
+ ...makeString(scope, str, undefined, undefined, true),
201
201
 
202
- return [
203
- ...number(type),
204
- [ Opcodes.call, importedFuncs.print ],
202
+ ...number(TYPES._bytestring, Valtype.i32),
203
+ setLastType(scope)
204
+ ],
205
+ __Porffor_s: str => [
206
+ ...makeString(scope, str, undefined, undefined, false),
205
207
 
206
- // newline
207
- ...number(10),
208
- [ Opcodes.call, importedFuncs.printChar ]
209
- ];
210
- }
211
- }
208
+ ...number(TYPES.string, Valtype.i32),
209
+ setLastType(scope)
210
+ ],
211
+ };
212
212
 
213
213
  const name = decl.tag.name;
214
214
  // hack for inline asm
@@ -274,25 +274,25 @@ const generateIdent = (scope, decl) => {
274
274
  const name = mapName(rawName);
275
275
  let local = scope.locals[rawName];
276
276
 
277
- if (builtinVars[name]) {
277
+ if (Object.hasOwn(builtinVars, name)) {
278
278
  if (builtinVars[name].floatOnly && valtype[0] === 'i') throw new Error(`Cannot use ${unhackName(name)} with integer valtype`);
279
279
  return builtinVars[name];
280
280
  }
281
281
 
282
- if (builtinFuncs[name] || internalConstrs[name]) {
282
+ if (Object.hasOwn(builtinFuncs, name) || Object.hasOwn(internalConstrs, name)) {
283
283
  // todo: return an actual something
284
284
  return number(1);
285
285
  }
286
286
 
287
- if (local === undefined) {
287
+ if (local?.idx === undefined) {
288
288
  // no local var with name
289
- if (importedFuncs.hasOwnProperty(name)) return number(importedFuncs[name]);
290
- if (funcIndex[name] !== undefined) return number(funcIndex[name]);
289
+ if (Object.hasOwn(importedFuncs, name)) return number(importedFuncs[name]);
290
+ if (Object.hasOwn(funcIndex, name)) return number(funcIndex[name]);
291
291
 
292
- if (globals[name] !== undefined) return [ [ Opcodes.global_get, globals[name].idx ] ];
292
+ if (Object.hasOwn(globals, name)) return [ [ Opcodes.global_get, globals[name].idx ] ];
293
293
  }
294
294
 
295
- if (local === undefined && rawName.startsWith('__')) {
295
+ if (local?.idx === undefined && rawName.startsWith('__')) {
296
296
  // return undefined if unknown key in already known var
297
297
  let parent = rawName.slice(2).split('_').slice(0, -1).join('_');
298
298
  if (parent.includes('_')) parent = '__' + parent;
@@ -301,7 +301,7 @@ const generateIdent = (scope, decl) => {
301
301
  if (!parentLookup[1]) return number(UNDEFINED);
302
302
  }
303
303
 
304
- if (local === undefined) return internalThrow(scope, 'ReferenceError', `${unhackName(name)} is not defined`, true);
304
+ if (local?.idx === undefined) return internalThrow(scope, 'ReferenceError', `${unhackName(name)} is not defined`, true);
305
305
 
306
306
  return [ [ Opcodes.local_get, local.idx ] ];
307
307
  };
@@ -925,7 +925,7 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
925
925
  [ Opcodes.i32_or ],
926
926
  [ Opcodes.if, Blocktype.void ],
927
927
  ...number(0, Valtype.i32),
928
- [ Opcodes.br, 1 ],
928
+ [ Opcodes.br, 2 ],
929
929
  [ Opcodes.end ],
930
930
 
931
931
  ...compareStrings(scope, [ [ Opcodes.local_get, tmpLeft ] ], [ [ Opcodes.local_get, tmpRight ] ]),
@@ -981,7 +981,7 @@ const asmFunc = (name, { wasm, params, locals: localTypes, globals: globalTypes
981
981
  localInd: allLocals.length,
982
982
  };
983
983
 
984
- wasm = wasm(scope, { TYPES, typeSwitch, makeArray });
984
+ wasm = wasm(scope, { TYPES, TYPE_NAMES, typeSwitch, makeArray, makeString });
985
985
  }
986
986
 
987
987
  let baseGlobalIdx, i = 0;
@@ -1286,8 +1286,8 @@ const getNodeType = (scope, node) => {
1286
1286
  const generateLiteral = (scope, decl, global, name) => {
1287
1287
  if (decl.value === null) return number(NULL);
1288
1288
 
1289
+ // hack: just return 1 for regex literals
1289
1290
  if (decl.regex) {
1290
- scope.regex[name] = decl.regex;
1291
1291
  return number(1);
1292
1292
  }
1293
1293
 
@@ -1932,6 +1932,8 @@ const generateVar = (scope, decl) => {
1932
1932
  for (const x of decl.declarations) {
1933
1933
  const name = mapName(x.id.name);
1934
1934
 
1935
+ if (!name) return todo('destructuring is not supported yet');
1936
+
1935
1937
  if (x.init && isFuncType(x.init.type)) {
1936
1938
  // hack for let a = function () { ... }
1937
1939
  x.init.id = { name };
@@ -2070,6 +2072,8 @@ const generateAssign = (scope, decl) => {
2070
2072
  ];
2071
2073
  }
2072
2074
 
2075
+ if (!name) return todo('destructuring is not supported yet');
2076
+
2073
2077
  const [ local, isGlobal ] = lookupName(scope, name);
2074
2078
 
2075
2079
  if (local === undefined) {
@@ -2383,7 +2387,13 @@ const generateForOf = (scope, decl) => {
2383
2387
  // setup local for left
2384
2388
  generate(scope, decl.left);
2385
2389
 
2386
- const leftName = decl.left.declarations[0].id.name;
2390
+ let leftName = decl.left.declarations?.[0]?.id?.name;
2391
+ if (!leftName && decl.left.name) {
2392
+ leftName = decl.left.name;
2393
+
2394
+ generateVar(scope, { kind: 'var', _bare: true, declarations: [ { id: { name: leftName } } ] })
2395
+ }
2396
+
2387
2397
  const [ local, isGlobal ] = lookupName(scope, leftName);
2388
2398
 
2389
2399
  depth.push('block');
@@ -2626,15 +2636,14 @@ const StoreOps = {
2626
2636
 
2627
2637
  let data = [];
2628
2638
 
2629
- const compileBytes = (val, itemType, signed = true) => {
2639
+ const compileBytes = (val, itemType) => {
2630
2640
  // todo: this is a mess and needs confirming / ????
2631
2641
  switch (itemType) {
2632
2642
  case 'i8': return [ val % 256 ];
2633
- case 'i16': return [ val % 256, Math.floor(val / 256) ];
2634
-
2635
- case 'i32':
2636
- case 'i64':
2637
- return enforceFourBytes(signedLEB128(val));
2643
+ case 'i16': return [ val % 256, (val / 256 | 0) % 256 ];
2644
+ case 'i16': return [ val % 256, (val / 256 | 0) % 256 ];
2645
+ case 'i32': return [...new Uint8Array(new Int32Array([ val ]).buffer)];
2646
+ // todo: i64
2638
2647
 
2639
2648
  case 'f64': return ieee754_binary64(val);
2640
2649
  }
@@ -2724,7 +2733,7 @@ const byteStringable = str => {
2724
2733
  return true;
2725
2734
  };
2726
2735
 
2727
- const makeString = (scope, str, global = false, name = '$undeclared') => {
2736
+ const makeString = (scope, str, global = false, name = '$undeclared', forceBytestring = undefined) => {
2728
2737
  const rawElements = new Array(str.length);
2729
2738
  let byteStringable = process.argv.includes('-bytestring');
2730
2739
  for (let i = 0; i < str.length; i++) {
@@ -2734,6 +2743,8 @@ const makeString = (scope, str, global = false, name = '$undeclared') => {
2734
2743
  if (byteStringable && c > 0xFF) byteStringable = false;
2735
2744
  }
2736
2745
 
2746
+ if (byteStringable && forceBytestring === false) byteStringable = false;
2747
+
2737
2748
  return makeArray(scope, {
2738
2749
  rawElements
2739
2750
  }, global, name, false, byteStringable ? 'i8' : 'i16')[0];
@@ -2859,7 +2870,7 @@ export const generateMember = (scope, decl, _global, _name) => {
2859
2870
  setLastType(scope)
2860
2871
  ],
2861
2872
 
2862
- default: [ [ Opcodes.unreachable ] ]
2873
+ default: internalThrow(scope, 'TypeError', 'Member expression is not supported for non-string non-array yet')
2863
2874
  });
2864
2875
  };
2865
2876
 
@@ -2981,6 +2992,16 @@ const generateCode = (scope, decl) => {
2981
2992
  };
2982
2993
 
2983
2994
  const internalConstrs = {
2995
+ Boolean: {
2996
+ generate: (scope, decl) => {
2997
+ if (decl.arguments.length === 0) return number(0);
2998
+
2999
+ // should generate/run all args
3000
+ return truthy(scope, generate(scope, decl.arguments[0]), getNodeType(scope, decl.arguments[0]), false, false);
3001
+ },
3002
+ type: TYPES.boolean
3003
+ },
3004
+
2984
3005
  Array: {
2985
3006
  generate: (scope, decl, global, name) => {
2986
3007
  // new Array(i0, i1, ...)
package/compiler/index.js CHANGED
@@ -68,11 +68,17 @@ export default (code, flags) => {
68
68
  console.log([...pages.keys()].map(x => `\x1B[36m - ${x}\x1B[0m`).join('\n') + '\n');
69
69
  }
70
70
 
71
- const out = { wasm: sections, funcs, globals, tags, exceptions, pages };
71
+ const out = { wasm: sections, funcs, globals, tags, exceptions, pages, data };
72
72
 
73
73
  const target = getArg('target') ?? getArg('t') ?? 'wasm';
74
74
  const outFile = getArg('o');
75
75
 
76
+ if (target === 'wasm' && outFile) {
77
+ writeFileSync(outFile, Buffer.from(sections));
78
+
79
+ if (process.version) process.exit();
80
+ }
81
+
76
82
  if (target === 'c') {
77
83
  const c = toc(out);
78
84
  out.c = c;
@@ -87,11 +93,16 @@ export default (code, flags) => {
87
93
  }
88
94
 
89
95
  if (target === 'native') {
90
- const compiler = getArg('compiler') ?? 'clang';
96
+ let compiler = getArg('compiler') ?? 'clang';
91
97
  const cO = getArg('cO') ?? 'Ofast';
92
98
 
99
+ if (compiler === 'zig') compiler = [ 'zig', 'cc' ];
100
+ else compiler = [ compiler ];
101
+
93
102
  const tmpfile = 'tmp.c';
94
- const args = [ compiler, tmpfile, '-o', outFile ?? (process.platform === 'win32' ? 'out.exe' : 'out'), '-' + cO, '-march=native' ];
103
+ // const args = [ compiler, tmpfile, '-o', outFile ?? (process.platform === 'win32' ? 'out.exe' : 'out'), '-' + cO, '-march=native', '-s', '-fno-unwind-tables', '-fno-asynchronous-unwind-tables', '-ffunction-sections', '-fdata-sections', '-Wl', '-fno-ident', '-fno-exceptions', '-ffast-math' ];
104
+ // const args = [ ...compiler, tmpfile, '-o', outFile ?? (process.platform === 'win32' ? 'out.exe' : 'out'), '-' + cO, '-march=native', '-s', '-ffast-math', '-fno-exceptions', '-target', 'x86_64-linux' ];
105
+ const args = [ ...compiler, tmpfile, '-o', outFile ?? (process.platform === 'win32' ? 'out.exe' : 'out'), '-' + cO, '-march=native', '-s', '-ffast-math', '-fno-exceptions' ];
95
106
 
96
107
  const c = toc(out);
97
108
  writeFileSync(tmpfile, c);
package/filesize.cmd ADDED
@@ -0,0 +1,2 @@
1
+ @echo off
2
+ echo %~z1
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.2.0-fbab1de",
4
+ "version": "0.2.0-fde989a",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "dependencies": {
package/porf ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ node runner/index.js "$@"
package/runner/index.js CHANGED
@@ -15,9 +15,22 @@ if (process.argv.includes('-compile-hints')) {
15
15
  // --experimental-wasm-return-call (on by default)
16
16
  }
17
17
 
18
- const file = process.argv.slice(2).find(x => x[0] !== '-');
18
+ let file = process.argv.slice(2).find(x => x[0] !== '-');
19
+ if (['run', 'wasm', 'native', 'c'].includes(file)) {
20
+ if (['wasm', 'native', 'c'].includes(file)) {
21
+ process.argv.push(`-target=${file}`);
22
+ }
23
+
24
+ file = process.argv.slice(process.argv.indexOf(file) + 1).find(x => x[0] !== '-');
25
+
26
+ const nonOptOutFile = process.argv.slice(process.argv.indexOf(file) + 1).find(x => x[0] !== '-');
27
+ if (nonOptOutFile) {
28
+ process.argv.push(`-o=${nonOptOutFile}`);
29
+ }
30
+ }
31
+
19
32
  if (!file) {
20
- if (process.argv.includes('-v')) {
33
+ if (process.argv.includes('-v') || process.argv.includes('--version')) {
21
34
  // just print version
22
35
  console.log((await import('./version.js')).default);
23
36
  process.exit(0);