porffor 0.60.2 → 0.60.4
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/AGENT.md +20 -0
- package/compiler/2c.js +17 -0
- package/compiler/builtins/_internal_object.ts +5 -5
- package/compiler/builtins/array.ts +1 -1
- package/compiler/builtins/date.ts +1 -1
- package/compiler/builtins/json.ts +3 -3
- package/compiler/builtins/object.ts +1 -2
- package/compiler/builtins/object_hiddenPrototype.js +1 -2
- package/compiler/builtins/typedarray.js +3 -3
- package/compiler/builtins/z_ecma262.ts +4 -6
- package/compiler/builtins_precompiled.js +473 -473
- package/compiler/codegen.js +5 -27
- package/compiler/index.js +43 -1
- package/foo.js +9 -0
- package/package.json +1 -1
- package/runtime/index.js +1 -1
package/AGENT.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
you are an assistant coder for Porffor - an early javascript and typescript to webassembly and native ahead-of-time compiler. the codebase is written in js and ts.
|
2
|
+
|
3
|
+
- built-ins apis (Date, String.prototype, etc) are written in ts inside `compiler/builtins`
|
4
|
+
- once you update a file inside that directory, you MUST run `./porf precompile` to compile to make your changes effective
|
5
|
+
- test your work using the test262 tools available, iterate independently but do not get stuck on one chain of thought or approach. paths for test262 tools should be relative to the 'test262/test' directory (e.g., 'built-ins/RegExp' NOT 'test262/test/built-ins/RegExp').
|
6
|
+
- to get an overview of the most failing directories, use the command: `node test262/fails.cjs`
|
7
|
+
- to just evaluate code in the engine, use the command: `./porf -p "..."`
|
8
|
+
- after finishing, check if your work/diff could be simplified
|
9
|
+
- always use single quotes (unless double is required)
|
10
|
+
- 2-space indentation, LF line endings, no trailing whitespace
|
11
|
+
- built-in APIs in `compiler/builtins/` written in TypeScript
|
12
|
+
- inline code in built-ins, avoid helper functions
|
13
|
+
- use semicolons
|
14
|
+
- do not use trailing commas
|
15
|
+
- use const/let, avoid var
|
16
|
+
- follow existing naming: camelCase for variables, PascalCase for types
|
17
|
+
- when possible, do not concat strings and instead write to them directly using wasm memory
|
18
|
+
- there are no closures, you cannot use locals between functions. use arguments or globals if really necessary
|
19
|
+
- The user prefers that prototype functions not have explicit return types in this codebase.
|
20
|
+
- The user prefers not to use global variables in built-in functions.
|
package/compiler/2c.js
CHANGED
@@ -612,6 +612,21 @@ export default ({ funcs, globals, data, pages }) => {
|
|
612
612
|
let func = funcs.find(x => x.index === i[1]);
|
613
613
|
if (!func) {
|
614
614
|
const importFunc = importFuncs[i[1]];
|
615
|
+
if (Prefs['2cWasmImports']) {
|
616
|
+
const name = '__porf_import_' + importFunc.name;
|
617
|
+
if (!prepend.has(name)) {
|
618
|
+
prepend.set(name, `
|
619
|
+
__attribute__((import_module(""), import_name("${importFunc.import}")))
|
620
|
+
extern ${importFunc.returns.length > 0 ? CValtype[importFunc.returns[0]] : 'void'} ${name}(${importFunc.params.map(x => CValtype[x]).join(', ')});`);
|
621
|
+
}
|
622
|
+
|
623
|
+
const call = `${name}(${importFunc.params.length > 0 ? vals.pop() : ''})`;
|
624
|
+
if (importFunc.returns.length > 0) vals.push(call);
|
625
|
+
else line(call);
|
626
|
+
|
627
|
+
break;
|
628
|
+
}
|
629
|
+
|
615
630
|
switch (importFunc.name) {
|
616
631
|
case 'print':
|
617
632
|
line(`printf("${valtype === 'f64' ? '%.15g' : '%i'}", ${vals.pop()})`);
|
@@ -807,6 +822,8 @@ export default ({ funcs, globals, data, pages }) => {
|
|
807
822
|
// todo: allow catching
|
808
823
|
const type = vals.pop();
|
809
824
|
const val = vals.pop();
|
825
|
+
if (Prefs['2cWasmImports']) break;
|
826
|
+
|
810
827
|
line(`printf("Uncaught ")`);
|
811
828
|
|
812
829
|
// const id = tmpId++;
|
@@ -172,15 +172,15 @@ local.set ${obj}`;
|
|
172
172
|
// it does not, make it
|
173
173
|
const underlying: object = {};
|
174
174
|
if (Porffor.type(_obj) == Porffor.TYPES.function) {
|
175
|
+
__Porffor_object_fastAdd(underlying, 'length', __Porffor_funcLut_length(obj), 0b0010);
|
176
|
+
__Porffor_object_fastAdd(underlying, 'name', __Porffor_funcLut_name(obj), 0b0010);
|
177
|
+
|
175
178
|
if (ecma262.IsConstructor(_obj)) { // constructor
|
176
179
|
// set prototype and prototype.constructor if function and constructor
|
177
180
|
const proto: object = {};
|
178
181
|
__Porffor_object_fastAdd(underlying, 'prototype', proto, 0b1000);
|
179
182
|
__Porffor_object_fastAdd(proto, 'constructor', _obj, 0b1010);
|
180
183
|
}
|
181
|
-
|
182
|
-
__Porffor_object_fastAdd(underlying, 'name', __Porffor_funcLut_name(obj), 0b0010);
|
183
|
-
__Porffor_object_fastAdd(underlying, 'length', __Porffor_funcLut_length(obj), 0b0010);
|
184
184
|
}
|
185
185
|
|
186
186
|
if (Porffor.type(_obj) == Porffor.TYPES.array) {
|
@@ -206,8 +206,8 @@ local.set x#type`;
|
|
206
206
|
|
207
207
|
if (Porffor.fastOr(
|
208
208
|
Porffor.type(_obj) == Porffor.TYPES.string,
|
209
|
-
Porffor.type(_obj) == Porffor.TYPES.stringobject
|
210
|
-
) {
|
209
|
+
Porffor.type(_obj) == Porffor.TYPES.stringobject
|
210
|
+
)) {
|
211
211
|
const len: i32 = (obj as string).length;
|
212
212
|
__Porffor_object_fastAdd(underlying, 'length', len, 0b0000);
|
213
213
|
|
@@ -42,7 +42,7 @@ export const __Array_from = (arg: any, mapFn: any): any[] => {
|
|
42
42
|
|
43
43
|
if (Porffor.fastOr(
|
44
44
|
Porffor.type(arg) == Porffor.TYPES.array,
|
45
|
-
Porffor.type(arg)
|
45
|
+
(Porffor.type(arg) | 0b10000000) == Porffor.TYPES.bytestring,
|
46
46
|
Porffor.type(arg) == Porffor.TYPES.set,
|
47
47
|
Porffor.fastAnd(Porffor.type(arg) >= Porffor.TYPES.uint8clampedarray, Porffor.type(arg) <= Porffor.TYPES.float64array)
|
48
48
|
)) {
|
@@ -1832,7 +1832,7 @@ export const Date = function (v0: unknown, v1: unknown, v2: unknown, v3: unknown
|
|
1832
1832
|
} else {
|
1833
1833
|
// c. Else,
|
1834
1834
|
// ii. If v is a String, then
|
1835
|
-
if (
|
1835
|
+
if ((Porffor.type(v0) | 0b10000000) == Porffor.TYPES.bytestring) {
|
1836
1836
|
// 1. Assert: The next step never returns an abrupt completion because v is a String.
|
1837
1837
|
|
1838
1838
|
// 2. Let tv be the result of parsing v as a date, in exactly the same manner as for the parse method (21.4.3.2).
|
@@ -311,7 +311,7 @@ export const __JSON_parse = (_: bytestring) => {
|
|
311
311
|
Porffor.bytestring.appendChar(out, ch);
|
312
312
|
pos++;
|
313
313
|
}
|
314
|
-
}
|
314
|
+
}
|
315
315
|
throw new SyntaxError('Unterminated string');
|
316
316
|
}
|
317
317
|
|
@@ -326,7 +326,7 @@ export const __JSON_parse = (_: bytestring) => {
|
|
326
326
|
}
|
327
327
|
|
328
328
|
while (true) {
|
329
|
-
|
329
|
+
Porffor.array.fastPush(arr, parseValue());
|
330
330
|
skipWhitespace();
|
331
331
|
if (pos >= len) throw new SyntaxError('Unterminated array');
|
332
332
|
|
@@ -396,7 +396,7 @@ export const __JSON_parse = (_: bytestring) => {
|
|
396
396
|
else break;
|
397
397
|
}
|
398
398
|
|
399
|
-
return
|
399
|
+
return ecma262.StringToNumber(__ByteString_prototype_slice(text, start, pos));
|
400
400
|
}
|
401
401
|
|
402
402
|
throw new SyntaxError('Unexpected token');
|
@@ -690,8 +690,7 @@ export const __Object_prototype_toString = (_this: any) => {
|
|
690
690
|
Porffor.type(_this) == Porffor.TYPES.number,
|
691
691
|
Porffor.type(_this) == Porffor.TYPES.numberobject)) return '[object Number]';
|
692
692
|
if (Porffor.fastOr(
|
693
|
-
Porffor.type(_this) == Porffor.TYPES.
|
694
|
-
Porffor.type(_this) == Porffor.TYPES.bytestring,
|
693
|
+
(Porffor.type(_this) | 0b10000000) == Porffor.TYPES.bytestring,
|
695
694
|
Porffor.type(_this) == Porffor.TYPES.stringobject)) return '[object String]';
|
696
695
|
if (Porffor.type(_this) == Porffor.TYPES.date) return '[object Date]';
|
697
696
|
if (Porffor.type(_this) == Porffor.TYPES.regexp) return '[object RegExp]';
|
@@ -3,8 +3,7 @@ export default ({ TYPES, TYPE_NAMES }) => {
|
|
3
3
|
export const __Porffor_object_getHiddenPrototype = (trueType: i32): any => {
|
4
4
|
if (Porffor.comptime.flag\`hasFunc.#get___String_prototype\`) {
|
5
5
|
if (Porffor.fastOr(
|
6
|
-
trueType == Porffor.TYPES.
|
7
|
-
trueType == Porffor.TYPES.bytestring,
|
6
|
+
(trueType | 0b10000000) == Porffor.TYPES.bytestring,
|
8
7
|
trueType == Porffor.TYPES.stringobject
|
9
8
|
)) return __String_prototype;
|
10
9
|
}
|
@@ -46,7 +46,7 @@ export default async () => {
|
|
46
46
|
|
47
47
|
if (Porffor.fastOr(
|
48
48
|
Porffor.type(arg) == Porffor.TYPES.array,
|
49
|
-
Porffor.type(arg)
|
49
|
+
(Porffor.type(arg) | 0b10000000) == Porffor.TYPES.bytestring,
|
50
50
|
Porffor.type(arg) == Porffor.TYPES.set,
|
51
51
|
Porffor.fastAnd(Porffor.type(arg) >= Porffor.TYPES.uint8clampedarray, Porffor.type(arg) <= Porffor.TYPES.float64array)
|
52
52
|
)) {
|
@@ -77,7 +77,7 @@ export const __${name}_from = (arg: any, mapFn: any): ${name} => {
|
|
77
77
|
|
78
78
|
if (Porffor.fastOr(
|
79
79
|
Porffor.type(arg) == Porffor.TYPES.array,
|
80
|
-
Porffor.type(arg)
|
80
|
+
(Porffor.type(arg) | 0b10000000) == Porffor.TYPES.bytestring,
|
81
81
|
Porffor.type(arg) == Porffor.TYPES.set,
|
82
82
|
Porffor.fastAnd(Porffor.type(arg) >= Porffor.TYPES.uint8clampedarray, Porffor.type(arg) <= Porffor.TYPES.float64array)
|
83
83
|
)) {
|
@@ -164,7 +164,7 @@ export const __${name}_prototype_set = (_this: ${name}, array: any, offset: numb
|
|
164
164
|
|
165
165
|
if (Porffor.fastOr(
|
166
166
|
Porffor.type(array) == Porffor.TYPES.array,
|
167
|
-
Porffor.type(array)
|
167
|
+
(Porffor.type(array) | 0b10000000) == Porffor.TYPES.bytestring,
|
168
168
|
Porffor.type(array) == Porffor.TYPES.set,
|
169
169
|
Porffor.fastAnd(Porffor.type(array) >= Porffor.TYPES.uint8clampedarray, Porffor.type(array) <= Porffor.TYPES.float64array)
|
170
170
|
)) {
|
@@ -49,9 +49,8 @@ export const __ecma262_ToNumber = (argument: unknown): number => {
|
|
49
49
|
if (argument === true) return 1;
|
50
50
|
|
51
51
|
// 6. If argument is a String, return StringToNumber(argument).
|
52
|
-
if (Porffor.
|
53
|
-
|
54
|
-
Porffor.type(argument) == Porffor.TYPES.bytestring)) return __ecma262_StringToNumber(argument);
|
52
|
+
if ((Porffor.type(argument) | 0b10000000) == Porffor.TYPES.bytestring)
|
53
|
+
return __ecma262_StringToNumber(argument);
|
55
54
|
|
56
55
|
// 7. Assert: argument is an Object.
|
57
56
|
// 8. Let primValue be ? ToPrimitive(argument, number).
|
@@ -121,9 +120,8 @@ export const __ecma262_ToIndex = (value: unknown): number => {
|
|
121
120
|
// https://tc39.es/ecma262/#sec-tostring
|
122
121
|
export const __ecma262_ToString = (argument: unknown): any => {
|
123
122
|
// 1. If argument is a String, return argument.
|
124
|
-
if (Porffor.
|
125
|
-
|
126
|
-
Porffor.type(argument) == Porffor.TYPES.bytestring)) return argument;
|
123
|
+
if ((Porffor.type(argument) | 0b10000000) == Porffor.TYPES.bytestring)
|
124
|
+
return argument;
|
127
125
|
|
128
126
|
// 2. If argument is a Symbol, throw a TypeError exception.
|
129
127
|
if (Porffor.type(argument) == Porffor.TYPES.symbol) throw new TypeError('Cannot convert a Symbol value to a string');
|