porffor 0.2.0-fdf0fc5 → 0.14.0-032e4ad08
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/CONTRIBUTING.md +9 -3
- package/README.md +17 -14
- package/asur/index.js +1 -1
- package/byg/index.js +3 -24
- package/compiler/2c.js +66 -54
- package/compiler/assemble.js +51 -11
- package/compiler/builtins/annexb_string.js +10 -10
- package/compiler/builtins/annexb_string.ts +4 -3
- package/compiler/builtins/array.ts +85 -9
- package/compiler/builtins/base64.ts +2 -1
- package/compiler/builtins/boolean.ts +2 -2
- package/compiler/builtins/crypto.ts +2 -1
- package/compiler/builtins/date.ts +2 -3
- package/compiler/builtins/error.js +22 -0
- package/compiler/builtins/escape.ts +2 -3
- package/compiler/builtins/function.ts +1 -1
- package/compiler/builtins/int.ts +1 -1
- package/compiler/builtins/math.ts +410 -0
- package/compiler/builtins/number.ts +4 -7
- package/compiler/builtins/object.ts +1 -1
- package/compiler/builtins/porffor.d.ts +9 -8
- package/compiler/builtins/set.ts +197 -3
- package/compiler/builtins/string.ts +2 -1
- package/compiler/builtins/symbol.ts +62 -0
- package/compiler/builtins.js +41 -15
- package/compiler/codegen.js +653 -366
- package/compiler/decompile.js +3 -3
- package/compiler/embedding.js +2 -2
- package/compiler/encoding.js +0 -14
- package/compiler/expression.js +1 -1
- package/compiler/generated_builtins.js +771 -187
- package/compiler/index.js +5 -11
- package/compiler/opt.js +7 -7
- package/compiler/parse.js +2 -4
- package/compiler/precompile.js +18 -25
- package/compiler/prefs.js +6 -2
- package/compiler/prototype.js +185 -162
- package/compiler/wasmSpec.js +5 -0
- package/compiler/wrap.js +150 -90
- package/package.json +1 -1
- package/porffor_tmp.c +202 -0
- package/runner/compare.js +0 -1
- package/runner/debug.js +1 -6
- package/runner/index.js +5 -4
- package/runner/profiler.js +15 -42
- package/runner/repl.js +20 -10
- package/runner/sizes.js +2 -2
- package/runner/version.js +10 -8
package/compiler/wrap.js
CHANGED
@@ -1,12 +1,106 @@
|
|
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
|
-
import Prefs from './prefs.js';
|
5
|
-
import { log } from './log.js';
|
6
5
|
import { TYPES } from './types.js';
|
6
|
+
import { log } from './log.js';
|
7
|
+
import Prefs from './prefs.js';
|
7
8
|
|
8
9
|
const bold = x => `\u001b[1m${x}\u001b[0m`;
|
9
10
|
|
11
|
+
const porfToJSValue = ({ memory, funcs, pages }, value, type) => {
|
12
|
+
switch (type) {
|
13
|
+
case TYPES.boolean: return Boolean(value);
|
14
|
+
case TYPES.undefined: return undefined;
|
15
|
+
case TYPES.object: return value === 0 ? null : {};
|
16
|
+
|
17
|
+
case TYPES.function: {
|
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
|
+
|
25
|
+
if (!func) return function () {};
|
26
|
+
|
27
|
+
// make fake empty func for repl/etc
|
28
|
+
return {[func.name]() {}}[func.name];
|
29
|
+
}
|
30
|
+
|
31
|
+
case TYPES.string: {
|
32
|
+
const length = (new Int32Array(memory.buffer, value, 1))[0];
|
33
|
+
return Array.from(new Uint16Array(memory.buffer, value + 4, length)).map(x => String.fromCharCode(x)).join('');
|
34
|
+
}
|
35
|
+
|
36
|
+
case TYPES.bytestring: {
|
37
|
+
const length = (new Int32Array(memory.buffer, value, 1))[0];
|
38
|
+
return Array.from(new Uint8Array(memory.buffer, value + 4, length)).map(x => String.fromCharCode(x)).join('');
|
39
|
+
}
|
40
|
+
|
41
|
+
case TYPES.array: {
|
42
|
+
const length = (new Int32Array(memory.buffer, value, 1))[0];
|
43
|
+
|
44
|
+
const out = [];
|
45
|
+
for (let i = 0; i < length; i++) {
|
46
|
+
const offset = value + 4 + (i * 9);
|
47
|
+
|
48
|
+
// have to slice because of memory alignment (?)
|
49
|
+
const v = (new Float64Array(memory.buffer.slice(offset, offset + 8), 0, 1))[0];
|
50
|
+
const t = (new Uint8Array(memory.buffer, offset + 8, 1))[0];
|
51
|
+
|
52
|
+
// console.log(`reading value at index ${i}...`)
|
53
|
+
// console.log(' memory:', Array.from(new Uint8Array(memory.buffer, offset, 9)).map(x => x.toString(16).padStart(2, '0')).join(' '));
|
54
|
+
// console.log(' read:', { value: v, type: t }, '\n');
|
55
|
+
|
56
|
+
out.push(porfToJSValue({ memory, funcs, pages }, v, t));
|
57
|
+
}
|
58
|
+
|
59
|
+
return out;
|
60
|
+
}
|
61
|
+
|
62
|
+
case TYPES.date: {
|
63
|
+
const t = (new Float64Array(memory.buffer, value, 1))[0];
|
64
|
+
return new Date(t);
|
65
|
+
}
|
66
|
+
|
67
|
+
case TYPES.set: {
|
68
|
+
const size = (new Int32Array(memory.buffer, value, 1))[0];
|
69
|
+
|
70
|
+
const out = new Set();
|
71
|
+
for (let i = 0; i < size; i++) {
|
72
|
+
const offset = value + 4 + (i * 9);
|
73
|
+
|
74
|
+
// have to slice because of memory alignment (?)
|
75
|
+
const v = (new Float64Array(memory.buffer.slice(offset, offset + 8), 0, 1))[0];
|
76
|
+
const t = (new Uint8Array(memory.buffer, offset + 8, 1))[0];
|
77
|
+
|
78
|
+
// console.log(`reading value at index ${i}...`)
|
79
|
+
// console.log(' memory:', Array.from(new Uint8Array(memory.buffer, offset, 9)).map(x => x.toString(16).padStart(2, '0')).join(' '));
|
80
|
+
// console.log(' read:', { value: v, type: t }, '\n');
|
81
|
+
|
82
|
+
out.add(porfToJSValue({ memory, funcs, pages }, v, t));
|
83
|
+
}
|
84
|
+
|
85
|
+
return out;
|
86
|
+
}
|
87
|
+
|
88
|
+
case TYPES.symbol: {
|
89
|
+
const descStore = pages.get('bytestring: __Porffor_symbol_descStore/ptr').ind * pageSize;
|
90
|
+
const offset = descStore + 4 + ((value - 1) * 9);
|
91
|
+
|
92
|
+
const v = (new Float64Array(memory.buffer.slice(offset, offset + 8), 0, 1))[0];
|
93
|
+
const t = (new Uint8Array(memory.buffer, offset + 8, 1))[0];
|
94
|
+
|
95
|
+
const desc = porfToJSValue({ memory, funcs, pages }, v, t);
|
96
|
+
|
97
|
+
return Symbol(desc);
|
98
|
+
}
|
99
|
+
|
100
|
+
default: return value;
|
101
|
+
}
|
102
|
+
};
|
103
|
+
|
10
104
|
export default async (source, flags = [ 'module' ], customImports = {}, print = str => process.stdout.write(str)) => {
|
11
105
|
const times = [];
|
12
106
|
|
@@ -22,40 +116,12 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
22
116
|
times.push(performance.now() - t1);
|
23
117
|
if (Prefs.profileCompiler) console.log(bold(`compiled in ${times[0].toFixed(2)}ms`));
|
24
118
|
|
25
|
-
const
|
26
|
-
|
27
|
-
let instance;
|
28
|
-
try {
|
29
|
-
let wasmEngine = WebAssembly;
|
30
|
-
if (Prefs.asur) {
|
31
|
-
log.warning('wrap', 'using our !experimental! asur wasm engine instead of host to run');
|
32
|
-
wasmEngine = await import('../asur/index.js');
|
33
|
-
}
|
34
|
-
|
35
|
-
0, { instance } = await wasmEngine.instantiate(wasm, {
|
36
|
-
'': {
|
37
|
-
p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
|
38
|
-
c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
|
39
|
-
t: () => performance.now(),
|
40
|
-
u: () => performance.timeOrigin,
|
41
|
-
y: () => {},
|
42
|
-
z: () => {},
|
43
|
-
...customImports
|
44
|
-
}
|
45
|
-
});
|
46
|
-
} catch (e) {
|
47
|
-
// only backtrace for runner, not test262/etc
|
48
|
-
if (!process.argv[1].includes('/runner')) throw e;
|
49
|
-
|
50
|
-
const funcInd = parseInt(e.message.match(/function #([0-9]+) /)?.[1]);
|
51
|
-
const blobOffset = parseInt(e.message.split('@')?.[1]);
|
52
|
-
|
53
|
-
if (!funcInd) throw e;
|
119
|
+
const backtrace = (funcInd, blobOffset) => {
|
120
|
+
if (funcInd == null || blobOffset == null) return false;
|
54
121
|
|
55
122
|
// convert blob offset -> function wasm offset.
|
56
123
|
// this is not good code and is somewhat duplicated
|
57
124
|
// I just want it to work for debugging, I don't care about perf/yes
|
58
|
-
|
59
125
|
const func = funcs.find(x => x.index === funcInd);
|
60
126
|
const locals = Object.values(func.locals).sort((a, b) => a.idx - b.idx).slice(func.params.length).sort((a, b) => a.idx - b.idx);
|
61
127
|
|
@@ -73,7 +139,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
73
139
|
|
74
140
|
if (typeCount !== 0) localDecl.push(encodeLocal(typeCount, lastType));
|
75
141
|
|
76
|
-
const toFind = encodeVector(localDecl).concat(func.wasm.flat().filter(x => x != null && x <= 0xff).slice(0,
|
142
|
+
const toFind = encodeVector(localDecl).concat(func.wasm.flat().filter(x => x != null && x <= 0xff).slice(0, 60));
|
77
143
|
|
78
144
|
let i = 0;
|
79
145
|
for (; i < wasm.length; i++) {
|
@@ -88,7 +154,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
88
154
|
if (!mismatch) break;
|
89
155
|
}
|
90
156
|
|
91
|
-
if (i === wasm.length)
|
157
|
+
if (i === wasm.length) return false;
|
92
158
|
|
93
159
|
const offset = (blobOffset - i) + encodeVector(localDecl).length;
|
94
160
|
|
@@ -99,7 +165,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
99
165
|
if (cumLen === offset) break;
|
100
166
|
}
|
101
167
|
|
102
|
-
if (cumLen !== offset)
|
168
|
+
if (cumLen !== offset) return false;
|
103
169
|
|
104
170
|
i -= 1;
|
105
171
|
|
@@ -124,6 +190,38 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
124
190
|
console.log(decomp.join('\n'));
|
125
191
|
console.log('\x1B[90m...\x1B[0m\n');
|
126
192
|
|
193
|
+
return true;
|
194
|
+
};
|
195
|
+
|
196
|
+
const t2 = performance.now();
|
197
|
+
|
198
|
+
let instance;
|
199
|
+
try {
|
200
|
+
let wasmEngine = WebAssembly;
|
201
|
+
if (Prefs.asur) {
|
202
|
+
log.warning('wrap', 'using our !experimental! asur wasm engine instead of host to run');
|
203
|
+
wasmEngine = await import('../asur/index.js');
|
204
|
+
}
|
205
|
+
|
206
|
+
0, { instance } = await wasmEngine.instantiate(wasm, {
|
207
|
+
'': {
|
208
|
+
p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
|
209
|
+
c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
|
210
|
+
t: () => performance.now(),
|
211
|
+
u: () => performance.timeOrigin,
|
212
|
+
y: () => {},
|
213
|
+
z: () => {},
|
214
|
+
...customImports
|
215
|
+
}
|
216
|
+
});
|
217
|
+
} catch (e) {
|
218
|
+
// only backtrace for runner, not test262/etc
|
219
|
+
if (!process.argv[1].includes('/runner')) throw e;
|
220
|
+
|
221
|
+
const funcInd = parseInt(e.message.match(/function #([0-9]+) /)?.[1]);
|
222
|
+
const blobOffset = parseInt(e.message.split('@')?.[1]);
|
223
|
+
|
224
|
+
backtrace(funcInd, blobOffset);
|
127
225
|
throw e;
|
128
226
|
}
|
129
227
|
|
@@ -131,6 +229,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
131
229
|
if (Prefs.profileCompiler) console.log(`instantiated in ${times[1].toFixed(2)}ms`);
|
132
230
|
|
133
231
|
const exports = {};
|
232
|
+
const rawValues = process.argv.includes('-i');
|
134
233
|
|
135
234
|
const exceptTag = instance.exports['0'], memory = instance.exports['$'];
|
136
235
|
for (const x in instance.exports) {
|
@@ -148,62 +247,12 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
148
247
|
|
149
248
|
exports[func.name] = function() {
|
150
249
|
try {
|
151
|
-
const
|
152
|
-
|
153
|
-
if (_ret == null) return undefined;
|
154
|
-
|
155
|
-
const [ ret, type ] = _ret;
|
156
|
-
|
157
|
-
// if (ret >= typeBase && ret <= typeBase + 8) return ret > (typeBase + 7) ? 'object' : TYPES[ret];
|
158
|
-
|
159
|
-
switch (type) {
|
160
|
-
case TYPES.boolean: return Boolean(ret);
|
161
|
-
case TYPES.undefined: return undefined;
|
162
|
-
case TYPES.object: return ret === 0 ? null : {};
|
163
|
-
|
164
|
-
case TYPES.string: {
|
165
|
-
const pointer = ret;
|
166
|
-
const length = (new Int32Array(memory.buffer, pointer, 1))[0];
|
250
|
+
const ret = exp.apply(this, arguments);
|
251
|
+
if (ret == null) return undefined;
|
167
252
|
|
168
|
-
|
169
|
-
}
|
253
|
+
if (rawValues) return { value: ret[0], type: ret[1], js: porfToJSValue({ memory, funcs, pages }, ret[0], ret[1]) };
|
170
254
|
|
171
|
-
|
172
|
-
// wasm func index, including all imports
|
173
|
-
const func = funcs.find(x => (x.originalIndex ?? x.index) === ret);
|
174
|
-
// if (!func) return ret;
|
175
|
-
if (!func) return function () {};
|
176
|
-
|
177
|
-
// make fake empty func for repl/etc
|
178
|
-
return {[func.name]() {}}[func.name];
|
179
|
-
}
|
180
|
-
|
181
|
-
case TYPES.array: {
|
182
|
-
const pointer = ret;
|
183
|
-
const length = (new Int32Array(memory.buffer, pointer, 1))[0];
|
184
|
-
|
185
|
-
// have to slice because of memory alignment
|
186
|
-
const buf = memory.buffer.slice(pointer + 4, pointer + 4 + 8 * length);
|
187
|
-
|
188
|
-
return Array.from(new Float64Array(buf));
|
189
|
-
}
|
190
|
-
|
191
|
-
case TYPES.bytestring: {
|
192
|
-
const pointer = ret;
|
193
|
-
const length = (new Int32Array(memory.buffer, pointer, 1))[0];
|
194
|
-
|
195
|
-
return Array.from(new Uint8Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
|
196
|
-
}
|
197
|
-
|
198
|
-
case TYPES.date: {
|
199
|
-
const pointer = ret;
|
200
|
-
const value = (new Float64Array(memory.buffer, pointer, 1))[0];
|
201
|
-
|
202
|
-
return new Date(value);
|
203
|
-
}
|
204
|
-
|
205
|
-
default: return ret;
|
206
|
-
}
|
255
|
+
return porfToJSValue({ memory, funcs, pages }, ret[0], ret[1]);
|
207
256
|
} catch (e) {
|
208
257
|
if (e.is && e.is(exceptTag)) {
|
209
258
|
const exceptId = e.getArg(exceptTag, 0);
|
@@ -218,6 +267,17 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
218
267
|
throw new constructor(exception.message);
|
219
268
|
}
|
220
269
|
|
270
|
+
if (e instanceof WebAssembly.RuntimeError) {
|
271
|
+
// only backtrace for runner, not test262/etc
|
272
|
+
if (!process.argv[1].includes('/runner')) throw e;
|
273
|
+
|
274
|
+
const match = e.stack.match(/wasm-function\[([0-9]+)\]:([0-9a-z]+)/) ?? [];
|
275
|
+
const funcInd = parseInt(match[1]);
|
276
|
+
const blobOffset = parseInt(match[2]);
|
277
|
+
|
278
|
+
backtrace(funcInd, blobOffset);
|
279
|
+
}
|
280
|
+
|
221
281
|
throw e;
|
222
282
|
}
|
223
283
|
};
|
package/package.json
CHANGED
package/porffor_tmp.c
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
#include <stdint.h>
|
2
|
+
#include <string.h>
|
3
|
+
#include <stdio.h>
|
4
|
+
#include <stdlib.h>
|
5
|
+
|
6
|
+
typedef uint8_t i8;
|
7
|
+
typedef uint16_t i16;
|
8
|
+
typedef int32_t i32;
|
9
|
+
typedef uint32_t u32;
|
10
|
+
typedef int64_t i64;
|
11
|
+
typedef uint64_t u64;
|
12
|
+
typedef float f32;
|
13
|
+
typedef double f64;
|
14
|
+
|
15
|
+
f64 NAN = 0e+0/0e+0;
|
16
|
+
|
17
|
+
struct ReturnValue {
|
18
|
+
f64 value;
|
19
|
+
i32 type;
|
20
|
+
};
|
21
|
+
|
22
|
+
char _memory[131072];
|
23
|
+
|
24
|
+
int _argc; char** _argv;
|
25
|
+
i32 i32_load(i32 align, i32 offset, i32 pointer) {
|
26
|
+
i32 out;
|
27
|
+
memcpy(&out, _memory + offset + pointer, sizeof(out));
|
28
|
+
return out;
|
29
|
+
}
|
30
|
+
|
31
|
+
i32 i32_load8_u(i32 align, i32 offset, i32 pointer) {
|
32
|
+
i8 out;
|
33
|
+
memcpy(&out, _memory + offset + pointer, sizeof(out));
|
34
|
+
return out;
|
35
|
+
}
|
36
|
+
|
37
|
+
void i32_store(i32 align, i32 offset, i32 pointer, i32 value) {
|
38
|
+
memcpy(_memory + offset + pointer, &value, sizeof(value));
|
39
|
+
}
|
40
|
+
|
41
|
+
void __Porffor_readArgv(u32 index, u32 outPtr) {
|
42
|
+
if (index >= _argc) {
|
43
|
+
printf("expected %d arguments\n", index);
|
44
|
+
exit(1);
|
45
|
+
}
|
46
|
+
|
47
|
+
char* arg = _argv[index];
|
48
|
+
|
49
|
+
u32 read = 0;
|
50
|
+
char* out = _memory + outPtr + 4;
|
51
|
+
char ch;
|
52
|
+
while ((ch = *(arg++)) != 0) {
|
53
|
+
out[read++] = ch;
|
54
|
+
}
|
55
|
+
|
56
|
+
memcpy(_memory + outPtr, &read, sizeof(read));
|
57
|
+
}
|
58
|
+
void __Porffor_readFile(u32 pathPtr, u32 outPtr) {
|
59
|
+
char* path = _memory + pathPtr + 4;
|
60
|
+
FILE* fp = fopen(path, "r");
|
61
|
+
if (fp == NULL) {
|
62
|
+
printf("failed to open file: %s\n", path);
|
63
|
+
exit(1);
|
64
|
+
}
|
65
|
+
|
66
|
+
u32 read = 0;
|
67
|
+
char* out = _memory + outPtr + 4;
|
68
|
+
char ch;
|
69
|
+
while ((ch = fgetc(fp)) != EOF) {
|
70
|
+
out[read++] = ch;
|
71
|
+
}
|
72
|
+
|
73
|
+
fclose(fp);
|
74
|
+
|
75
|
+
memcpy(_memory + outPtr, &read, sizeof(read));
|
76
|
+
}
|
77
|
+
|
78
|
+
f64 out = 0;
|
79
|
+
i32 outdtype = 0;
|
80
|
+
|
81
|
+
void __Porffor_print(f64 x, i32 y) {
|
82
|
+
i32 a = 0;
|
83
|
+
i32 b = 0;
|
84
|
+
i32 dtypeswitch_tmp = 0;
|
85
|
+
|
86
|
+
dtypeswitch_tmp = y;
|
87
|
+
// block
|
88
|
+
// if
|
89
|
+
if (dtypeswitch_tmp == 0) {
|
90
|
+
printf("%g\n", x);
|
91
|
+
goto j0;
|
92
|
+
}
|
93
|
+
// end
|
94
|
+
j1:;
|
95
|
+
// if
|
96
|
+
if (dtypeswitch_tmp == 1) {
|
97
|
+
// if
|
98
|
+
if (((u32)x) != 0) {
|
99
|
+
printf("%c", (int)(1.16e+2));
|
100
|
+
printf("%c", (int)(1.14e+2));
|
101
|
+
printf("%c", (int)(1.17e+2));
|
102
|
+
printf("%c", (int)(1.01e+2));
|
103
|
+
} else {
|
104
|
+
printf("%c", (int)(1.02e+2));
|
105
|
+
printf("%c", (int)(9.7e+1));
|
106
|
+
printf("%c", (int)(1.08e+2));
|
107
|
+
printf("%c", (int)(1.15e+2));
|
108
|
+
printf("%c", (int)(1.01e+2));
|
109
|
+
}
|
110
|
+
// end
|
111
|
+
j3:;
|
112
|
+
goto j0;
|
113
|
+
}
|
114
|
+
// end
|
115
|
+
j2:;
|
116
|
+
// if
|
117
|
+
if (dtypeswitch_tmp == 3) {
|
118
|
+
printf("%c", (int)(1.17e+2));
|
119
|
+
printf("%c", (int)(1.1e+2));
|
120
|
+
printf("%c", (int)(1e+2));
|
121
|
+
printf("%c", (int)(1.01e+2));
|
122
|
+
printf("%c", (int)(1.02e+2));
|
123
|
+
printf("%c", (int)(1.05e+2));
|
124
|
+
printf("%c", (int)(1.1e+2));
|
125
|
+
printf("%c", (int)(1.01e+2));
|
126
|
+
printf("%c", (int)(1e+2));
|
127
|
+
goto j0;
|
128
|
+
}
|
129
|
+
// end
|
130
|
+
j4:;
|
131
|
+
// if
|
132
|
+
if (dtypeswitch_tmp == 4) {
|
133
|
+
// if
|
134
|
+
if (((u32)x) != 0) {
|
135
|
+
printf("%c", (int)(1.23e+2));
|
136
|
+
printf("%c", (int)(1.25e+2));
|
137
|
+
} else {
|
138
|
+
printf("%c", (int)(1.1e+2));
|
139
|
+
printf("%c", (int)(1.17e+2));
|
140
|
+
printf("%c", (int)(1.08e+2));
|
141
|
+
printf("%c", (int)(1.08e+2));
|
142
|
+
}
|
143
|
+
// end
|
144
|
+
j6:;
|
145
|
+
goto j0;
|
146
|
+
}
|
147
|
+
// end
|
148
|
+
j5:;
|
149
|
+
// if
|
150
|
+
if (dtypeswitch_tmp == 5) {
|
151
|
+
printf("%c", (int)(1.02e+2));
|
152
|
+
printf("%c", (int)(1.17e+2));
|
153
|
+
printf("%c", (int)(1.1e+2));
|
154
|
+
printf("%c", (int)(9.9e+1));
|
155
|
+
printf("%c", (int)(1.16e+2));
|
156
|
+
printf("%c", (int)(1.05e+2));
|
157
|
+
printf("%c", (int)(1.11e+2));
|
158
|
+
printf("%c", (int)(1.1e+2));
|
159
|
+
printf("%c", (int)(3.2e+1));
|
160
|
+
printf("%c", (int)(4e+1));
|
161
|
+
printf("%c", (int)(4.1e+1));
|
162
|
+
printf("%c", (int)(3.2e+1));
|
163
|
+
printf("%c", (int)(1.23e+2));
|
164
|
+
printf("%c", (int)(1.25e+2));
|
165
|
+
goto j0;
|
166
|
+
}
|
167
|
+
// end
|
168
|
+
j7:;
|
169
|
+
// if
|
170
|
+
if (dtypeswitch_tmp == 18) {
|
171
|
+
a = (u32)x;
|
172
|
+
b = i32_load(1, 0, a) + a;
|
173
|
+
// loop
|
174
|
+
j9:;
|
175
|
+
printf("%c", (int)((f64)(i32_load8_u(0, 4, a))));
|
176
|
+
a = a + 1;
|
177
|
+
if (a != b) {
|
178
|
+
goto j9;
|
179
|
+
}
|
180
|
+
// end
|
181
|
+
goto j0;
|
182
|
+
}
|
183
|
+
// end
|
184
|
+
j8:;
|
185
|
+
printf("%g\n", x);
|
186
|
+
// end
|
187
|
+
j0:;
|
188
|
+
}
|
189
|
+
|
190
|
+
int main(int argc, char* argv[]) {
|
191
|
+
_argc = argc; _argv = argv;
|
192
|
+
|
193
|
+
out = 1e+0;
|
194
|
+
outdtype = 18;
|
195
|
+
i32_store(1, 0, 65536, 0);
|
196
|
+
__Porffor_readArgv((u32)(0e+0), (u32)(6.5536e+4));
|
197
|
+
__Porffor_readFile((u32)(undefined), (u32)(out));
|
198
|
+
__Porffor_print(out, outdtype);
|
199
|
+
printf("%c", (int)(1e+1));
|
200
|
+
|
201
|
+
return 0;
|
202
|
+
}
|
package/runner/compare.js
CHANGED
package/runner/debug.js
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
2
|
|
3
3
|
import compile from '../compiler/wrap.js';
|
4
|
-
import fs from 'node:fs';
|
5
|
-
|
6
4
|
import Byg from '../byg/index.js';
|
5
|
+
import fs from 'node:fs';
|
7
6
|
|
8
7
|
const file = process.argv.slice(2).find(x => x[0] !== '-');
|
9
8
|
let source = fs.readFileSync(file, 'utf8');
|
@@ -19,7 +18,6 @@ source = source.replace(/^\s*(function|const)\s*([a-zA-Z0-9]+)(\s*=\s*)?\([^)]*\
|
|
19
18
|
|
20
19
|
const lines = source.split('\n');
|
21
20
|
for (let i = 0; i < lines.length; i++) {
|
22
|
-
// lines[line] = lines[line].replace(/^[^\n}]*;$/, _ => `profile(${line});${_}`);
|
23
21
|
if (lines[i].trim().replace('}', '') !== '') lines[i] = `profile1(Porffor.wasm.i32.const(${i}));` + lines[i];
|
24
22
|
}
|
25
23
|
source = lines.join('\n');
|
@@ -35,8 +33,6 @@ const byg = Byg({
|
|
35
33
|
}
|
36
34
|
});
|
37
35
|
|
38
|
-
// console.log(source);
|
39
|
-
|
40
36
|
let stepIn = false, stepOut = false;
|
41
37
|
const callStack = [];
|
42
38
|
|
@@ -72,7 +68,6 @@ try {
|
|
72
68
|
[
|
73
69
|
{
|
74
70
|
x: termWidth - 1 - 40 - 6,
|
75
|
-
// y: () => termHeight - 20 - 1 - 4,
|
76
71
|
y: () => 4,
|
77
72
|
width: 40,
|
78
73
|
height: 20,
|
package/runner/index.js
CHANGED
@@ -25,7 +25,7 @@ if (process.argv.includes('--help')) {
|
|
25
25
|
console.log(`Usage: \x1B[1mporf [command] path/to/script.js [...prefs] [...args]\x1B[0m`);
|
26
26
|
|
27
27
|
// commands
|
28
|
-
console.log(`\n\
|
28
|
+
console.log(`\n\x1B[1mCommands:\x1B[0m`);
|
29
29
|
for (const [ cmd, [ color, desc ] ] of Object.entries({
|
30
30
|
run: [ 34, 'Run a JS file' ],
|
31
31
|
wasm: [ 34, 'Compile a JS file to a Wasm binary\n' ],
|
@@ -60,8 +60,10 @@ if (process.argv.includes('--help')) {
|
|
60
60
|
|
61
61
|
let file = process.argv.slice(2).find(x => x[0] !== '-');
|
62
62
|
if (['run', 'wasm', 'native', 'c', 'profile', 'debug', 'debug-wasm'].includes(file)) {
|
63
|
+
// remove this arg
|
64
|
+
process.argv.splice(process.argv.indexOf(file), 1);
|
65
|
+
|
63
66
|
if (file === 'profile') {
|
64
|
-
process.argv.splice(process.argv.indexOf(file), 1);
|
65
67
|
await import('./profiler.js');
|
66
68
|
await new Promise(() => {}); // do nothing for the rest of this file
|
67
69
|
}
|
@@ -75,12 +77,11 @@ if (['run', 'wasm', 'native', 'c', 'profile', 'debug', 'debug-wasm'].includes(fi
|
|
75
77
|
}
|
76
78
|
|
77
79
|
if (file === 'debug') {
|
78
|
-
process.argv.splice(process.argv.indexOf(file), 1);
|
79
80
|
await import('./debug.js');
|
80
81
|
await new Promise(() => {}); // do nothing for the rest of this file
|
81
82
|
}
|
82
83
|
|
83
|
-
file = process.argv.slice(
|
84
|
+
file = process.argv.slice(2).find(x => x[0] !== '-');
|
84
85
|
|
85
86
|
const nonOptOutFile = process.argv.slice(process.argv.indexOf(file) + 1).find(x => x[0] !== '-');
|
86
87
|
if (nonOptOutFile) {
|
package/runner/profiler.js
CHANGED
@@ -3,22 +3,12 @@
|
|
3
3
|
import compile from '../compiler/wrap.js';
|
4
4
|
import fs from 'node:fs';
|
5
5
|
|
6
|
-
import Prefs from '../compiler/prefs.js';
|
7
|
-
|
8
|
-
// const fast = Prefs.profiler === 'fast';
|
9
|
-
const fast = !Prefs.experimentalProfiler;
|
10
|
-
|
11
6
|
const file = process.argv.slice(2).find(x => x[0] !== '-');
|
12
7
|
let source = fs.readFileSync(file, 'utf8');
|
13
8
|
|
14
9
|
let profileId = 0;
|
15
|
-
|
16
|
-
// source = fast ? source.replace(/^[^\n}]*;$/mg, _ => `profile(Porffor.wasm.i32.const(${profileId++}));${_}profile(Porffor.wasm.i32.const(${profileId++}));`) : source.replace(/^[^\n}]*;$/mg, _ => `profile(${profileId++});profile(${profileId++});${_}profile(${profileId++});`);
|
17
|
-
source = fast ? source.replace(/^[^\n}]*;$/mg, _ => `profile1(Porffor.wasm.i32.const(${profileId}));${_}profile2(Porffor.wasm.i32.const(${profileId++}));`) : source.replace(/^[^\n}]*;$/mg, _ => `profile(${profileId++});profile(${profileId++});${_}profile(${profileId++});`);
|
10
|
+
source = source.replace(/^[^\n}]*;$/mg, _ => `profile1(Porffor.wasm.i32.const(${profileId}));${_}profile2(Porffor.wasm.i32.const(${profileId++}));`)
|
18
11
|
|
19
|
-
// console.log(source);
|
20
|
-
|
21
|
-
// let tmp = new Array(profileId).fill(0);
|
22
12
|
let tmp = new Array(profileId).fill(0);
|
23
13
|
let times = new Array(profileId).fill(0);
|
24
14
|
let samples = 0;
|
@@ -31,31 +21,19 @@ let last = 0;
|
|
31
21
|
|
32
22
|
try {
|
33
23
|
const { exports } = await compile(source, process.argv.includes('--module') ? [ 'module' ] : [], {
|
34
|
-
y:
|
24
|
+
y: n => {
|
35
25
|
tmp[n] = performance.now();
|
36
|
-
}
|
37
|
-
z:
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
// if (n % 3 === 2) {
|
48
|
-
// tmp[n] += (performance.now() - tmp[n - 1]) - (tmp[n - 1] - tmp[n - 2]);
|
49
|
-
// samples++;
|
50
|
-
|
51
|
-
// if (performance.now() > last) {
|
52
|
-
// process.stdout.write(`\r${spinner[spin++ % 4]} running: collected ${samples} samples...`);
|
53
|
-
// last = performance.now() + 100;
|
54
|
-
// }
|
55
|
-
// } else {
|
56
|
-
// tmp[n] = performance.now();
|
57
|
-
// }
|
58
|
-
// }
|
26
|
+
},
|
27
|
+
z: n => {
|
28
|
+
const t = performance.now();
|
29
|
+
times[n] += t - tmp[n];
|
30
|
+
|
31
|
+
samples++;
|
32
|
+
if (t > last) {
|
33
|
+
process.stdout.write(`\r${spinner[spin++ % 4]} running: collected ${samples} samples...`);
|
34
|
+
last = t + 100;
|
35
|
+
}
|
36
|
+
}
|
59
37
|
});
|
60
38
|
|
61
39
|
const start = performance.now();
|
@@ -64,14 +42,11 @@ try {
|
|
64
42
|
|
65
43
|
const total = performance.now() - start;
|
66
44
|
|
67
|
-
console.log(`\
|
45
|
+
console.log(`\ntotal: ${total}ms\nsamples: ${samples}\n\n\n` + source.split('\n').map(x => {
|
68
46
|
let time = 0;
|
69
47
|
if (x.startsWith('profile')) {
|
70
|
-
// const id = parseInt(x.slice(8, x.indexOf(')')));
|
71
|
-
// const id = parseInt(x.slice(31, x.indexOf(')') + 1));
|
72
48
|
const id = parseInt(x.slice(32, x.indexOf(')')));
|
73
|
-
|
74
|
-
time = fast ? times[id] : tmp[id + 2];
|
49
|
+
time = times[id]
|
75
50
|
}
|
76
51
|
|
77
52
|
let color = [ 0, 0, 0 ];
|
@@ -85,8 +60,6 @@ try {
|
|
85
60
|
|
86
61
|
const ansiColor = `2;${color[0]};${color[1]};${color[2]}m`;
|
87
62
|
|
88
|
-
// const line = x.replace(/profile\([0-9]+\);/g, '');
|
89
|
-
// const line = x.replace(/profile\(Porffor.wasm.i32.const\([0-9]+\)\);/g, '');
|
90
63
|
const line = x.replace(/profile[0-9]\(Porffor.wasm.i32.const\([0-9]+\)\);/g, '');
|
91
64
|
|
92
65
|
if (percents) return `\x1b[48;${ansiColor}\x1b[97m${time ? ((time * 100).toFixed(0).padStart(4, ' ') + '%') : ' '}\x1b[0m\x1b[38;${ansiColor}▌\x1b[0m ${line}`;
|