porffor 0.0.0-ee33579 → 0.0.0-f74a73a

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.
package/README.md CHANGED
@@ -83,6 +83,7 @@ these include some early (stage 1/0) and/or dead (last commit years ago) proposa
83
83
  - truthy/falsy (eg `!'' == true`)
84
84
  - string comparison (eg `'a' == 'a'`, `'a' != 'b'`)
85
85
  - nullish coalescing operator (`??`)
86
+ - `for...of` (arrays and strings)
86
87
 
87
88
  ### built-ins
88
89
 
@@ -114,7 +115,6 @@ no particular order and no guarentees, just what could happen soon™
114
115
  - more of `Array` prototype
115
116
  - arrays/strings inside arrays
116
117
  - destructuring
117
- - for .. of
118
118
  - strings
119
119
  - member setting
120
120
  - objects
package/compiler/2c.js CHANGED
@@ -34,18 +34,24 @@ const todo = msg => {
34
34
  throw new TodoError(`todo: ${msg}`);
35
35
  };
36
36
 
37
+ const removeBrackets = str => str.startsWith('(') && str.endsWith(')') ? str.slice(1, -1) : str;
38
+
37
39
  export default ({ funcs, globals, tags, exceptions, pages }) => {
38
- const invOperatorOpcode = inv(operatorOpcode[valtype]);
40
+ const invOperatorOpcode = Object.values(operatorOpcode).reduce((acc, x) => {
41
+ for (const k in x) {
42
+ acc[x[k]] = k;
43
+ }
44
+ return acc;
45
+ }, {});
39
46
  const invGlobals = inv(globals, x => x.idx);
40
47
 
41
- const includes = new Map();
48
+ const includes = new Map(), unixIncludes = new Map(), winIncludes = new Map();
42
49
  let out = '';
43
50
 
44
51
  for (const x in globals) {
45
52
  const g = globals[x];
46
53
 
47
- out += `${CValtype[g.type]} ${x}`;
48
- if (x.init) out += ` ${x.init}`;
54
+ out += `${CValtype[g.type]} ${x} = ${g.init ?? 0}`;
49
55
  out += ';\n';
50
56
  }
51
57
 
@@ -56,7 +62,43 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
56
62
 
57
63
  if (out) out += '\n';
58
64
 
65
+ let depth = 1;
66
+ const line = (str, semi = true) => out += `${' '.repeat(depth * 2)}${str}${semi ? ';' : ''}\n`;
67
+ const lines = lines => {
68
+ for (const x of lines) {
69
+ out += `${' '.repeat(depth * 2)}${x}\n`;
70
+ }
71
+ };
72
+
73
+ const platformSpecific = (win, unix, add = true) => {
74
+ let tmp = '';
75
+
76
+ if (win) {
77
+ if (add) out += '#ifdef _WIN32\n';
78
+ else tmp += '#ifdef _WIN32\n';
79
+
80
+ if (add) lines(win.split('\n'));
81
+ else tmp += win + (win.endsWith('\n') ? '' : '\n');
82
+ }
83
+
84
+ if (unix) {
85
+ if (add) out += (win ? '#else' : '#ifndef _WIN32') + '\n';
86
+ else tmp += (win ? '#else' : '#ifndef _WIN32') + '\n';
87
+
88
+ if (add) lines(unix.split('\n'));
89
+ else tmp += unix + (unix.endsWith('\n') ? '' : '\n');
90
+ }
91
+
92
+ if (win || unix)
93
+ if (add) out += '#endif\n';
94
+ else tmp += '#endif\n';
95
+
96
+ return tmp;
97
+ };
98
+
59
99
  for (const f of funcs) {
100
+ depth = 1;
101
+
60
102
  const invLocals = inv(f.locals, x => x.idx);
61
103
  if (f.returns.length > 1) todo('funcs returning >1 value unsupported');
62
104
 
@@ -64,16 +106,13 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
64
106
 
65
107
  const returns = f.returns.length === 1;
66
108
 
67
- const shouldInline = ['f64_%'].includes(f.name);
109
+ const shouldInline = f.internal;
68
110
  out += `${f.name === 'main' ? 'int' : CValtype[f.returns[0]]} ${shouldInline ? 'inline ' : ''}${sanitize(f.name)}(${f.params.map((x, i) => `${CValtype[x]} ${invLocals[i]}`).join(', ')}) {\n`;
69
111
 
70
- let depth = 1;
71
- const line = (str, semi = true) => out += `${' '.repeat(depth * 2)}${str}${semi ? ';' : ''}\n`;
72
-
73
112
  const localKeys = Object.keys(f.locals).sort((a, b) => f.locals[a].idx - f.locals[b].idx).slice(f.params.length).sort((a, b) => f.locals[a].idx - f.locals[b].idx);
74
113
  for (const x of localKeys) {
75
114
  const l = f.locals[x];
76
- line(`${CValtype[l.type]} ${x}`);
115
+ line(`${CValtype[l.type]} ${x} = 0`);
77
116
  }
78
117
 
79
118
  if (localKeys.length !== 0) out += '\n';
@@ -94,7 +133,8 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
94
133
  if (['==', '!=', '>', '>=', '<', '<='].includes(op)) lastCond = true;
95
134
  else lastCond = false;
96
135
 
97
- vals.push(`${a} ${op} ${b}`);
136
+ // vals.push(`${a} ${op} ${b}`);
137
+ vals.push(`(${removeBrackets(a)} ${op} ${b})`);
98
138
  continue;
99
139
  }
100
140
 
@@ -118,6 +158,7 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
118
158
 
119
159
  switch (i[0]) {
120
160
  case Opcodes.i32_const:
161
+ case Opcodes.i64_const:
121
162
  vals.push(read_signedLEB128(i.slice(1)).toString());
122
163
  break;
123
164
 
@@ -130,24 +171,42 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
130
171
  break;
131
172
 
132
173
  case Opcodes.local_set:
133
- line(`${invLocals[i[1]]} = ${vals.pop()}`);
174
+ line(`${invLocals[i[1]]} = ${removeBrackets(vals.pop())}`);
134
175
  break;
135
176
 
136
177
  case Opcodes.local_tee:
137
- vals.push(`${invLocals[i[1]]} = ${vals.pop()}`);
178
+ line(`${invLocals[i[1]]} = ${removeBrackets(vals.pop())}`);
179
+ vals.push(`${invLocals[i[1]]}`);
180
+ // vals.push(`${invLocals[i[1]]} = ${vals.pop()}`);
181
+ break;
182
+
183
+ case Opcodes.global_get:
184
+ vals.push(`${invGlobals[i[1]]}`);
185
+ break;
186
+
187
+ case Opcodes.global_set:
188
+ line(`${invGlobals[i[1]]} = ${removeBrackets(vals.pop())}`);
138
189
  break;
139
190
 
140
191
  case Opcodes.f64_trunc:
141
192
  // vals.push(`trunc(${vals.pop()})`);
142
- vals.push(`(int)(${vals.pop()})`); // this is ~10x faster with clang. what the fuck.
193
+ vals.push(`(int)(${removeBrackets(vals.pop())})`); // this is ~10x faster with clang??
194
+ break;
195
+
196
+ case Opcodes.f64_convert_i32_u:
197
+ case Opcodes.f64_convert_i32_s:
198
+ case Opcodes.f64_convert_i64_u:
199
+ case Opcodes.f64_convert_i64_s:
200
+ // int to double
201
+ vals.push(`(double)${vals.pop()}`);
143
202
  break;
144
203
 
145
204
  case Opcodes.return:
146
- line(`return${returns ? ` ${vals.pop()}` : ''}`);
205
+ line(`return${returns ? ` ${removeBrackets(vals.pop())}` : ''}`);
147
206
  break;
148
207
 
149
208
  case Opcodes.if:
150
- let cond = vals.pop();
209
+ let cond = removeBrackets(vals.pop());
151
210
  if (!lastCond) {
152
211
  if (cond.startsWith('(long)')) cond = `${cond.slice(6)} == 1e+0`;
153
212
  else cond += ' == 1';
@@ -212,12 +271,44 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
212
271
  line(`printf("%f\\n", ${vals.pop()})`);
213
272
  includes.set('stdio.h', true);
214
273
  break;
274
+
275
+ case 'time':
276
+ line(`double _time_out`);
277
+ /* platformSpecific(
278
+ `FILETIME _time_filetime;
279
+ GetSystemTimeAsFileTime(&_time_filetime);
280
+
281
+ ULARGE_INTEGER _time_ularge;
282
+ _time_ularge.LowPart = _time_filetime.dwLowDateTime;
283
+ _time_ularge.HighPart = _time_filetime.dwHighDateTime;
284
+ _time_out = (_time_ularge.QuadPart - 116444736000000000i64) / 10000.;`,
285
+ `struct timespec _time;
286
+ clock_gettime(CLOCK_MONOTONIC, &_time);
287
+ _time_out = _time.tv_nsec / 1000000.;`); */
288
+ platformSpecific(
289
+ `LARGE_INTEGER _time_freq, _time_t;
290
+ QueryPerformanceFrequency(&_time_freq);
291
+ QueryPerformanceCounter(&_time_t);
292
+ _time_out = ((double)_time_t.QuadPart / _time_freq.QuadPart) * 1000.;`,
293
+ `struct timespec _time;
294
+ clock_gettime(CLOCK_MONOTONIC, &_time);
295
+ _time_out = _time.tv_nsec / 1000000.;`);
296
+ vals.push(`_time_out`);
297
+
298
+ unixIncludes.set('time.h', true);
299
+ winIncludes.set('windows.h', true);
300
+ break;
301
+
302
+ default:
303
+ log('2c', `unimplemented import: ${importFunc.name}`);
304
+ break;
215
305
  }
306
+
216
307
  break;
217
308
  }
218
309
 
219
310
  let args = [];
220
- for (let j = 0; j < func.params.length; j++) args.unshift(vals.pop());
311
+ for (let j = 0; j < func.params.length; j++) args.unshift(removeBrackets(vals.pop()));
221
312
 
222
313
  if (func.returns.length === 1) vals.push(`${sanitize(func.name)}(${args.join(', ')})`)
223
314
  else line(`${sanitize(func.name)}(${args.join(', ')})`);
@@ -249,7 +340,11 @@ export default ({ funcs, globals, tags, exceptions, pages }) => {
249
340
  out += '}\n\n';
250
341
  }
251
342
 
252
- out = [...includes.keys()].map(x => `#include <${x}>`).join('\n') + '\n\n' + out;
343
+ depth = 0;
344
+
345
+ const makeIncludes = includes => [...includes.keys()].map(x => `#include <${x}>\n`).join('');
346
+
347
+ out = platformSpecific(makeIncludes(winIncludes), makeIncludes(unixIncludes), false) + '\n' + makeIncludes(includes) + '\n' + out;
253
348
 
254
349
  return out;
255
350
  };
@@ -109,8 +109,8 @@ const generate = (scope, decl, global = false, name = undefined) => {
109
109
  case 'WhileStatement':
110
110
  return generateWhile(scope, decl);
111
111
 
112
- /* case 'ForOfStatement':
113
- return generateForOf(scope, decl); */
112
+ case 'ForOfStatement':
113
+ return generateForOf(scope, decl);
114
114
 
115
115
  case 'BreakStatement':
116
116
  return generateBreak(scope, decl);
@@ -732,17 +732,11 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
732
732
  ];
733
733
  };
734
734
 
735
- let binaryExpDepth = 0;
736
735
  const generateBinaryExp = (scope, decl, _global, _name) => {
737
- binaryExpDepth++;
738
-
739
- const out = [
740
- ...performOp(scope, decl.operator, generate(scope, decl.left), generate(scope, decl.right), getNodeType(scope, decl.left), getNodeType(scope, decl.right), _global, _name)
741
- ];
736
+ const out = performOp(scope, decl.operator, generate(scope, decl.left), generate(scope, decl.right), getNodeType(scope, decl.left), getNodeType(scope, decl.right), _global, _name);
742
737
 
743
738
  if (valtype !== 'i32' && ['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(decl.operator)) out.push(Opcodes.i32_from_u);
744
739
 
745
- binaryExpDepth--;
746
740
  return out;
747
741
  };
748
742
 
@@ -1567,7 +1561,7 @@ const generateUpdate = (scope, decl) => {
1567
1561
  };
1568
1562
 
1569
1563
  const generateIf = (scope, decl) => {
1570
- const out = truthy(scope, generate(scope, decl.test), decl.test);
1564
+ const out = truthy(scope, generate(scope, decl.test), getNodeType(scope, decl.test));
1571
1565
 
1572
1566
  out.push(Opcodes.i32_to, [ Opcodes.if, Blocktype.void ]);
1573
1567
  depth.push('if');
@@ -1660,18 +1654,106 @@ const generateWhile = (scope, decl) => {
1660
1654
  const generateForOf = (scope, decl) => {
1661
1655
  const out = [];
1662
1656
 
1657
+ const rightType = getNodeType(scope, decl.right);
1658
+ const valtypeSize = rightType === TYPES._array ? ValtypeSize[valtype] : ValtypeSize.i16; // presume array (:()
1659
+
1660
+ // todo: for of inside for of might fuck up?
1661
+ const pointer = localTmp(scope, 'forof_base_pointer', Valtype.i32);
1662
+ const length = localTmp(scope, 'forof_length', Valtype.i32);
1663
+ const counter = localTmp(scope, 'forof_counter', Valtype.i32);
1664
+
1665
+ out.push(
1666
+ // set pointer as right
1667
+ ...generate(scope, decl.right),
1668
+ Opcodes.i32_to_u,
1669
+ [ Opcodes.local_set, pointer ],
1670
+
1671
+ // get length
1672
+ [ Opcodes.local_get, pointer ],
1673
+ [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
1674
+ [ Opcodes.local_set, length ]
1675
+ );
1676
+
1663
1677
  out.push([ Opcodes.loop, Blocktype.void ]);
1664
- depth.push('while');
1678
+ depth.push('forof');
1665
1679
 
1666
- out.push(...generate(scope, decl.test));
1667
- out.push(Opcodes.i32_to, [ Opcodes.if, Blocktype.void ]);
1668
- depth.push('if');
1680
+ // setup local for left
1681
+ generate(scope, decl.left);
1669
1682
 
1670
- out.push(...generate(scope, decl.body));
1683
+ const leftName = decl.left.declarations[0].id.name;
1671
1684
 
1672
- out.push([ Opcodes.br, 1 ]);
1673
- out.push([ Opcodes.end ], [ Opcodes.end ]);
1674
- depth.pop(); depth.pop();
1685
+ // set type for local
1686
+ typeStates[leftName] = rightType === TYPES._array ? TYPES.number : TYPES.string;
1687
+
1688
+ const [ local, isGlobal ] = lookupName(scope, leftName);
1689
+
1690
+ if (rightType === TYPES._array) { // array
1691
+ out.push(
1692
+ [ Opcodes.local_get, pointer ],
1693
+ [ Opcodes.load, Math.log2(valtypeSize) - 1, ...unsignedLEB128(ValtypeSize.i32) ]
1694
+ );
1695
+ } else { // string
1696
+ const [ newOut, newPointer ] = makeArray(scope, {
1697
+ rawElements: new Array(1)
1698
+ }, isGlobal, leftName, true, 'i16');
1699
+
1700
+ out.push(
1701
+ // setup new/out array
1702
+ ...newOut,
1703
+ [ Opcodes.drop ],
1704
+
1705
+ ...number(0, Valtype.i32), // base 0 for store after
1706
+
1707
+ // load current string ind {arg}
1708
+ [ Opcodes.local_get, pointer ],
1709
+ [ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(ValtypeSize.i32) ],
1710
+
1711
+ // store to new string ind 0
1712
+ [ Opcodes.i32_store16, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
1713
+
1714
+ // return new string (page)
1715
+ ...number(newPointer)
1716
+ );
1717
+ }
1718
+
1719
+ // set left value
1720
+ out.push([ isGlobal ? Opcodes.global_set : Opcodes.local_set, local.idx ]);
1721
+
1722
+ out.push(
1723
+ [ Opcodes.block, Blocktype.void ],
1724
+ [ Opcodes.block, Blocktype.void ]
1725
+ );
1726
+ depth.push('block');
1727
+ depth.push('block');
1728
+
1729
+ out.push(
1730
+ ...generate(scope, decl.body),
1731
+ [ Opcodes.end ]
1732
+ );
1733
+ depth.pop();
1734
+
1735
+ out.push(
1736
+ // increment iter pointer by valtype size
1737
+ [ Opcodes.local_get, pointer ],
1738
+ ...number(valtypeSize, Valtype.i32),
1739
+ [ Opcodes.i32_add ],
1740
+ [ Opcodes.local_set, pointer ],
1741
+
1742
+ // increment counter by 1
1743
+ [ Opcodes.local_get, counter ],
1744
+ ...number(1, Valtype.i32),
1745
+ [ Opcodes.i32_add ],
1746
+ [ Opcodes.local_tee, counter ],
1747
+
1748
+ // loop if counter != length
1749
+ [ Opcodes.local_get, length ],
1750
+ [ Opcodes.i32_ne ],
1751
+ [ Opcodes.br_if, 1 ],
1752
+
1753
+ [ Opcodes.end ], [ Opcodes.end ]
1754
+ );
1755
+ depth.pop();
1756
+ depth.pop();
1675
1757
 
1676
1758
  return out;
1677
1759
  };
package/compiler/index.js CHANGED
@@ -100,10 +100,10 @@ export default (code, flags) => {
100
100
 
101
101
  if (target === 'native') {
102
102
  const compiler = getArg('compiler') ?? 'clang';
103
- const cO = getArg('cO') ?? 'O3';
103
+ const cO = getArg('cO') ?? 'Ofast';
104
104
 
105
105
  const tmpfile = 'tmp.c';
106
- const args = [ compiler, tmpfile, '-o', outFile ?? (process.platform === 'win32' ? 'out.exe' : 'out'), '-' + cO ];
106
+ const args = [ compiler, tmpfile, '-o', outFile ?? (process.platform === 'win32' ? 'out.exe' : 'out'), '-' + cO, '-march=native' ];
107
107
 
108
108
  const c = toc(out);
109
109
  writeFileSync(tmpfile, c);
package/compiler/parse.js CHANGED
@@ -1,5 +1,5 @@
1
- import { parse } from 'acorn';
2
- // const { parse } = (await import(globalThis.document ? 'https://esm.sh/acorn' : 'acorn'));
1
+ // import { parse } from 'acorn';
2
+ const { parse } = (await import(globalThis.document ? 'https://esm.sh/acorn' : 'acorn'));
3
3
 
4
4
  export default (input, flags) => {
5
5
  return parse(input, {
package/out.exe ADDED
Binary file
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.0.0-ee33579",
4
+ "version": "0.0.0-f74a73a",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "dependencies": {
package/r.js CHANGED
@@ -1 +1 @@
1
- /a(b)/.test('hi');
1
+ print(performance.now());
package/rhemyn/compile.js CHANGED
@@ -21,7 +21,7 @@ const generate = (node, negated = false, get = true, func = 'test') => {
21
21
  out = [
22
22
  // set length local
23
23
  [ Opcodes.local_get, BasePointer ],
24
- [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(0) ],
24
+ [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
25
25
  [ Opcodes.local_set, Length ],
26
26
 
27
27
  // set iter pointer local as base + sizeof i32 initially
package/runner/index.js CHANGED
@@ -49,5 +49,5 @@ try {
49
49
  if (cache) process.stdout.write(cache);
50
50
  } catch (e) {
51
51
  if (cache) process.stdout.write(cache);
52
- console.error(`${e.constructor.name}: ${e.message}`);
52
+ console.error(process.argv.includes('-i') ? e : `${e.constructor.name}: ${e.message}`);
53
53
  }
package/tmp.c CHANGED
@@ -1,37 +1,58 @@
1
+ #ifdef _WIN32
2
+ #include <windows.h>
3
+ #else
4
+ #include <time.h>
5
+ #endif
6
+
1
7
  #include <stdio.h>
2
8
 
3
- double inline f64_f(double x, double y) {
4
- return x - (int)(x / y) * y;
9
+ double aux(double n, double acc1, double acc2) {
10
+ if (n == 0e+0) {
11
+ return acc1;
12
+ }
13
+ if (n == 1e+0) {
14
+ return acc2;
15
+ }
16
+ return aux(n - 1e+0, acc2, acc1 + acc2);
5
17
  }
6
18
 
7
- double isPrime(double number) {
8
- double i;
19
+ double fib(double n) {
20
+ return aux(n, 0e+0, 1e+0);
21
+ }
9
22
 
10
- if (number < 2e+0) {
11
- return 0e+0;
12
- }
13
- i = 2e+0;
14
- while (i < number) {
15
- if (f64_f(number, i) == 0e+0) {
16
- return 0e+0;
17
- }
23
+ double test(double n, double count) {
24
+ double res = 0;
25
+ double i = 0;
26
+
27
+ i = 0e+0;
28
+ while (i < count) {
29
+ res = fib(n);
18
30
  i = i + 1e+0;
19
31
  }
20
- return 1e+0;
32
+ return res;
33
+ }
34
+
35
+ double inline __performance_now() {
36
+ double _time_out;
37
+ #ifdef _WIN32
38
+ LARGE_INTEGER _time_freq, _time_t;
39
+ QueryPerformanceFrequency(&_time_freq);
40
+ QueryPerformanceCounter(&_time_t);
41
+ _time_out = ((double)_time_t.QuadPart / _time_freq.QuadPart) * 1000.;
42
+ #else
43
+ struct timespec _time;
44
+ clock_gettime(CLOCK_MONOTONIC, &_time);
45
+ _time_out = _time.tv_nsec / 1000000.;
46
+ #endif
47
+ return _time_out;
21
48
  }
22
49
 
23
50
  int main() {
24
- double sum;
25
- double counter;
26
-
27
- sum = 0e+0;
28
- counter = 0e+0;
29
- while (counter <= 1e+5) {
30
- if (isPrime(counter) == 1e+0) {
31
- sum = sum + counter;
32
- }
33
- counter = counter + 1e+0;
34
- }
35
- printf("%f\n", sum);
51
+ double t = 0;
52
+
53
+ t = __performance_now();
54
+ // Sleep(1000);
55
+ printf("%f\n", test(4.6e+1, 1e+7));
56
+ printf("%f\n", (__performance_now() - t));
36
57
  }
37
58