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.
Files changed (45) hide show
  1. package/ChangeLog +846 -0
  2. package/README.md +140 -0
  3. package/bin/ishvara.js +174 -0
  4. package/lib/ishvara.js +29 -0
  5. package/package.json +111 -0
  6. package/packages/compiler-fasm/compiler.js +75 -0
  7. package/packages/compiler-wasm/compiler.js +62 -0
  8. package/packages/operator-wasm/index.js +55 -0
  9. package/packages/optimizer-fasm/optimizer.js +15 -0
  10. package/packages/optimizer-wasm/optimizer.js +13 -0
  11. package/packages/printer-fasm/printer/printer.js +30 -0
  12. package/packages/printer-fasm/printer/visitors/assignment-expression.js +47 -0
  13. package/packages/printer-fasm/printer/visitors/block-statement.js +7 -0
  14. package/packages/printer-fasm/printer/visitors/call-expression.js +56 -0
  15. package/packages/printer-fasm/printer/visitors/expression-statement/expression-statement.js +34 -0
  16. package/packages/printer-fasm/printer/visitors/expression-statement/print-in-out.js +37 -0
  17. package/packages/printer-fasm/printer/visitors/expression-statement/print-jmp-far.js +30 -0
  18. package/packages/printer-fasm/printer/visitors/labeled-statement.js +14 -0
  19. package/packages/printer-fasm/printer/visitors/member-expression.js +5 -0
  20. package/packages/printer-fasm/printer/visitors/sequence-expression.js +17 -0
  21. package/packages/printer-fasm/printer/visitors/string-literal.js +55 -0
  22. package/packages/printer-fasm/printer/visitors/tagged-template-expression.js +4 -0
  23. package/packages/printer-fasm/printer.js +7 -0
  24. package/packages/printer-wasm/printer/maybe-type-annotation.js +15 -0
  25. package/packages/printer-wasm/printer/params.js +72 -0
  26. package/packages/printer-wasm/printer/printer.js +32 -0
  27. package/packages/printer-wasm/printer/visitors/block-statement.js +33 -0
  28. package/packages/printer-wasm/printer/visitors/call-expression/call-expression.js +53 -0
  29. package/packages/printer-wasm/printer/visitors/call-expression/is-wasm-type.js +6 -0
  30. package/packages/printer-wasm/printer/visitors/export-named-declaration.js +3 -0
  31. package/packages/printer-wasm/printer/visitors/expression-statement/expression-statement.js +38 -0
  32. package/packages/printer-wasm/printer/visitors/expression-statement/print-wasm-import.js +81 -0
  33. package/packages/printer-wasm/printer/visitors/expression-statement/print-wasm-memory.js +31 -0
  34. package/packages/printer-wasm/printer/visitors/function-declaration.js +91 -0
  35. package/packages/printer-wasm/printer/visitors/identifier.js +11 -0
  36. package/packages/printer-wasm/printer/visitors/if-statement.js +128 -0
  37. package/packages/printer-wasm/printer/visitors/program.js +26 -0
  38. package/packages/printer-wasm/printer/visitors/return.js +16 -0
  39. package/packages/printer-wasm/printer.js +10 -0
  40. package/packages/test-wasm/test.js +45 -0
  41. package/packages/transformer-fasm/transformer.js +70 -0
  42. package/packages/transformer-wasm/transformer.js +20 -0
  43. package/packages/translator-fasm/dump.js +68 -0
  44. package/packages/translator-fasm/translator.js +15 -0
  45. package/packages/translator-wasm/translator.js +51 -0
@@ -0,0 +1,31 @@
1
+ import {types} from '@putout/babel';
2
+
3
+ const {isCallExpression} = types;
4
+
5
+ export const isWastMemory = (expression) => {
6
+ if (!isCallExpression(expression))
7
+ return;
8
+
9
+ const {name} = expression.node.callee;
10
+
11
+ return name === '__ishvara_wasm_memory';
12
+ };
13
+
14
+ export function printWasmMemory(path, printer) {
15
+ const {print} = printer;
16
+ const [first, second] = path.get('arguments');
17
+
18
+ print('(memory ');
19
+
20
+ if (!second) {
21
+ print(first);
22
+ } else {
23
+ print('(export ');
24
+ print(first);
25
+ print(')');
26
+ print.space();
27
+ print(second);
28
+ }
29
+
30
+ print(')');
31
+ }
@@ -0,0 +1,91 @@
1
+ import {types} from '@putout/babel';
2
+ import {isNext, isNextParent} from '@putout/printer/is';
3
+ import {printParams} from '../params.js';
4
+
5
+ const {
6
+ isAssignmentExpression,
7
+ isTSModuleBlock,
8
+ isBlockStatement,
9
+ isExpressionStatement,
10
+ isFunctionDeclaration,
11
+ } = types;
12
+
13
+ export const FunctionDeclaration = {
14
+ print(path, printer, semantics) {
15
+ const {print} = printer;
16
+ const {generator, returnType} = path.node;
17
+
18
+ print('(');
19
+ print('func');
20
+
21
+ if (!generator) {
22
+ print(' ');
23
+ } else {
24
+ print('*');
25
+ print.space();
26
+ }
27
+
28
+ print('$');
29
+ print('__id');
30
+
31
+ if (path.parentPath.isExportNamedDeclaration()) {
32
+ print(' ');
33
+ print('(');
34
+ print('export ');
35
+ print('"');
36
+ print('__id');
37
+ print('"');
38
+ print(')');
39
+ print(' ');
40
+ }
41
+
42
+ printParams(path, printer, semantics, {
43
+ braceOpen: '(param ',
44
+ });
45
+
46
+ if (returnType) {
47
+ print.space();
48
+ print('(');
49
+ print('result ');
50
+ print('__returnType');
51
+ print(')');
52
+ }
53
+
54
+ print('__body');
55
+ print(')');
56
+ },
57
+ afterSatisfy: () => [isNext, isNextParent, isInsideBlockStatement],
58
+ after(path, {indent, write}) {
59
+ if (isNextAssign(path) || isNextFunction(path) || isNext(path))
60
+ indent();
61
+
62
+ write.breakline();
63
+ //maybe.write.newline(notInsideExportDefaultWithBody(path));
64
+ },
65
+ };
66
+
67
+ const isNextFunction = (path) => {
68
+ const next = path.getNextSibling();
69
+ return isFunctionDeclaration(next);
70
+ };
71
+
72
+ const isNextAssign = (path) => {
73
+ const next = path.getNextSibling();
74
+
75
+ if (!isExpressionStatement(next))
76
+ return false;
77
+
78
+ return isAssignmentExpression(next.node.expression);
79
+ };
80
+
81
+ function isInsideBlockStatement(path) {
82
+ const {parentPath} = path;
83
+
84
+ if (isTSModuleBlock(parentPath.parentPath))
85
+ return true;
86
+
87
+ if (!isBlockStatement(parentPath))
88
+ return false;
89
+
90
+ return !path.node.body.body.length;
91
+ }
@@ -0,0 +1,11 @@
1
+ import {maybeTypeAnnotation} from '../maybe-type-annotation.js';
2
+
3
+ export const Identifier = maybeTypeAnnotation((path, printer) => {
4
+ const {write, maybe} = printer;
5
+
6
+ const {node} = path;
7
+ const {name, optional} = node;
8
+
9
+ write(name);
10
+ maybe.write(optional, '?');
11
+ });
@@ -0,0 +1,128 @@
1
+ import {types} from '@putout/babel';
2
+ import {exists, isInsideIf} from '@putout/printer/is';
3
+
4
+ const {
5
+ isBlockStatement,
6
+ isFunctionDeclaration,
7
+ isStatement,
8
+ isReturnStatement,
9
+ } = types;
10
+
11
+ const isTopLevel = ({parentPath}) => parentPath.parentPath.isProgram();
12
+
13
+ const isInsideNestedBody = ({parentPath}) => {
14
+ if (parentPath.type !== 'BlockStatement')
15
+ return false;
16
+
17
+ return parentPath.parentPath.type === 'BlockStatement';
18
+ };
19
+
20
+ const isEmptyBody = (path) => !path.node.body.length;
21
+
22
+ const isLastEmptyInsideBody = (path) => {
23
+ const {parentPath} = path;
24
+
25
+ if (!isBlockStatement(parentPath))
26
+ return false;
27
+
28
+ if (!isBlockStatement(path.node.consequent))
29
+ return false;
30
+
31
+ if (path.node.consequent.body.length)
32
+ return false;
33
+
34
+ return isFunctionDeclaration(path.parentPath.parentPath);
35
+ };
36
+
37
+ export const IfStatement = (path, {indent, print, maybe, write, traverse}) => {
38
+ const {parentPath} = path;
39
+ const partOfAlternate = parentPath.get('alternate');
40
+
41
+ if (path !== partOfAlternate)
42
+ indent();
43
+
44
+ print('(if');
45
+
46
+ if (path.node.test.typeArguments) {
47
+ print.space();
48
+ print('(result ');
49
+ print(path.get('test.typeArguments.params.0.typeName'));
50
+ print(')');
51
+ }
52
+
53
+ indent.inc();
54
+ print.breakline();
55
+
56
+ print('__test');
57
+ print.breakline();
58
+ print('(then');
59
+
60
+ const consequent = path.get('consequent');
61
+ const alternate = path.get('alternate');
62
+ const isConsequentBlock = consequent.isBlockStatement();
63
+ const isVar = consequent.isVariableDeclaration();
64
+
65
+ if (isConsequentBlock) {
66
+ print.space();
67
+ print(consequent);
68
+
69
+ if (isInsideIf(path.parentPath) || isInsideNestedBody(path))
70
+ maybe.print.newline(isEmptyBody(consequent));
71
+ } else {
72
+ const isRet = isReturnStatement(consequent);
73
+ print.newline();
74
+ indent.inc();
75
+ maybe.indent(!isRet);
76
+ print(consequent);
77
+ indent.dec();
78
+ maybe.print.newline(!isRet);
79
+ }
80
+
81
+ indent();
82
+ print(')');
83
+ print.newline();
84
+
85
+ if (alternate.isBlockStatement()) {
86
+ write.space();
87
+ write('(else');
88
+ write.space();
89
+ traverse(alternate);
90
+ } else if (alternate.isIfStatement()) {
91
+ if (alternate.get('consequent').isBlockStatement())
92
+ write.space();
93
+ else
94
+ indent();
95
+
96
+ write('(else ');
97
+ traverse(alternate);
98
+ } else if (exists(alternate)) {
99
+ maybe.write.newline(isVar);
100
+ maybe.indent(!isConsequentBlock);
101
+ maybe.write.space(isConsequentBlock);
102
+ write('(else');
103
+ write.splitter();
104
+ indent.inc();
105
+
106
+ const isRet = isReturnStatement(alternate);
107
+ maybe.indent(!isRet);
108
+ traverse(alternate);
109
+ maybe.write.newline(!isRet);
110
+ indent.dec();
111
+ indent();
112
+ write(')');
113
+ write.newline();
114
+ }
115
+
116
+ const nextPath = path.parentPath.getNextSibling();
117
+
118
+ if (path === partOfAlternate && !isTopLevel(path) && !isStatement(nextPath))
119
+ print.newline();
120
+
121
+ if (isLastEmptyInsideBody(path))
122
+ print.newline();
123
+
124
+ indent.dec();
125
+ indent();
126
+ print(')');
127
+ print.newline();
128
+ };
@@ -0,0 +1,26 @@
1
+ import {hasCoupleTrailingComments} from '@putout/printer/is';
2
+
3
+ export const Program = (path, printer) => {
4
+ const {body} = path.node;
5
+ const {
6
+ traverse,
7
+ write,
8
+ indent,
9
+ } = printer;
10
+
11
+ traverse(path.get('interpreter'));
12
+ write('(');
13
+ write('module');
14
+ indent.inc();
15
+ write.breakline();
16
+
17
+ path.get('body').forEach(traverse);
18
+ indent.dec();
19
+ write.newline();
20
+ write(')');
21
+
22
+ if (body.length && hasCoupleTrailingComments(body.at(-1)))
23
+ return;
24
+
25
+ write.endOfFile();
26
+ };
@@ -0,0 +1,16 @@
1
+ export const ReturnStatement = (path, printer) => {
2
+ const {
3
+ indent,
4
+ print,
5
+ maybe,
6
+ } = printer;
7
+
8
+ indent();
9
+ print('(');
10
+ print('return');
11
+ maybe.print.space(path.node.argument);
12
+
13
+ print('__argument');
14
+ print(')');
15
+ print.newline();
16
+ };
@@ -0,0 +1,10 @@
1
+ import {parse} from 'putout';
2
+ import * as printer from './printer/printer.js';
3
+
4
+ export const print = (source) => {
5
+ const ast = parse(source, {
6
+ isTS: true,
7
+ });
8
+
9
+ return printer.print(ast);
10
+ };
@@ -0,0 +1,45 @@
1
+ const {entries} = Object;
2
+
3
+ export const prepare = (wast) => {
4
+ const result = {};
5
+ let stack = [];
6
+ let imports = [];
7
+
8
+ for (const [name, value] of entries(wast)) {
9
+ if (name === 'stack') {
10
+ stack = value;
11
+ continue;
12
+ }
13
+
14
+ if (name === 'imports') {
15
+ imports = value;
16
+ continue;
17
+ }
18
+
19
+ result[name] = (...args) => {
20
+ value(...args);
21
+
22
+ return stack[0];
23
+ };
24
+ }
25
+
26
+ result.declareImport = (module, name, override) => {
27
+ for (const [i, [currentModule, currentName]] of imports.entries()) {
28
+ if (module === currentModule && name === currentName) {
29
+ imports[i].push(override);
30
+ return;
31
+ }
32
+ }
33
+ };
34
+
35
+ result.undeclareImport = (module, name) => {
36
+ for (const [i, [currentModule, currentName]] of imports.entries()) {
37
+ if (module === currentModule && name === currentName) {
38
+ imports[i].pop();
39
+ return;
40
+ }
41
+ }
42
+ };
43
+
44
+ return result;
45
+ };
@@ -0,0 +1,70 @@
1
+ import {readFileSync as _readFileSync} from 'node:fs';
2
+ import putout from 'putout';
3
+ import * as removeUselessOperand from '@putout/plugin-remove-useless-operand';
4
+ import * as removeNestedBlocks from '@putout/plugin-remove-nested-blocks';
5
+ import * as fasm from '@nirguna/plugin-fasm';
6
+ import * as ishvara from '@nirguna/plugin-ishvara';
7
+ import * as bundler from '@nirguna/plugin-bandler-fasm';
8
+
9
+ const defaultConfig = {
10
+ rules: {},
11
+ plugins: [],
12
+ };
13
+
14
+ const parseConfig = (config) => ({
15
+ ...defaultConfig,
16
+ ...config,
17
+ });
18
+
19
+ export const transform = (source, config) => {
20
+ const {
21
+ debug,
22
+ plugins,
23
+ rules,
24
+ readFileSync = _readFileSync,
25
+ } = parseConfig(config);
26
+
27
+ const variables = [];
28
+ const functions = [];
29
+
30
+ const {code: bundled} = putout(source, {
31
+ isTS: true,
32
+ rules: {
33
+ 'ishvara/bundler-fasm/apply-debug': ['on', {
34
+ debug,
35
+ count: 0,
36
+ variables,
37
+ functions,
38
+ }],
39
+ 'ishvara/bundler-fasm/replace-section-data-with-let': ['on', {
40
+ variables,
41
+ }],
42
+ 'ishvara/bundler-fasm/replace-section-code-with-functions': ['on', {
43
+ functions,
44
+ }],
45
+ },
46
+ plugins: [
47
+ ['ishvara/bundler-fasm', bundler],
48
+ ],
49
+ });
50
+
51
+ const {code, places} = putout(bundled, {
52
+ fixCount: 5,
53
+ isTS: true,
54
+ rules: {
55
+ ...rules,
56
+ 'ishvara/fasm/apply-include': ['on', {
57
+ readFileSync,
58
+ }],
59
+ },
60
+ plugins: [
61
+ ...plugins,
62
+ ['remove-useless-operand', removeUselessOperand],
63
+ ['remove-nested-blocks', removeNestedBlocks],
64
+ ['ishvara/ishvara', ishvara],
65
+ ['ishvara/fasm', fasm],
66
+ ],
67
+ });
68
+
69
+ return [code, places];
70
+ };
@@ -0,0 +1,20 @@
1
+ import putout from 'putout';
2
+ import * as removeNestedBlocks from '@putout/plugin-remove-nested-blocks';
3
+ import * as esm from '@putout/plugin-esm';
4
+ import * as ishvara from '@nirguna/plugin-ishvara';
5
+ import * as wasm from '@nirguna/plugin-wasm';
6
+
7
+ export const transform = (source) => {
8
+ const {code, places} = putout(source, {
9
+ fix: true,
10
+ isTS: true,
11
+ plugins: [
12
+ ['ishvara/wasm', wasm],
13
+ ['ishvara/ishvara', ishvara],
14
+ ['esm', esm],
15
+ ['remove-nested-blocks', removeNestedBlocks],
16
+ ],
17
+ });
18
+
19
+ return [code, places];
20
+ };
@@ -0,0 +1,68 @@
1
+ import {
2
+ Decoder,
3
+ DecoderOptions,
4
+ Formatter,
5
+ FormatterSyntax,
6
+ } from 'iced-x86';
7
+
8
+ function parseBitness(source) {
9
+ if (source.startsWith('use32'))
10
+ return 32;
11
+
12
+ return 16;
13
+ }
14
+
15
+ export const dump = (source, binary) => {
16
+ const exampleRip = 0x0000000000007c00n;
17
+ const hexBytesColumnByteLength = 10;
18
+ const bitness = parseBitness(source);
19
+
20
+ const decoder = new Decoder(bitness, binary, DecoderOptions.None);
21
+
22
+ decoder.ip = exampleRip;
23
+ // This decodes all bytes. There's also `decode()` which decodes the next instruction,
24
+ // `decodeInstructions(count)` which decodes `count` instructions and `decodeOut(instruction)`
25
+ // which overwrites an existing instruction.
26
+ const instructions = decoder.decodeAll();
27
+
28
+ // Create a nasm formatter. It supports: Masm, Nasm, Gas (AT&T) and Intel (XED).
29
+ // There's also `FastFormatter` which uses less code (smaller wasm files).
30
+ // const formatter = new FastFormatter();
31
+ const formatter = new Formatter(FormatterSyntax.Intel);
32
+
33
+ // Change some options, there are many more
34
+ formatter.digitSeparator = '`';
35
+ formatter.firstOperandCharIndex = 10;
36
+ // Format the instructions
37
+
38
+ const output = instructions.map((instruction) => {
39
+ // Eg. "00007FFAC46ACDB2 488DAC2400FFFFFF lea rbp,[rsp-100h]"
40
+ let line = instruction.ip.toString(16);
41
+
42
+ line += ' ';
43
+ const startIndex = Number(instruction.ip - exampleRip);
44
+
45
+ for (const b of binary.slice(startIndex, startIndex + instruction.length)) {
46
+ line += ('0' + b.toString(16))
47
+ .substr(-2)
48
+ .toUpperCase();
49
+ }
50
+
51
+ for (let i = instruction.length; i < hexBytesColumnByteLength; i++)
52
+ line += ' ';
53
+
54
+ line += ' ';
55
+ line += formatter.format(instruction);
56
+
57
+ return line;
58
+ });
59
+
60
+ // Free wasm memory
61
+ for (const instruction of instructions)
62
+ instruction.free();
63
+
64
+ formatter.free();
65
+ decoder.free();
66
+
67
+ return output.join('\n');
68
+ };
@@ -0,0 +1,15 @@
1
+ import * as fasm from 'fasm.js';
2
+ import {dump} from './dump.js';
3
+
4
+ export const translate = async (source, options = {}) => {
5
+ const {type} = options;
6
+ const [binary, places] = await fasm.translate(source);
7
+
8
+ if (type === 'dump')
9
+ return [
10
+ dump(source, binary),
11
+ [],
12
+ ];
13
+
14
+ return [binary, places];
15
+ };
@@ -0,0 +1,51 @@
1
+ import createWabt from 'wabt';
2
+ import {tryCatch} from 'try-catch';
3
+
4
+ export const translate = async (wast, options = {}) => {
5
+ const {name = 'ishvara.wast', type} = options;
6
+
7
+ const {parseWat} = await createWabt();
8
+ const [error, parsedWat] = tryCatch(parseWat, name, wast);
9
+
10
+ if (error)
11
+ return [null, toPlaces(name, error)];
12
+
13
+ const {log, buffer} = parsedWat.toBinary({
14
+ log: type === 'dump',
15
+ });
16
+
17
+ return [
18
+ log || buffer,
19
+ [],
20
+ ];
21
+ };
22
+
23
+ function toPlaces(name, error) {
24
+ const [, first] = error.message.split('\n');
25
+
26
+ const list = first
27
+ .replace(`${name}�`, '')
28
+ .split(':');
29
+
30
+ list.shift();
31
+
32
+ const [line, column] = list;
33
+
34
+ list.shift();
35
+ list.shift();
36
+ list.shift();
37
+
38
+ const messageRaw = list
39
+ .join(':')
40
+ .slice(1);
41
+
42
+ const message = messageRaw[0].toUpperCase() + messageRaw.slice(1);
43
+
44
+ return [{
45
+ message,
46
+ position: {
47
+ line: Number(line),
48
+ column: Number(column),
49
+ },
50
+ }];
51
+ }