porffor 0.0.0-ebc0491 → 0.0.0-ee33579
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 +22 -9
- package/c +0 -0
- package/c.exe +0 -0
- package/compiler/2c.js +255 -0
- package/compiler/builtins.js +0 -1
- package/compiler/codeGen.js +67 -11
- package/compiler/decompile.js +1 -1
- package/compiler/index.js +44 -2
- package/compiler/opt.js +1 -1
- package/compiler/parse.js +2 -1
- package/compiler/prototype.js +2 -1
- package/compiler/sections.js +1 -0
- package/compiler/wrap.js +5 -3
- package/cool.exe +0 -0
- package/g +0 -0
- package/g.exe +0 -0
- package/hi.c +37 -0
- package/out +0 -0
- package/package.json +1 -1
- package/rhemyn/README.md +37 -0
- package/rhemyn/compile.js +214 -0
- package/rhemyn/parse.js +321 -0
- package/rhemyn/test/parse.js +59 -0
- package/runner/index.js +52 -52
- package/tmp.c +37 -0
- package/compiler/rhemyn/compile.js +0 -173
- package/compiler/rhemyn/parse.js +0 -125
- package/compiler/rhemyn/test/parse.js +0 -20
package/runner/index.js
CHANGED
@@ -1,53 +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
|
-
}
|
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}`);
|
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
|
+
}
|
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
53
|
}
|
package/tmp.c
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
|
3
|
+
double inline f64_f(double x, double y) {
|
4
|
+
return x - (int)(x / y) * y;
|
5
|
+
}
|
6
|
+
|
7
|
+
double isPrime(double number) {
|
8
|
+
double i;
|
9
|
+
|
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
|
+
}
|
18
|
+
i = i + 1e+0;
|
19
|
+
}
|
20
|
+
return 1e+0;
|
21
|
+
}
|
22
|
+
|
23
|
+
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);
|
36
|
+
}
|
37
|
+
|
@@ -1,173 +0,0 @@
|
|
1
|
-
import { Blocktype, Opcodes, Valtype, PageSize, ValtypeSize } from '../wasmSpec.js';
|
2
|
-
import { signedLEB128, unsignedLEB128 } from '../encoding.js';
|
3
|
-
import parse from './parse.js';
|
4
|
-
|
5
|
-
// local indexes
|
6
|
-
const BasePointer = 0; // base string pointer
|
7
|
-
const IterPointer = 1; // this iteration base pointer
|
8
|
-
const Counter = 2; // what char we are running on
|
9
|
-
const Pointer = 3; // next char BYTE pointer
|
10
|
-
const Length = 4;
|
11
|
-
const Tmp = 5;
|
12
|
-
|
13
|
-
const generate = (node, get = true) => {
|
14
|
-
let out = [];
|
15
|
-
switch (node.type) {
|
16
|
-
case 'Expression':
|
17
|
-
out = [
|
18
|
-
// set length local
|
19
|
-
[ Opcodes.local_get, BasePointer ],
|
20
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(0) ],
|
21
|
-
[ Opcodes.local_set, Length ],
|
22
|
-
|
23
|
-
// set iter pointer local as base + sizeof i32 initially
|
24
|
-
[ Opcodes.local_get, BasePointer ],
|
25
|
-
...number(ValtypeSize.i32, Valtype.i32),
|
26
|
-
[ Opcodes.i32_add ],
|
27
|
-
[ Opcodes.local_set, IterPointer ],
|
28
|
-
|
29
|
-
[ Opcodes.loop, Blocktype.void ],
|
30
|
-
|
31
|
-
// reset pointer as iter pointer
|
32
|
-
[ Opcodes.local_get, IterPointer ],
|
33
|
-
[ Opcodes.local_set, Pointer ],
|
34
|
-
|
35
|
-
[ Opcodes.block, Blocktype.void ],
|
36
|
-
// generate checks
|
37
|
-
...generate(x),
|
38
|
-
|
39
|
-
// reached end without branching out, successful match
|
40
|
-
...number(1, Valtype.i32),
|
41
|
-
[ Opcodes.return ],
|
42
|
-
|
43
|
-
[ Opcodes.end ],
|
44
|
-
|
45
|
-
// increment iter pointer by sizeof i16
|
46
|
-
[ Opcodes.local_get, IterPointer ],
|
47
|
-
...number(ValtypeSize.i16, Valtype.i32),
|
48
|
-
[ Opcodes.i32_add ],
|
49
|
-
[ Opcodes.local_set, IterPointer ],
|
50
|
-
|
51
|
-
// increment counter by 1, check if eq length, if not loop
|
52
|
-
[ Opcodes.local_get, Counter ],
|
53
|
-
...number(1, Valtype.i32),
|
54
|
-
[ Opcodes.i32_add ],
|
55
|
-
[ Opcodes.local_tee, Counter ],
|
56
|
-
|
57
|
-
[ Opcodes.local_get, Length ],
|
58
|
-
[ Opcodes.i32_ne ],
|
59
|
-
[ Opcodes.br_if, 1 ],
|
60
|
-
|
61
|
-
[ Opcodes.end ],
|
62
|
-
|
63
|
-
// no match, return 0
|
64
|
-
...number(0, Valtype.i32)
|
65
|
-
];
|
66
|
-
|
67
|
-
break;
|
68
|
-
|
69
|
-
case 'Character':
|
70
|
-
out = generateChar(node, get);
|
71
|
-
break;
|
72
|
-
|
73
|
-
case 'Set':
|
74
|
-
out = generateSet(node, get);
|
75
|
-
break;
|
76
|
-
|
77
|
-
case 'Group':
|
78
|
-
out = generateGroup(node, get);
|
79
|
-
break;
|
80
|
-
|
81
|
-
case 'Range':
|
82
|
-
out = generateRange(node, get);
|
83
|
-
break;
|
84
|
-
}
|
85
|
-
|
86
|
-
return out;
|
87
|
-
};
|
88
|
-
|
89
|
-
const getNextChar = () => [
|
90
|
-
// get char from pointer
|
91
|
-
[ Opcodes.local_get, Pointer ],
|
92
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(0) ],
|
93
|
-
|
94
|
-
// pointer += sizeof i16
|
95
|
-
[ Opcodes.local_get, Pointer ],
|
96
|
-
...number(ValtypeSize.i16, Valtype.i32),
|
97
|
-
[ Opcodes.i32_add ],
|
98
|
-
[ Opcodes.local_set, Pointer ]
|
99
|
-
];
|
100
|
-
|
101
|
-
const checkFailure = () => [
|
102
|
-
// surely we do not need to do this for every single mismatch, right?
|
103
|
-
/* [ Opcodes.if, Blocktype.void ],
|
104
|
-
...number(0, Valtype.i32),
|
105
|
-
[ Opcodes.return ],
|
106
|
-
[ Opcodes.end ], */
|
107
|
-
|
108
|
-
[ Opcodes.br, 1 ]
|
109
|
-
];
|
110
|
-
|
111
|
-
const generateChar = (node, get) => {
|
112
|
-
return [
|
113
|
-
...(get ? getNextChar() : []),
|
114
|
-
...number(String.fromCharCode(node.char), Valtype.i32),
|
115
|
-
[ Opcodes.i32_ne ],
|
116
|
-
...checkFailure()
|
117
|
-
];
|
118
|
-
};
|
119
|
-
|
120
|
-
const generateSet = (node, get) => {
|
121
|
-
const out = [
|
122
|
-
...(get ? getNextChar() : []),
|
123
|
-
[ Opcodes.local_set, Tmp ],
|
124
|
-
];
|
125
|
-
|
126
|
-
for (const x of node.body) {
|
127
|
-
out = [
|
128
|
-
...out,
|
129
|
-
[ Opcodes.local_get, Tmp ],
|
130
|
-
...generate(x, false)
|
131
|
-
];
|
132
|
-
}
|
133
|
-
|
134
|
-
out = out.concat(new Array(node.body.length - 1).fill([ Opcodes.i32_or ]));
|
135
|
-
|
136
|
-
return [
|
137
|
-
...out,
|
138
|
-
...checkFailure()
|
139
|
-
];
|
140
|
-
};
|
141
|
-
|
142
|
-
const generateGroup = (node, get) => {
|
143
|
-
|
144
|
-
};
|
145
|
-
|
146
|
-
const generateRange = (node, get) => {
|
147
|
-
|
148
|
-
};
|
149
|
-
|
150
|
-
|
151
|
-
export const match = regex => {
|
152
|
-
|
153
|
-
};
|
154
|
-
|
155
|
-
export const test = regex => {
|
156
|
-
const code = generate(parse(regex));
|
157
|
-
};
|
158
|
-
|
159
|
-
const wasmify = code => {
|
160
|
-
const funcs = [{
|
161
|
-
name: 'exp',
|
162
|
-
export: true,
|
163
|
-
params: [ Valtype.i32 ],
|
164
|
-
returns: [ Valtype.i32 ],
|
165
|
-
locals: {
|
166
|
-
iterPointer: { idx: 1, type: Valtype.i32 },
|
167
|
-
counter: { idx: 2, type: Valtype.i32 },
|
168
|
-
pointer: { idx: 3, type: Valtype.i32 },
|
169
|
-
length: { idx: 4, type: Valtype.i32 },
|
170
|
-
tmp: { idx: 5, type: Valtype.i32 },
|
171
|
-
}
|
172
|
-
}]
|
173
|
-
};
|
package/compiler/rhemyn/parse.js
DELETED
@@ -1,125 +0,0 @@
|
|
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
|
-
export default str => {
|
14
|
-
const out = {
|
15
|
-
type: 'Expression',
|
16
|
-
body: []
|
17
|
-
};
|
18
|
-
let node = out, parents = [];
|
19
|
-
|
20
|
-
let state = State.none, escape = false;
|
21
|
-
for (let i = 0; i < str.length; i++) {
|
22
|
-
const c = str[i];
|
23
|
-
|
24
|
-
const addChar = () => {
|
25
|
-
node.body.push({
|
26
|
-
type: 'Character',
|
27
|
-
char: c
|
28
|
-
});
|
29
|
-
};
|
30
|
-
|
31
|
-
const seek = () => {
|
32
|
-
const cNext = str[++i];
|
33
|
-
|
34
|
-
if (cNext === '\\') return str[++i];
|
35
|
-
return cNext;
|
36
|
-
};
|
37
|
-
|
38
|
-
if (escape) {
|
39
|
-
addChar();
|
40
|
-
|
41
|
-
escape = false;
|
42
|
-
continue;
|
43
|
-
}
|
44
|
-
|
45
|
-
if (c === '\\') {
|
46
|
-
escape = true;
|
47
|
-
continue;
|
48
|
-
}
|
49
|
-
|
50
|
-
switch (state) {
|
51
|
-
case State.none:
|
52
|
-
if (c === '[') {
|
53
|
-
parents.push(node);
|
54
|
-
node = {
|
55
|
-
type: 'Set',
|
56
|
-
body: []
|
57
|
-
};
|
58
|
-
|
59
|
-
parents.at(-1).body.push(node);
|
60
|
-
|
61
|
-
state = State.insideSet;
|
62
|
-
continue;
|
63
|
-
}
|
64
|
-
|
65
|
-
if (c === '(') {
|
66
|
-
parents.push(node);
|
67
|
-
node = {
|
68
|
-
type: 'Group',
|
69
|
-
body: []
|
70
|
-
};
|
71
|
-
|
72
|
-
parents.at(-1).body.push(node);
|
73
|
-
continue;
|
74
|
-
}
|
75
|
-
|
76
|
-
if (c === ')') {
|
77
|
-
if (node.type !== 'Group') throw new SyntaxError('Unmatched closing parenthesis');
|
78
|
-
|
79
|
-
node = parents.pop();
|
80
|
-
continue;
|
81
|
-
}
|
82
|
-
|
83
|
-
if (QuantifierKeys.includes(c)) {
|
84
|
-
const amount = Quantifiers[c];
|
85
|
-
node.body.at(-1).quantifier = amount;
|
86
|
-
continue;
|
87
|
-
}
|
88
|
-
|
89
|
-
addChar();
|
90
|
-
break;
|
91
|
-
|
92
|
-
case State.insideSet:
|
93
|
-
if (c === ']') {
|
94
|
-
state = State.none;
|
95
|
-
node = parents.pop();
|
96
|
-
|
97
|
-
continue;
|
98
|
-
}
|
99
|
-
|
100
|
-
// range
|
101
|
-
if (c === '-') {
|
102
|
-
const from = node.body.pop().char;
|
103
|
-
const to = seek();
|
104
|
-
|
105
|
-
node.body.push({
|
106
|
-
type: 'Range',
|
107
|
-
from,
|
108
|
-
to
|
109
|
-
});
|
110
|
-
continue;
|
111
|
-
}
|
112
|
-
|
113
|
-
addChar();
|
114
|
-
break;
|
115
|
-
}
|
116
|
-
}
|
117
|
-
|
118
|
-
// still in a group by the end
|
119
|
-
if (node.type !== 'Expression') throw new SyntaxError('Unmatched opening parenthesis');
|
120
|
-
|
121
|
-
// still in a set by the end
|
122
|
-
if (state === State.insideSet) throw new SyntaxError('Unmatched opening square bracket');
|
123
|
-
|
124
|
-
return out;
|
125
|
-
};
|
@@ -1,20 +0,0 @@
|
|
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
|
-
}
|
17
|
-
|
18
|
-
for (const str in tests) {
|
19
|
-
console.log(str, util.inspect(parse(str), false, null, true));
|
20
|
-
}
|