porffor 0.0.0-05f898f

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.
@@ -0,0 +1,321 @@
1
+ const State = {
2
+ none: 0,
3
+ insideSet: 1
4
+ };
5
+
6
+ const Quantifiers = {
7
+ '*': [ 0 ], // 0 -
8
+ '+': [ 1 ], // 1 -
9
+ '?': [ 0, 1 ], // 0 - 1
10
+ };
11
+ const QuantifierKeys = Object.keys(Quantifiers);
12
+
13
+ const getArg = (name, def) => {
14
+ const arg = (typeof process !== 'undefined' ? process.argv : Deno.args).find(x => x.startsWith(`-${name}=`));
15
+ if (arg) return arg.split('=')[0];
16
+
17
+ return def;
18
+ };
19
+
20
+ // full is spec-compliant but slower. not needed most of the time. (evil)
21
+ const DotChars = () => ({
22
+ full: [ '\n', '\r', '\u2028', '\u2029' ],
23
+ simple: [ '\n', '\r' ],
24
+ fast: [ '\n' ]
25
+ })[getArg('regex-dot', 'fast')];
26
+
27
+ const WordChars = () => ({
28
+ full: [ [ 'a', 'z' ], [ 'A', 'Z' ], [ '0', '9' ], '_' ],
29
+ fast: [ [ '_', 'z' ], [ 'A', 'Z' ], [ '0', '9' ] ] // skip individual _ with _-z BUT it also matches '`'
30
+ })[getArg('regex-word', 'full')];
31
+
32
+ const WhitespaceChars = () => ({
33
+ full: [ ' ', '\t', '\n', '\r', '\u2028', '\u2029' ],
34
+ simple: [ ' ', '\t', '\n', '\r' ]
35
+ })[getArg('regex-ws', 'simple')];
36
+
37
+ const _Metachars = () => ({
38
+ unescaped: {
39
+ '.': [ DotChars(), true ], // dot
40
+ },
41
+ escaped: {
42
+ d: [ [ [ '0', '9' ] ], false ], // digit
43
+ D: [ [ [ '0', '9' ] ], true ], // not digit
44
+ w: [ WordChars(), false ], // word
45
+ W: [ WordChars(), true ], // not word
46
+ s: [ WhitespaceChars(), false ], // whitespace
47
+ S: [ WhitespaceChars(), true ], // not whitespace
48
+ }
49
+ });
50
+
51
+ const EscapeSequences = {
52
+ f: '\f',
53
+ n: '\n',
54
+ r: '\r',
55
+ t: '\t',
56
+ v: '\v',
57
+ '0': '\0'
58
+ };
59
+
60
+ const HexDigit = /[0-9a-fA-F]/;
61
+
62
+ export default str => {
63
+ const Metachars = _Metachars();
64
+
65
+ const out = {
66
+ type: 'Expression',
67
+ body: []
68
+ };
69
+ let node = out, parents = [];
70
+
71
+ let state = State.none, setIndex = 0, escape = false;
72
+ for (let i = 0; i < str.length; i++) {
73
+ const c = str[i];
74
+
75
+ const charNode = char => ({
76
+ type: 'Character',
77
+ char
78
+ });
79
+
80
+ const rangeNode = (from, to) => ({
81
+ type: 'Range',
82
+ from,
83
+ to
84
+ });
85
+
86
+ const addChar = (char = c) => {
87
+ node.body.push(charNode(char));
88
+ };
89
+
90
+ const addSet = (matches, negated = false) => {
91
+ let body = matches.map(x => x[1] ? rangeNode(x[0], x[1]) : charNode(x));
92
+ if (state === State.insideSet) {
93
+ // if negated, mark each node as negated for merge
94
+ if (negated) body = body.map(x => {
95
+ x.negated = true;
96
+ return x;
97
+ });
98
+
99
+ // already in set, merge bodies
100
+ node.body.push(...body);
101
+ return;
102
+ }
103
+
104
+ node.body.push({
105
+ type: 'Set',
106
+ body,
107
+ negated
108
+ });
109
+ };
110
+
111
+ const addMetachar = meta => {
112
+ const [ matches, negated = false ] = meta;
113
+ return addSet(matches, negated);
114
+ };
115
+
116
+ // get next char and consume it
117
+ const seek = (allowEscaped = true) => {
118
+ const cNext = str[++i];
119
+
120
+ if (cNext === '\\') return !allowEscaped ? undefined : [ str[++i], true ];
121
+ return !allowEscaped ? cNext : [ cNext, false ];
122
+ };
123
+
124
+ // get next char without consuming
125
+ const peek = (allowEscaped = true, offset = 0) => {
126
+ const cNext = str[i + 1 + offset];
127
+
128
+ if (cNext === '\\') return !allowEscaped ? undefined : [ str[i + 2 + offset], true ];
129
+ return !allowEscaped ? cNext : [ cNext, false ];
130
+ };
131
+
132
+ if (escape) {
133
+ escape = false;
134
+ if (EscapeSequences[c]) {
135
+ addChar(EscapeSequences[c]);
136
+ continue;
137
+ }
138
+
139
+ if (Metachars.escaped[c]) {
140
+ addMetachar(Metachars.escaped[c]);
141
+ continue;
142
+ }
143
+
144
+ if (c === 'c') {
145
+ // \c (not [A-Za-z] ...) = literal \c... (WHY)
146
+ const next = peek(false);
147
+ if (next == null || /[^a-zA-Z]/.test(next)) {
148
+ addChar('\\');
149
+ addChar('c');
150
+ continue;
151
+ }
152
+
153
+ // \c[A-Za-z]
154
+ const code = seek(false).charCodeAt(0);
155
+ addChar(String.fromCharCode(code % 32));
156
+ continue;
157
+ }
158
+
159
+ if (c === 'x') {
160
+ // \x = x
161
+ // \xH = xH
162
+ // \x[0-9a-zA-Z][0-9a-zA-Z] = \xAB
163
+ const next1 = peek(false);
164
+ const next2 = peek(false, 1);
165
+
166
+ // missing a char or invalid hex digit
167
+ if (next1 == null || next2 == null || !HexDigit.test(next1) || !HexDigit.test(next2)) {
168
+ addChar('x');
169
+ continue;
170
+ }
171
+
172
+ const code = parseInt(seek(false) + seek(false), 16);
173
+ addChar(String.fromCodePoint(code));
174
+ continue;
175
+ }
176
+
177
+ if (c === 'u') {
178
+ // '\u' = u
179
+ // '\uHHH' = uHHH
180
+ // '\uABCD' = \uABCD
181
+ const next1 = peek(false);
182
+ const next2 = peek(false, 1);
183
+ const next3 = peek(false, 2);
184
+ const next4 = peek(false, 3);
185
+
186
+ // missing a char or invalid hex digit
187
+ if (next1 == null || next2 == null || next3 == null || next4 == null || !HexDigit.test(next1) || !HexDigit.test(next2) || !HexDigit.test(next3) || !HexDigit.test(next4)) {
188
+ addChar('u');
189
+ continue;
190
+ }
191
+
192
+ const code = parseInt(seek(false) + seek(false) + seek(false) + seek(false), 16);
193
+ addChar(String.fromCodePoint(code));
194
+ continue;
195
+ }
196
+
197
+ addChar();
198
+ continue;
199
+ }
200
+
201
+ if (c === '\\') {
202
+ escape = true;
203
+ continue;
204
+ }
205
+
206
+ switch (state) {
207
+ case State.none:
208
+ if (c === '[') {
209
+ parents.push(node);
210
+ node = {
211
+ type: 'Set',
212
+ body: [],
213
+ negated: false
214
+ };
215
+
216
+ parents.at(-1).body.push(node);
217
+
218
+ state = State.insideSet;
219
+ setIndex = 0;
220
+ continue;
221
+ }
222
+
223
+ if (c === '(') {
224
+ parents.push(node);
225
+ node = {
226
+ type: 'Group',
227
+ body: []
228
+ };
229
+
230
+ parents.at(-1).body.push(node);
231
+ continue;
232
+ }
233
+
234
+ if (c === ')') {
235
+ if (node.type !== 'Group') throw new SyntaxError('Unmatched closing parenthesis');
236
+
237
+ node = parents.pop();
238
+ continue;
239
+ }
240
+
241
+ if (QuantifierKeys.includes(c)) {
242
+ node.body.at(-1).quantifier = Quantifiers[c];
243
+
244
+ // lazy modifier
245
+ if (peek(false) === '?') node.body.at(-1).lazy = true;
246
+
247
+ continue;
248
+ }
249
+
250
+ if (Metachars.unescaped[c]) {
251
+ addMetachar(Metachars.unescaped[c]);
252
+ continue;
253
+ }
254
+
255
+ addChar();
256
+ break;
257
+
258
+ case State.insideSet:
259
+ setIndex++;
260
+ if (setIndex === 1) {
261
+ // first char in set
262
+ if (c === '^') {
263
+ node.negated = true;
264
+ continue;
265
+ }
266
+ }
267
+
268
+ if (c === ']') {
269
+ state = State.none;
270
+ node = parents.pop();
271
+
272
+ continue;
273
+ }
274
+
275
+ // range
276
+ if (c === '-') {
277
+ // start of set (or not char), just literal -
278
+ if (node.body.at(-1)?.char == null) {
279
+ addChar(); // add -
280
+ continue;
281
+ }
282
+
283
+ const from = node.body.pop().char;
284
+ const [ to, escaped ] = seek();
285
+
286
+ // end of set, just literal -
287
+ if (to == null || (!escaped && to === ']')) {
288
+ addChar(from); // add from char back
289
+ i--; // rollback seek
290
+
291
+ addChar(); // add -
292
+ continue;
293
+ }
294
+
295
+ // next char was escaped and a metachar, just literal -
296
+ if (escaped && Metachars.escaped[to] != null) {
297
+ i -= 2; // rollback seek
298
+
299
+ addChar(); // add -
300
+ continue;
301
+ }
302
+
303
+ if (to < from) throw new SyntaxError('Range out of order');
304
+
305
+ node.body.push(rangeNode(from, to));
306
+ continue;
307
+ }
308
+
309
+ addChar();
310
+ break;
311
+ }
312
+ }
313
+
314
+ // still in a group by the end
315
+ if (node.type !== 'Expression') throw new SyntaxError('Unmatched opening parenthesis');
316
+
317
+ // still in a set by the end
318
+ if (state === State.insideSet) throw new SyntaxError('Unmatched opening square bracket');
319
+
320
+ return out;
321
+ };
@@ -0,0 +1,59 @@
1
+ import util from 'node:util';
2
+
3
+ import parse from '../parse.js';
4
+
5
+ const tests = {
6
+ 'a': {},
7
+ 'a(b)': {},
8
+ 'a(b(c))': {},
9
+ 'ab': {},
10
+ '[ab]': {},
11
+ '[a-z]': {},
12
+ 'a*': {},
13
+ 'a+': {},
14
+ 'a?': {},
15
+ 'a(b)+': {},
16
+ '[^a]': {},
17
+ '[a^]': {},
18
+ '[^ab]': {},
19
+ '.': {},
20
+
21
+ // not range
22
+ '[-]': {},
23
+ '[0-]': {},
24
+ '[-0]': {},
25
+ '[\\s-\\S]': {},
26
+ '[\\s-.]': {},
27
+
28
+ '[\\S]': {},
29
+
30
+ '\\c': {},
31
+ '\\c0': {},
32
+ '\\cJ': {},
33
+
34
+ '\\x': {},
35
+ '\\x0': {},
36
+ '\\x0g': {},
37
+ '\\x0a': {},
38
+
39
+ '\\u': {},
40
+ '\\u0': {},
41
+ '\\u000': {},
42
+ '\\u000g': {},
43
+ '\\u000a': {},
44
+
45
+ /*
46
+ // email regexes
47
+ '^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$': {},
48
+
49
+ // input type=email from HTML spec
50
+ // https://html.spec.whatwg.org/multipage/input.html#email-state-(type=email)
51
+ // simpler form
52
+ '^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$': {},
53
+ // full/complex form
54
+ '^[a-zA-Z0-9.!#$%&\'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$': {}*/
55
+ };
56
+
57
+ for (const str in tests) {
58
+ console.log(str, util.inspect(parse(str), false, null, true));
59
+ }
@@ -0,0 +1,35 @@
1
+ import { execSync } from 'node:child_process';
2
+ import { pathToFileURL } from 'node:url';
3
+ import fs from 'node:fs';
4
+
5
+ const [ commitsAgo, file ] = process.argv.slice(2);
6
+ const source = fs.readFileSync(file, 'utf8');
7
+
8
+ const compileNow = (await import('../compiler/index.js')).default;
9
+ const wasmNow = compileNow(source).byteLength;
10
+
11
+ execSync(`git checkout HEAD~${commitsAgo}`);
12
+
13
+ let failed = false;
14
+
15
+ fs.writeFileSync('tmp.js', source);
16
+ try {
17
+ execSync(`node runner/index.js tmp.js`);
18
+ } catch {
19
+ failed = true;
20
+ } finally {
21
+ fs.rmSync('tmp.js');
22
+ execSync(`git checkout main`);
23
+ }
24
+
25
+ console.log();
26
+
27
+ if (failed) {
28
+ console.log(`!! failed to compile then`);
29
+ process.exit();
30
+ }
31
+
32
+ const wasmThen = Buffer.byteLength(fs.readFileSync('out.wasm'));
33
+
34
+ console.log(`now: ${wasmNow} bytes`);
35
+ console.log(`${commitsAgo} commit${commitsAgo > 1 ? 's' : ''} ago: ${wasmThen} bytes`);
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+
3
+ import compile from '../compiler/wrap.js';
4
+ import fs from 'node:fs';
5
+
6
+ if (process.argv.includes('-compile-hints')) {
7
+ const v8 = await import('node:v8');
8
+ v8.setFlagsFromString(`--experimental-wasm-compilation-hints`);
9
+
10
+ // see also these flags:
11
+ // --experimental-wasm-branch-hinting
12
+ // --experimental-wasm-extended-const
13
+ // --experimental-wasm-inlining (?)
14
+ // --experimental-wasm-js-inlining (?)
15
+ // --experimental-wasm-return-call (on by default)
16
+ }
17
+
18
+ const file = process.argv.slice(2).find(x => x[0] !== '-');
19
+ if (!file) {
20
+ if (process.argv.includes('-v')) {
21
+ // just print version
22
+ console.log((await import('./version.js')).default);
23
+ process.exit(0);
24
+ }
25
+
26
+ // run repl if no file given
27
+ await import('./repl.js');
28
+
29
+ // do nothing for the rest of this file
30
+ await new Promise(() => {});
31
+ }
32
+
33
+ const source = fs.readFileSync(file, 'utf8');
34
+
35
+ let cache = '';
36
+ const print = str => {
37
+ cache += str;
38
+
39
+ if (str === '\n') {
40
+ process.stdout.write(cache);
41
+ cache = '';
42
+ } else print('\n');
43
+ };
44
+
45
+ try {
46
+ const { exports } = await compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {}, print);
47
+
48
+ exports.main();
49
+ if (cache) process.stdout.write(cache);
50
+ } catch (e) {
51
+ if (cache) process.stdout.write(cache);
52
+ console.error(`${e.constructor.name}: ${e.message}`);
53
+ }
package/runner/info.js ADDED
@@ -0,0 +1,54 @@
1
+ import compile from '../compiler/wrap.js';
2
+ import fs from 'node:fs';
3
+
4
+ /* if (globalThis.process) {
5
+ const v8 = await import('node:v8');
6
+ v8.setFlagsFromString('--experimental-wasm-gc');
7
+ } */
8
+
9
+ const raw = process.argv.includes('-raw');
10
+
11
+ const file = process.argv.slice(2).find(x => x[0] !== '-');
12
+ if (!file) {
13
+ // run repl if no file given
14
+ await import('./repl.js');
15
+
16
+ // do nothing for the rest of this file
17
+ await new Promise(() => {});
18
+ }
19
+
20
+ const source = fs.readFileSync(file, 'utf8');
21
+
22
+ const underline = x => `\u001b[4m\u001b[1m${x}\u001b[0m`;
23
+ const bold = x => `\u001b[1m${x}\u001b[0m`;
24
+
25
+ if (!raw) console.log(`\n${underline('source')}\n` + source);
26
+ if (!raw) console.log(`\n\n${underline('processing')}`);
27
+
28
+ let cache = '';
29
+ const print = str => {
30
+ cache += str;
31
+
32
+ if (str === '\n') {
33
+ process.stdout.write(cache);
34
+ cache = '';
35
+ }
36
+ };
37
+
38
+ const t0 = performance.now();
39
+ const { wasm, exports } = await compile(source, raw ? [ 'module' ] : [ 'module', 'info' ], {}, print);
40
+
41
+ if (!raw && typeof Deno === 'undefined') fs.writeFileSync('out.wasm', Buffer.from(wasm));
42
+
43
+ if (!process.argv.includes('-no-run')) {
44
+ console.log(`\n\n${underline('output')}`);
45
+ const t2 = performance.now();
46
+
47
+ exports.main();
48
+ print('\n');
49
+
50
+ if (!raw) console.log(bold(`\n\nexecuted in ${(performance.now() - t2).toFixed(2)}ms`));
51
+ }
52
+
53
+ if (!raw) console.log(bold(`wasm binary is ${wasm.byteLength} bytes`));
54
+ if (!raw) console.log(`total: ${(performance.now() - t0).toFixed(2)}ms`);
@@ -0,0 +1,47 @@
1
+ import compile from '../compiler/index.js';
2
+ import fs from 'node:fs';
3
+
4
+ let csv = `phase,time\n`;
5
+
6
+ csv += `node,${performance.now()}\n`;
7
+
8
+ const t0 = performance.now();
9
+ const file = process.argv.slice(2).find(x => x[0] !== '-');
10
+ const source = fs.readFileSync(file, 'utf8');
11
+ csv += `read,${performance.now() - t0}\n`;
12
+
13
+ console.log = x => {
14
+ if (x.includes(' in ')) {
15
+ csv += [ 'parse', 'codegen', 'opt', 'sections' ][parseInt(x[0]) - 1] + ',' + x.split(' in ')[1].slice(0, -2) + '\n';
16
+ }
17
+ };
18
+
19
+ const wasm = compile(source, [ 'info' ]);
20
+
21
+ let cache = '';
22
+ const print = str => {
23
+ cache += str;
24
+
25
+ if (str === '\n') {
26
+ process.stdout.write(cache);
27
+ cache = '';
28
+ }
29
+ };
30
+
31
+ const t1 = performance.now();
32
+ const { instance } = await WebAssembly.instantiate(wasm, {
33
+ '': {
34
+ p: i => print(Number(i).toString()),
35
+ c: i => print(String.fromCharCode(Number(i))),
36
+ a: c => { if (!Number(c)) throw new Error(`assert failed`); }
37
+ }
38
+ });
39
+ csv += `inst,${performance.now() - t1}\n`;
40
+
41
+ const t2 = performance.now();
42
+ instance.exports.m();
43
+ print('\n');
44
+
45
+ csv += `exec,${performance.now() - t2}`;
46
+
47
+ fs.writeFileSync(`profile.csv`, csv);
package/runner/repl.js ADDED
@@ -0,0 +1,99 @@
1
+ import compile from '../compiler/wrap.js';
2
+ import rev from './version.js';
3
+
4
+ import repl from 'node:repl';
5
+
6
+ // process.argv.push('-O0'); // disable opts
7
+
8
+ globalThis.valtype = 'f64';
9
+
10
+ const valtypeOpt = process.argv.find(x => x.startsWith('-valtype='));
11
+ if (valtypeOpt) valtype = valtypeOpt.split('=')[1];
12
+
13
+ console.log(`welcome to porffor rev ${rev.slice(0, 7)}`);
14
+ console.log(`info: using opt ${process.argv.find(x => x.startsWith('-O')) ?? '-O1'} and valtype ${valtype}`);
15
+ console.log();
16
+
17
+ let lastMemory, lastPages;
18
+ const PageSize = 65536;
19
+ const memoryToString = mem => {
20
+ let out = '';
21
+ const pages = lastPages.length;
22
+ const wasmPages = mem.buffer.byteLength / PageSize;
23
+
24
+ out += `\x1B[1mallocated ${mem.buffer.byteLength / 1024}KiB\x1B[0m for ${pages} things using ${wasmPages} Wasm page${wasmPages === 1 ? '' : 's'}\n`;
25
+
26
+ const buf = new Uint8Array(mem.buffer);
27
+
28
+ for (let i = 0; i < pages; i++) {
29
+ out += `\x1B[36m${lastPages[i]}\x1B[2m | \x1B[0m`;
30
+
31
+ for (let j = 0; j < 50; j++) {
32
+ const val = buf[i * pageSize + j];
33
+ if (val === 0) out += '\x1B[2m';
34
+ out += val.toString(16).padStart(2, '0');
35
+ if (val === 0) out += '\x1B[0m';
36
+ out += ' ';
37
+ }
38
+ out += '\n';
39
+ }
40
+
41
+ return out;
42
+ };
43
+
44
+ const alwaysPrev = process.argv.includes('-prev');
45
+
46
+ let prev = '';
47
+ const run = async (source, _context, _filename, callback, run = true) => {
48
+ let toRun = prev + source.trim();
49
+ if (alwaysPrev) prev = toRun + ';\n';
50
+
51
+ const { exports, wasm, pages } = await compile(toRun, []);
52
+ // fs.writeFileSync('out.wasm', Buffer.from(wasm));
53
+
54
+ if (run && exports.$) {
55
+ lastMemory = exports.$;
56
+ lastPages = [...pages.keys()];
57
+ }
58
+
59
+ const ret = run ? exports.main() : undefined;
60
+ callback(null, ret);
61
+
62
+ if (!alwaysPrev && (source.includes(' = ') || source.includes('let ') || source.includes('var ') || source.includes('const ') || source.includes('function '))) prev = toRun + ';\n';
63
+ // prev = toRun + ';\n';
64
+ };
65
+
66
+ const replServer = repl.start({ prompt: '> ', eval: run });
67
+
68
+ replServer.setupHistory('.repl_history', () => {});
69
+
70
+ replServer.defineCommand('memory', {
71
+ help: 'Log Wasm memory',
72
+ action() {
73
+ this.clearBufferedCommand();
74
+ console.log(memoryToString(lastMemory));
75
+ this.displayPrompt();
76
+ }
77
+ });
78
+ replServer.defineCommand('asm', {
79
+ help: 'Log Wasm decompiled bytecode',
80
+ async action() {
81
+ this.clearBufferedCommand();
82
+
83
+ try {
84
+ process.argv.push('-opt-funcs');
85
+ await run('', null, null, () => {}, false);
86
+ process.argv.pop();
87
+ } catch { }
88
+
89
+ this.displayPrompt();
90
+ }
91
+ });
92
+ replServer.defineCommand('js', {
93
+ help: 'Log JS being actually ran',
94
+ async action() {
95
+ this.clearBufferedCommand();
96
+ console.log(prev);
97
+ this.displayPrompt();
98
+ }
99
+ });
@@ -0,0 +1,38 @@
1
+ import fs from 'node:fs';
2
+ import compile from '../compiler/index.js';
3
+
4
+ // deno compat
5
+ const textEncoder = new TextEncoder();
6
+ if (typeof process === 'undefined') globalThis.process = { argv: ['', '', ...Deno.args], stdout: { write: str => Deno.writeAllSync(Deno.stdout, textEncoder.encode(str)) } };
7
+
8
+ let csv = `file,porffor i32 -O0,porffor i32 -O1,porffor i32 -O2,porffor i32 -O3,porffor i64 -O0,porffor i64 -O1,porffor i64 -O2,porffor i64 -O3,porffor f64 -O0, porffor f64 -O1, porffor f64 -O2, porffor f64 -O3\n`;
9
+ const perform = async (file, args) => {
10
+ process.argv = process.argv.slice(0, 2).concat(args);
11
+ const source = fs.readFileSync(file, 'utf8');
12
+
13
+ const { wasm } = compile(source, []);
14
+ const size = wasm.byteLength;
15
+
16
+ const label = `${file} ${args.join(' ')}`;
17
+ csv += `${size},`;
18
+ console.log(label, ' '.repeat(40 - label.length), `${size}b`);
19
+ };
20
+
21
+ const argsValtypes = [ '-valtype=i32', '-valtype=i64', '-valtype=f64' ];
22
+ const argsOptlevels = [ '-O0', '-O1', '-O2', '-O3' ];
23
+
24
+ for (const file of [ 'bench/prime_basic.js', 'bench/fib_iter.js', 'test/math_1.js', 'test/math_3.js', 'test/while_1.js', 'test/for_2.js', 'test/unary_3.js', 'test/updateexp_1.js', 'test/eq_3.js', 'test/empty.js' ]) {
25
+ const niceFile = file.split('/')[1].slice(0, -3);
26
+ csv += `${niceFile},`;
27
+
28
+ for (const x of argsValtypes) {
29
+ for (const y of argsOptlevels) {
30
+ await perform(file, [ x, y ]);
31
+ }
32
+ }
33
+
34
+ csv = csv.slice(0, -1) + '\n';
35
+ }
36
+
37
+ fs.writeFileSync('sizes.csv', csv);
38
+ console.log(csv);