nirguna 0.1.0
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/ChangeLog +846 -0
- package/README.md +140 -0
- package/bin/ishvara.js +174 -0
- package/lib/ishvara.js +29 -0
- package/package.json +111 -0
- package/packages/compiler-fasm/compiler.js +75 -0
- package/packages/compiler-wasm/compiler.js +62 -0
- package/packages/operator-wasm/index.js +55 -0
- package/packages/optimizer-fasm/optimizer.js +15 -0
- package/packages/optimizer-wasm/optimizer.js +13 -0
- package/packages/printer-fasm/printer/printer.js +30 -0
- package/packages/printer-fasm/printer/visitors/assignment-expression.js +47 -0
- package/packages/printer-fasm/printer/visitors/block-statement.js +7 -0
- package/packages/printer-fasm/printer/visitors/call-expression.js +56 -0
- package/packages/printer-fasm/printer/visitors/expression-statement/expression-statement.js +34 -0
- package/packages/printer-fasm/printer/visitors/expression-statement/print-in-out.js +37 -0
- package/packages/printer-fasm/printer/visitors/expression-statement/print-jmp-far.js +30 -0
- package/packages/printer-fasm/printer/visitors/labeled-statement.js +14 -0
- package/packages/printer-fasm/printer/visitors/member-expression.js +5 -0
- package/packages/printer-fasm/printer/visitors/sequence-expression.js +17 -0
- package/packages/printer-fasm/printer/visitors/string-literal.js +55 -0
- package/packages/printer-fasm/printer/visitors/tagged-template-expression.js +4 -0
- package/packages/printer-fasm/printer.js +7 -0
- package/packages/printer-wasm/printer/maybe-type-annotation.js +15 -0
- package/packages/printer-wasm/printer/params.js +72 -0
- package/packages/printer-wasm/printer/printer.js +32 -0
- package/packages/printer-wasm/printer/visitors/block-statement.js +33 -0
- package/packages/printer-wasm/printer/visitors/call-expression/call-expression.js +53 -0
- package/packages/printer-wasm/printer/visitors/call-expression/is-wasm-type.js +6 -0
- package/packages/printer-wasm/printer/visitors/export-named-declaration.js +3 -0
- package/packages/printer-wasm/printer/visitors/expression-statement/expression-statement.js +38 -0
- package/packages/printer-wasm/printer/visitors/expression-statement/print-wasm-import.js +81 -0
- package/packages/printer-wasm/printer/visitors/expression-statement/print-wasm-memory.js +31 -0
- package/packages/printer-wasm/printer/visitors/function-declaration.js +91 -0
- package/packages/printer-wasm/printer/visitors/identifier.js +11 -0
- package/packages/printer-wasm/printer/visitors/if-statement.js +128 -0
- package/packages/printer-wasm/printer/visitors/program.js +26 -0
- package/packages/printer-wasm/printer/visitors/return.js +16 -0
- package/packages/printer-wasm/printer.js +10 -0
- package/packages/test-wasm/test.js +45 -0
- package/packages/transformer-fasm/transformer.js +70 -0
- package/packages/transformer-wasm/transformer.js +20 -0
- package/packages/translator-fasm/dump.js +68 -0
- package/packages/translator-fasm/translator.js +15 -0
- package/packages/translator-wasm/translator.js +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Ishvara
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
Compile JavaScript to WASM and Fasm.
|
|
6
|
+
|
|
7
|
+
<img width="300" alt="image" src="https://github.com/user-attachments/assets/e3808fa0-90cc-4e9f-acb3-68babafa0350" />
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
npm i ishvara -g
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage Example
|
|
16
|
+
|
|
17
|
+
Let's suppose you have JavaScript:
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
function add() {
|
|
21
|
+
const eax = 1;
|
|
22
|
+
const ebx = 2;
|
|
23
|
+
|
|
24
|
+
return eax + ebx;
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
You can compile it to fasm and wasm.
|
|
29
|
+
|
|
30
|
+
### Fasm
|
|
31
|
+
|
|
32
|
+
Let's compile javascript with:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
ishvara --target fasm example/fn.ts -o code
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
To intermediate representation:
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
__ishvara_add: {
|
|
42
|
+
mov(eax, 0x1);
|
|
43
|
+
mov(ebx, 0x2);
|
|
44
|
+
add(eax, ebx);
|
|
45
|
+
ret;
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Also we can compile it with:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
ishvara -t fasm example/fn.ts -o code
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
to assembly representation with:
|
|
56
|
+
|
|
57
|
+
```asm
|
|
58
|
+
__ishvara_add:
|
|
59
|
+
mov eax, 0x1
|
|
60
|
+
mov ebx, 0x2
|
|
61
|
+
add eax, ebx
|
|
62
|
+
ret
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Also we can compile it to binary representation with `ishvara fasm example/fn.ts`:
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
$ hexdump example/fn.bin
|
|
69
|
+
|
|
70
|
+
0000000 b866 0001 0000 bb66 0002 0000 0166 c3d8
|
|
71
|
+
0000010
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### wasm
|
|
75
|
+
|
|
76
|
+
Let's suppose we have absolutely valid JavaScript file with types, which we can run with node v24.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import {create} from '#ishvara';
|
|
80
|
+
|
|
81
|
+
export const stack = [];
|
|
82
|
+
|
|
83
|
+
export const imports = [
|
|
84
|
+
['console', 'log', function log() {
|
|
85
|
+
return i32;
|
|
86
|
+
}],
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
const {
|
|
90
|
+
i32,
|
|
91
|
+
local,
|
|
92
|
+
call,
|
|
93
|
+
} = create({
|
|
94
|
+
stack,
|
|
95
|
+
imports,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
export function x(a: i32, b: i32): i32 {
|
|
99
|
+
i32.add(local.get(a), local.get(b));
|
|
100
|
+
call('log');
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Compiled with `ishvara 1.wast.ts` to `1.wast`:
|
|
105
|
+
|
|
106
|
+
```wast
|
|
107
|
+
(module
|
|
108
|
+
(import "console" "log" (func $log (param $message i32) (result i32)))
|
|
109
|
+
(func $x (export "x") (param $a i32) (param $b i32) (result i32)
|
|
110
|
+
(i32.add (local.get $a) (local.get $b))
|
|
111
|
+
(call $log)
|
|
112
|
+
)
|
|
113
|
+
)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
With:
|
|
117
|
+
|
|
118
|
+
```js
|
|
119
|
+
import {compile} from 'ishvara';
|
|
120
|
+
|
|
121
|
+
const wast = compile(wastts);
|
|
122
|
+
const binary = await translate(wast);
|
|
123
|
+
|
|
124
|
+
const {x} = run(binary, {
|
|
125
|
+
console: {
|
|
126
|
+
log: (a) => {
|
|
127
|
+
console.log(a);
|
|
128
|
+
return a;
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
x(1, 2);
|
|
134
|
+
// outputs
|
|
135
|
+
3;
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
MIT
|
package/bin/ishvara.js
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import {writeFileSync} from 'node:fs';
|
|
4
|
+
import process, {cwd, exit} from 'node:process';
|
|
5
|
+
import {stat} from 'node:fs/promises';
|
|
6
|
+
import path, {join} from 'node:path';
|
|
7
|
+
import {codeFrameColumns} from '@putout/babel';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import {bundle} from '@nirguna/bundler';
|
|
10
|
+
import {prepareError} from '@nirguna/bundler/prepare-error';
|
|
11
|
+
import {help} from '@nirguna/cli-help';
|
|
12
|
+
import {
|
|
13
|
+
parseArgs,
|
|
14
|
+
validateArgs,
|
|
15
|
+
parseConfig,
|
|
16
|
+
} from '@nirguna/cli-args';
|
|
17
|
+
import {compile} from '#ishvara';
|
|
18
|
+
|
|
19
|
+
debugger;
|
|
20
|
+
const onStageChange = (args) => (stage, {last, places}) => {
|
|
21
|
+
const line = stage[0].toUpperCase() + stage.slice(1);
|
|
22
|
+
|
|
23
|
+
log(args, '✅ \n');
|
|
24
|
+
log(args, line, {
|
|
25
|
+
withDivider: true,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
if (!last)
|
|
29
|
+
return;
|
|
30
|
+
|
|
31
|
+
if (!places.length) {
|
|
32
|
+
log(args, '✅ \n\n');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
log(args, '❌ \n\n');
|
|
37
|
+
|
|
38
|
+
const fullName = join(cwd(), name);
|
|
39
|
+
|
|
40
|
+
for (const {message, position} of places) {
|
|
41
|
+
const {line, column} = position;
|
|
42
|
+
|
|
43
|
+
if (stage === 'translate') {
|
|
44
|
+
console.error(`${chalk.blue(`${line}:${column}`)}: ${chalk.red(message)}`);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.error(`file://${chalk.blue(`${fullName}:${line}:${column}`)}: ${chalk.red(message)}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
exit(1);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const {O = 1, RAW} = process.env;
|
|
55
|
+
const args = parseArgs(process.argv.slice(2));
|
|
56
|
+
|
|
57
|
+
if (args.help) {
|
|
58
|
+
console.log(help());
|
|
59
|
+
process.exit(0);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
await validateArgs(args, {
|
|
63
|
+
log: (a) => console.error(chalk.red(a)),
|
|
64
|
+
exit: process.exit,
|
|
65
|
+
stat,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const [name] = args._;
|
|
69
|
+
|
|
70
|
+
const [errorOptions, config] = parseConfig(name);
|
|
71
|
+
|
|
72
|
+
if (errorOptions) {
|
|
73
|
+
console.error(errorOptions);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
log(args, `🔎 ${name}\n`);
|
|
78
|
+
log(args, `🚀 ${args.target}\n\n`);
|
|
79
|
+
|
|
80
|
+
log(args, 'Bundle', {
|
|
81
|
+
withDivider: true,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const [error, source] = await bundle(name, config);
|
|
85
|
+
|
|
86
|
+
if (error) {
|
|
87
|
+
console.log(error);
|
|
88
|
+
|
|
89
|
+
if (!error.id) {
|
|
90
|
+
console.error(error.message);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (error.code === 'UNRESOLVED_IMPORT') {
|
|
95
|
+
console.error(`file://${chalk.blue(error.id)}: ${chalk.red(error.message)}`);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const {message} = await prepareError(error);
|
|
100
|
+
|
|
101
|
+
const {line} = error.location?.start || error.loc;
|
|
102
|
+
const name = error.id || error.fileName;
|
|
103
|
+
|
|
104
|
+
console.error(`file://${chalk.blue(name)}:${line}: ${chalk.red(message)}`);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (/bundled?/.test(args.output)) {
|
|
109
|
+
log(args, `✅ \n\n`);
|
|
110
|
+
|
|
111
|
+
if (RAW)
|
|
112
|
+
console.log(source);
|
|
113
|
+
else
|
|
114
|
+
console.log(codeFrameColumns(source, {}, {
|
|
115
|
+
highlightCode: true,
|
|
116
|
+
forceColor: true,
|
|
117
|
+
}));
|
|
118
|
+
|
|
119
|
+
process.exit();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const [binary] = await compile(source, {
|
|
123
|
+
name,
|
|
124
|
+
type: args.output,
|
|
125
|
+
target: args.target,
|
|
126
|
+
optimization: Boolean(Number(O)),
|
|
127
|
+
config,
|
|
128
|
+
onStageChange: onStageChange(args),
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
if (args.output) {
|
|
132
|
+
if (args.output === 'binary' || RAW)
|
|
133
|
+
process.stdout.write(binary);
|
|
134
|
+
else
|
|
135
|
+
console.log(codeFrameColumns(String(binary), {}, {
|
|
136
|
+
highlightCode: true,
|
|
137
|
+
forceColor: true,
|
|
138
|
+
}));
|
|
139
|
+
|
|
140
|
+
process.exit();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!args.output)
|
|
144
|
+
if (args.target === 'fasm')
|
|
145
|
+
write(name, 'bin', binary);
|
|
146
|
+
else if (args.target === 'wasm')
|
|
147
|
+
write(name, 'wasm', binary);
|
|
148
|
+
|
|
149
|
+
if (args.target === 'wast')
|
|
150
|
+
write(name, 'wast', binary);
|
|
151
|
+
else if (args.target === 'asm')
|
|
152
|
+
write(name, 'asm', binary);
|
|
153
|
+
|
|
154
|
+
process.exit(0);
|
|
155
|
+
|
|
156
|
+
function write(input, extension, binary) {
|
|
157
|
+
const {dir, name} = path.parse(input);
|
|
158
|
+
const full = `${join(dir, name)}.${extension}`;
|
|
159
|
+
|
|
160
|
+
writeFileSync(full, binary);
|
|
161
|
+
log(args, `💾 ${full}\n\n`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function log({quiet}, message, {withDivider} = {}) {
|
|
165
|
+
if (quiet)
|
|
166
|
+
return;
|
|
167
|
+
|
|
168
|
+
process.stdout.write(message);
|
|
169
|
+
|
|
170
|
+
if (withDivider) {
|
|
171
|
+
const divider = Array(35 - message.length).join('.');
|
|
172
|
+
process.stdout.write(divider);
|
|
173
|
+
}
|
|
174
|
+
}
|
package/lib/ishvara.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as wasm from '#compiler-wasm';
|
|
2
|
+
import * as fasm from '#compiler-fasm';
|
|
3
|
+
|
|
4
|
+
export const compile = async (source, options) => {
|
|
5
|
+
const {
|
|
6
|
+
target,
|
|
7
|
+
type,
|
|
8
|
+
name,
|
|
9
|
+
optimization,
|
|
10
|
+
config,
|
|
11
|
+
onStageChange,
|
|
12
|
+
} = options;
|
|
13
|
+
|
|
14
|
+
if (target === 'wasm')
|
|
15
|
+
return await wasm.compile(source, {
|
|
16
|
+
type,
|
|
17
|
+
name,
|
|
18
|
+
optimization,
|
|
19
|
+
onStageChange,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return await fasm.compile(source, {
|
|
23
|
+
type,
|
|
24
|
+
target,
|
|
25
|
+
optimization,
|
|
26
|
+
config,
|
|
27
|
+
onStageChange,
|
|
28
|
+
});
|
|
29
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nirguna",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
|
|
6
|
+
"description": "Compile JavaScript to WASM and FASM",
|
|
7
|
+
"homepage": "https://github.com/putoutjs/nirguna",
|
|
8
|
+
"main": "lib/nirguna.js",
|
|
9
|
+
"bin": {
|
|
10
|
+
"nirguna": "bin/nirguna.js"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/putoutjs/nirguna.git"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "madrun test",
|
|
18
|
+
"watch:test": "madrun watch:test",
|
|
19
|
+
"lint": "madrun lint",
|
|
20
|
+
"fresh:lint": "madrun fresh:lint",
|
|
21
|
+
"lint:fresh": "madrun lint:fresh",
|
|
22
|
+
"fix:lint": "madrun fix:lint",
|
|
23
|
+
"coverage": "madrun coverage",
|
|
24
|
+
"report": "madrun report",
|
|
25
|
+
"build:boot": "madrun build:boot",
|
|
26
|
+
"build:boot:fasm": "madrun build:boot:fasm",
|
|
27
|
+
"build:boot:asm": "madrun build:boot:asm",
|
|
28
|
+
"build:nemesis": "madrun build:nemesis",
|
|
29
|
+
"build:nemesis:asm": "madrun build:nemesis:asm",
|
|
30
|
+
"build:nemesis:fasm": "madrun build:nemesis:fasm"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@nirguna/bundler": "*",
|
|
34
|
+
"@nirguna/cli-args": "*",
|
|
35
|
+
"@nirguna/cli-help": "*",
|
|
36
|
+
"@nirguna/operator-fasm": "*",
|
|
37
|
+
"@nirguna/plugin-bandler-fasm": "*",
|
|
38
|
+
"@nirguna/plugin-fasm": "*",
|
|
39
|
+
"@nirguna/plugin-nirguna": "*",
|
|
40
|
+
"@nirguna/plugin-nemesis": "*",
|
|
41
|
+
"@nirguna/plugin-optimizer-fasm": "*",
|
|
42
|
+
"@nirguna/plugin-optimizer-wasm": "*",
|
|
43
|
+
"@nirguna/plugin-wasm": "*",
|
|
44
|
+
"@nirguna/runner-fasm": "*",
|
|
45
|
+
"@nirguna/runner-wasm": "*",
|
|
46
|
+
"@putout/babel": "^5.2.12",
|
|
47
|
+
"@putout/plugin-assignment": "^2.0.0",
|
|
48
|
+
"@putout/plugin-esm": "^9.2.0",
|
|
49
|
+
"@putout/plugin-remove-nested-blocks": "^9.0.0",
|
|
50
|
+
"@putout/plugin-remove-useless-operand": "^3.0.0",
|
|
51
|
+
"@putout/printer": "^17.1.0",
|
|
52
|
+
"@typescript-eslint/typescript-estree": "^8.32.1",
|
|
53
|
+
"chalk": "^5.4.1",
|
|
54
|
+
"fasm.js": "^1.0.7",
|
|
55
|
+
"hexdump-nodejs": "^0.1.0",
|
|
56
|
+
"iced-x86": "^1.21.0",
|
|
57
|
+
"just-snake-case": "^3.2.0",
|
|
58
|
+
"putout": "^41.20.0",
|
|
59
|
+
"try-catch": "^4.0.9",
|
|
60
|
+
"try-to-catch": "^4.0.5",
|
|
61
|
+
"typescript": "^5.8.3",
|
|
62
|
+
"wabt": "^1.0.37",
|
|
63
|
+
"yargs-parser": "^22.0.0"
|
|
64
|
+
},
|
|
65
|
+
"keywords": [
|
|
66
|
+
"putout"
|
|
67
|
+
],
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@putout/plugin-printer": "^7.1.1",
|
|
70
|
+
"@putout/test": "^15.1.1",
|
|
71
|
+
"c8": "^10.0.0",
|
|
72
|
+
"eslint": "^10.0.0",
|
|
73
|
+
"eslint-plugin-n": "^17.0.0",
|
|
74
|
+
"eslint-plugin-putout": "^30.0.2",
|
|
75
|
+
"just-kebab-case": "^4.2.0",
|
|
76
|
+
"madrun": "^12.1.3",
|
|
77
|
+
"montag": "^1.2.1",
|
|
78
|
+
"nodemon": "^3.0.1",
|
|
79
|
+
"redlint": "^5.7.0",
|
|
80
|
+
"supertape": "^12.4.0"
|
|
81
|
+
},
|
|
82
|
+
"imports": {
|
|
83
|
+
"#cli-args": "./packages/cli-args/index.js",
|
|
84
|
+
"#cli-help": "./packages/cli-help/help.js",
|
|
85
|
+
"#plugin-wasm": "./packages/plugin-wasm/lib/index.js",
|
|
86
|
+
"#plugin-fasm": "./packages/plugin-fasm/lib/index.js",
|
|
87
|
+
"#plugin-nirguna": "./packages/plugin-nirguna/lib/index.js",
|
|
88
|
+
"#plugin-bundler-fasm": "./packages/plugin-bundler-fasm/lib/index.js",
|
|
89
|
+
"#compiler-wasm": "./packages/compiler-wasm/compiler.js",
|
|
90
|
+
"#compiler-fasm": "./packages/compiler-fasm/compiler.js",
|
|
91
|
+
"#optimizer-fasm": "./packages/optimizer-fasm/optimizer.js",
|
|
92
|
+
"#optimizer-wasm": "./packages/optimizer-wasm/optimizer.js",
|
|
93
|
+
"#printer-wasm": "./packages/printer-wasm/printer.js",
|
|
94
|
+
"#printer-fasm": "./packages/printer-fasm/printer.js",
|
|
95
|
+
"#translator-wasm": "./packages/translator-wasm/translator.js",
|
|
96
|
+
"#test-wasm": "./packages/test-wasm/test.js",
|
|
97
|
+
"#translator-fasm": "./packages/translator-fasm/translator.js",
|
|
98
|
+
"#transformer-wasm": "./packages/transformer-wasm/transformer.js",
|
|
99
|
+
"#transformer-fasm": "./packages/transformer-fasm/transformer.js",
|
|
100
|
+
"#operator-wasm": "./packages/operator-wasm/index.js",
|
|
101
|
+
"#operator-fasm": "./externals/operator-fasm/index.ts",
|
|
102
|
+
"#nirguna": "./lib/nirguna.js"
|
|
103
|
+
},
|
|
104
|
+
"license": "MIT",
|
|
105
|
+
"engines": {
|
|
106
|
+
"node": ">=22"
|
|
107
|
+
},
|
|
108
|
+
"publishConfig": {
|
|
109
|
+
"access": "public"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import {transform} from '#transformer-fasm';
|
|
2
|
+
import {print} from '#printer-fasm';
|
|
3
|
+
import {translate} from '#translator-fasm';
|
|
4
|
+
import {optimize} from '#optimizer-fasm';
|
|
5
|
+
|
|
6
|
+
const noop = () => {};
|
|
7
|
+
|
|
8
|
+
export const compile = async (source, options = {}) => {
|
|
9
|
+
const {
|
|
10
|
+
name,
|
|
11
|
+
type = 'binary',
|
|
12
|
+
optimization = true,
|
|
13
|
+
target = 'fasm',
|
|
14
|
+
config,
|
|
15
|
+
onStageChange = noop,
|
|
16
|
+
} = options;
|
|
17
|
+
|
|
18
|
+
const emitStateChange = (a) => onStageChange(a, {
|
|
19
|
+
last: false,
|
|
20
|
+
places: [],
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const emitLastStateChange = (a, places = []) => onStageChange(a, {
|
|
24
|
+
last: true,
|
|
25
|
+
places,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const [code, compilePlaces] = transform(source, config);
|
|
29
|
+
|
|
30
|
+
if (compilePlaces.length) {
|
|
31
|
+
emitLastStateChange('transform', compilePlaces);
|
|
32
|
+
|
|
33
|
+
return [code, compilePlaces];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (type === 'code') {
|
|
37
|
+
emitLastStateChange('transform');
|
|
38
|
+
return [code, compilePlaces];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
emitStateChange('transform');
|
|
42
|
+
|
|
43
|
+
const [optimized, optimizedPlaces] = optimization ? optimize(code) : [
|
|
44
|
+
code,
|
|
45
|
+
[],
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
if (type === 'optimized') {
|
|
49
|
+
emitLastStateChange('optimize');
|
|
50
|
+
return [optimized, optimizedPlaces];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
emitStateChange('optimize');
|
|
54
|
+
|
|
55
|
+
const assembly = print(optimized);
|
|
56
|
+
|
|
57
|
+
if (type === 'assembly' || target === 'asm') {
|
|
58
|
+
emitLastStateChange('Print');
|
|
59
|
+
return [
|
|
60
|
+
assembly,
|
|
61
|
+
[],
|
|
62
|
+
];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
emitStateChange('print');
|
|
66
|
+
|
|
67
|
+
const [binary, places] = await translate(assembly, {
|
|
68
|
+
name,
|
|
69
|
+
type,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
emitLastStateChange('translate', places);
|
|
73
|
+
|
|
74
|
+
return [binary, places];
|
|
75
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {translate} from '#translator-wasm';
|
|
2
|
+
import {transform} from '#transformer-wasm';
|
|
3
|
+
import {print} from '#printer-wasm';
|
|
4
|
+
import {optimize} from '#optimizer-wasm';
|
|
5
|
+
|
|
6
|
+
const noop = () => {};
|
|
7
|
+
|
|
8
|
+
export const compile = async (source, options = {}) => {
|
|
9
|
+
const {
|
|
10
|
+
name,
|
|
11
|
+
type = 'binary',
|
|
12
|
+
onStageChange = noop,
|
|
13
|
+
} = options;
|
|
14
|
+
|
|
15
|
+
const emitStateChange = (a) => onStageChange(a, {
|
|
16
|
+
last: false,
|
|
17
|
+
places: [],
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const emitLastStateChange = (a, places = []) => onStageChange(a, {
|
|
21
|
+
last: true,
|
|
22
|
+
places,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const [code, compilePlaces] = transform(source);
|
|
26
|
+
|
|
27
|
+
if (compilePlaces.length) {
|
|
28
|
+
emitLastStateChange('Transform', compilePlaces);
|
|
29
|
+
return [code, compilePlaces];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (type === 'code') {
|
|
33
|
+
emitLastStateChange('Transform');
|
|
34
|
+
return [code, compilePlaces];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
emitStateChange('transform');
|
|
38
|
+
const [optimized, optimizedPlaces] = optimize(code);
|
|
39
|
+
|
|
40
|
+
if (/optimize/.test(type)) {
|
|
41
|
+
emitLastStateChange('optimize');
|
|
42
|
+
return [optimized, optimizedPlaces];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
emitStateChange('Optimize');
|
|
46
|
+
const assembly = print(optimized);
|
|
47
|
+
|
|
48
|
+
if (type === 'assembly')
|
|
49
|
+
return [
|
|
50
|
+
assembly,
|
|
51
|
+
[],
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
emitStateChange('print');
|
|
55
|
+
const [binary, places] = await translate(assembly, {
|
|
56
|
+
name,
|
|
57
|
+
type,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
emitLastStateChange('translate', places);
|
|
61
|
+
return [binary, places];
|
|
62
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const isFn = (a) => typeof a === 'function';
|
|
2
|
+
|
|
3
|
+
export const create = ({stack, imports = []}) => {
|
|
4
|
+
const push = stack.push.bind(stack);
|
|
5
|
+
const pop = stack.pop.bind(stack);
|
|
6
|
+
|
|
7
|
+
const i32 = createI32({
|
|
8
|
+
push,
|
|
9
|
+
pop,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const local = createLocal({
|
|
13
|
+
push,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const call = createCall(imports);
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
i32,
|
|
20
|
+
local,
|
|
21
|
+
call,
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const createCall = (imports) => (name, ...args) => {
|
|
26
|
+
if (isFn(name))
|
|
27
|
+
return name(...args);
|
|
28
|
+
|
|
29
|
+
for (const [, currentName, fn, override] of imports) {
|
|
30
|
+
if (name !== currentName)
|
|
31
|
+
continue;
|
|
32
|
+
|
|
33
|
+
const currentFn = override || fn;
|
|
34
|
+
|
|
35
|
+
return currentFn(...args);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
throw Error(`[call]: '${name}' not found`);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const createI32 = ({push, pop}) => ({
|
|
42
|
+
const: push,
|
|
43
|
+
add: createAdd({
|
|
44
|
+
push,
|
|
45
|
+
pop,
|
|
46
|
+
}),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const createLocal = ({push}) => ({
|
|
50
|
+
get: push,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const createAdd = ({push, pop}) => (a, b) => {
|
|
54
|
+
push(pop(a) + pop(b));
|
|
55
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import putout from 'putout';
|
|
2
|
+
import * as removeNestedBlocks from '@putout/plugin-remove-nested-blocks';
|
|
3
|
+
import * as fasm from '@nirguna/plugin-optimizer-fasm';
|
|
4
|
+
|
|
5
|
+
export const optimize = (source) => {
|
|
6
|
+
const {code, places} = putout(source, {
|
|
7
|
+
isTS: true,
|
|
8
|
+
plugins: [
|
|
9
|
+
['ishvara/optimizer-fasm', fasm],
|
|
10
|
+
['remove-nested-blocks', removeNestedBlocks],
|
|
11
|
+
],
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
return [code, places];
|
|
15
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import putout from 'putout';
|
|
2
|
+
import * as wasm from '@nirguna/plugin-optimizer-wasm';
|
|
3
|
+
|
|
4
|
+
export const optimize = (source) => {
|
|
5
|
+
const {code, places} = putout(source, {
|
|
6
|
+
isTS: true,
|
|
7
|
+
plugins: [
|
|
8
|
+
['ishvara/optimizer-wasm', wasm],
|
|
9
|
+
],
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
return [code, places];
|
|
13
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {print as putoutPrint} from '@putout/printer';
|
|
2
|
+
import {CallExpression} from './visitors/call-expression.js';
|
|
3
|
+
import {MemberExpression} from './visitors/member-expression.js';
|
|
4
|
+
import {BlockStatement} from './visitors/block-statement.js';
|
|
5
|
+
import {LabeledStatement} from './visitors/labeled-statement.js';
|
|
6
|
+
import {ExpressionStatement} from './visitors/expression-statement/expression-statement.js';
|
|
7
|
+
import {SequenceExpression} from './visitors/sequence-expression.js';
|
|
8
|
+
import {AssignmentExpression} from './visitors/assignment-expression.js';
|
|
9
|
+
import {TaggedTemplateExpression} from './visitors/tagged-template-expression.js';
|
|
10
|
+
import {StringLiteral} from './visitors/string-literal.js';
|
|
11
|
+
|
|
12
|
+
export const print = (ast) => {
|
|
13
|
+
return putoutPrint(ast, {
|
|
14
|
+
semantics: {
|
|
15
|
+
comments: false,
|
|
16
|
+
maxElementLengthInOneLine: 100,
|
|
17
|
+
},
|
|
18
|
+
visitors: {
|
|
19
|
+
AssignmentExpression,
|
|
20
|
+
CallExpression,
|
|
21
|
+
MemberExpression,
|
|
22
|
+
BlockStatement,
|
|
23
|
+
LabeledStatement,
|
|
24
|
+
ExpressionStatement,
|
|
25
|
+
SequenceExpression,
|
|
26
|
+
StringLiteral,
|
|
27
|
+
TaggedTemplateExpression,
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
};
|