@nirguna/plugin-fasm 1.0.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 (49) hide show
  1. package/README.md +48 -0
  2. package/lib/add-label-prefix/index.js +50 -0
  3. package/lib/apply-equality/index.js +8 -0
  4. package/lib/apply-inc/index.js +8 -0
  5. package/lib/apply-include/index.js +17 -0
  6. package/lib/apply-registers/index.js +44 -0
  7. package/lib/apply-types/index.js +79 -0
  8. package/lib/convert-args-to-regs/index.js +170 -0
  9. package/lib/convert-assign-to-add/index.js +5 -0
  10. package/lib/convert-assign-to-and/index.js +5 -0
  11. package/lib/convert-assign-to-member/index.js +5 -0
  12. package/lib/convert-assign-to-mov/index.js +53 -0
  13. package/lib/convert-assign-to-or/index.js +5 -0
  14. package/lib/convert-assign-to-shl/index.js +5 -0
  15. package/lib/convert-assign-to-sub/index.js +5 -0
  16. package/lib/convert-assign-to-xor/index.js +5 -0
  17. package/lib/convert-await-to-call/index.js +53 -0
  18. package/lib/convert-bios-clear-screen-to-int-10/index.js +8 -0
  19. package/lib/convert-bios-print-line-to-int-10/index.js +52 -0
  20. package/lib/convert-bios-read-char-to-int-16/index.js +18 -0
  21. package/lib/convert-bios-read-sector-to-int-13/index.js +80 -0
  22. package/lib/convert-bios-reboot-to-jmp-far/index.js +5 -0
  23. package/lib/convert-bios-scroll-to-int-10/index.js +16 -0
  24. package/lib/convert-const-to-equ/index.js +15 -0
  25. package/lib/convert-dec-to-hex/index.js +19 -0
  26. package/lib/convert-declaration-to-mov/index.js +23 -0
  27. package/lib/convert-do-while-to-jnz/index.js +155 -0
  28. package/lib/convert-equ-call-to-member/index.js +30 -0
  29. package/lib/convert-function-to-label/index.js +114 -0
  30. package/lib/convert-if-to-jmp/index.js +166 -0
  31. package/lib/convert-if-to-jmp/operator.js +27 -0
  32. package/lib/convert-linux-exit-to-syscall/index.js +15 -0
  33. package/lib/convert-linux-write-to-syscall/index.js +48 -0
  34. package/lib/convert-mov-to-add/index.js +5 -0
  35. package/lib/convert-return-to-eax/index.js +76 -0
  36. package/lib/convert-strncmp-to-repe-cmpsb/index.js +23 -0
  37. package/lib/convert-ternary-to-if/index.js +5 -0
  38. package/lib/convert-ureg-to-reg/index.js +108 -0
  39. package/lib/convert-while-to-jz/index.js +158 -0
  40. package/lib/extract-labeled-block/index.js +68 -0
  41. package/lib/index.js +93 -0
  42. package/lib/remove-useless-braces/index.js +5 -0
  43. package/lib/remove-useless-declarations/index.js +7 -0
  44. package/lib/remove-useless-promise/index.js +5 -0
  45. package/lib/split-assign-await-with-assign-eax/index.js +41 -0
  46. package/lib/split-binary-expression/index.js +31 -0
  47. package/lib/split-stack-operations/index.js +50 -0
  48. package/lib/switch-cmp-operands/index.js +19 -0
  49. package/package.json +56 -0
@@ -0,0 +1,48 @@
1
+ import {operator, types} from 'putout';
2
+
3
+ const {isArrayExpression} = types;
4
+ const {extract} = operator;
5
+ const STDOUT = 1;
6
+
7
+ export const report = () => `Use 'syscall' instead of 'linux.write()'`;
8
+
9
+ export const match = () => ({
10
+ 'linux.write()': (vars, path) => {
11
+ return path.parentPath.isExpressionStatement();
12
+ },
13
+ });
14
+
15
+ export const replace = () => ({
16
+ 'linux.write(__object)': ({__object}) => {
17
+ const {
18
+ descriptor = STDOUT,
19
+ message = 0,
20
+ length = 0,
21
+ } = parseArgs(__object.properties);
22
+
23
+ return `{
24
+ rdi = ${descriptor};
25
+ rsi = ${message};
26
+ rdx = ${length};
27
+ rax = 1;
28
+ syscall();
29
+ }`;
30
+ },
31
+ });
32
+
33
+ function parseArgs(properties) {
34
+ const result = {};
35
+
36
+ for (const {key, value} of properties) {
37
+ const extracted = extract(value);
38
+
39
+ if (isArrayExpression(value)) {
40
+ result[key.name] = `[${extracted}]`;
41
+ continue;
42
+ }
43
+
44
+ result[key.name] = extracted;
45
+ }
46
+
47
+ return result;
48
+ }
@@ -0,0 +1,5 @@
1
+ export const report = () => `Use 'add' instead of 'mov'`;
2
+
3
+ export const replace = () => ({
4
+ 'mov(__a, __a + __b)': 'add(__a, __b)',
5
+ });
@@ -0,0 +1,76 @@
1
+ import {types} from 'putout';
2
+
3
+ const {isFunction} = types;
4
+ const i16 = [
5
+ 'ax',
6
+ 'bx',
7
+ 'cx',
8
+ 'dx',
9
+ 'di',
10
+ 'si',
11
+ ];
12
+
13
+ export const report = () => `Use 'eax' instead of 'return'`;
14
+
15
+ export const replace = () => ({
16
+ 'return': 'ret()',
17
+ 'return __a': ({__a}, path) => {
18
+ if (i16.includes(__a.name))
19
+ return `{
20
+ ax = __a;
21
+ ret();
22
+ }`;
23
+
24
+ const fnPath = path.find(isFunction);
25
+
26
+ if (fnPath) {
27
+ const {returnType} = fnPath.node;
28
+
29
+ if (!fnPath.node.params.length)
30
+ delete fnPath.node.returnType;
31
+
32
+ const name = parseType(fnPath, returnType);
33
+
34
+ const reg = getReg(name);
35
+
36
+ return `{
37
+ ${reg} = __a;
38
+ ret();
39
+ }`;
40
+ }
41
+
42
+ return `{
43
+ ax = __a;
44
+ ret();
45
+ }`;
46
+ },
47
+ });
48
+
49
+ function parseType(path, returnType) {
50
+ const {__nirguna_return_type} = path;
51
+
52
+ if (__nirguna_return_type)
53
+ return __nirguna_return_type;
54
+
55
+ if (!returnType)
56
+ return '';
57
+
58
+ const {name} = returnType.typeAnnotation.typeName;
59
+
60
+ path.__nirguna_return_type = name;
61
+
62
+ return name;
63
+ }
64
+
65
+ function getReg(name) {
66
+ if (name === 'i8')
67
+ return 'al';
68
+
69
+ if (name === 'i32')
70
+ return 'eax';
71
+
72
+ if (name === 'i64')
73
+ return 'rax';
74
+
75
+ return 'ax';
76
+ }
@@ -0,0 +1,23 @@
1
+ export const report = () => `Use 'repe.cmbsp()' instead of 'strncmp()'`;
2
+
3
+ export const match = () => ({
4
+ 'strncmp(__a, __b, __c)': (vars, path) => {
5
+ return path.parentPath.isExpressionStatement();
6
+ },
7
+ });
8
+
9
+ export const replace = () => ({
10
+ '__a = strncmp(__b, __c, __d)': `{
11
+ mov(cx, __d);
12
+ si = __b;
13
+ di =__c
14
+ repe.cmpsb();
15
+ mov(__a, cx);
16
+ }`,
17
+ 'strncmp(__a, __b, __c)': `{
18
+ mov(cx, __c);
19
+ si = __a;
20
+ di =__b
21
+ repe.cmpsb();
22
+ }`,
23
+ });
@@ -0,0 +1,5 @@
1
+ export const report = () => `Use 'if' instead of 'ternary'`;
2
+
3
+ export const replace = () => ({
4
+ '__a = __b ? __c : __d': 'if (__b) __a = __c; else __a = __d',
5
+ });
@@ -0,0 +1,108 @@
1
+ import {operator} from 'putout';
2
+
3
+ const {keys} = Object;
4
+ const {rename} = operator;
5
+
6
+ function getBitness(path) {
7
+ const programPath = path.scope.getProgramParent().path;
8
+ const {directives} = programPath.node;
9
+
10
+ if (!directives.length)
11
+ return 16;
12
+
13
+ const {value} = directives[0].value;
14
+
15
+ if (value === 'use 16')
16
+ return 16;
17
+
18
+ if (value === 'use 32')
19
+ return 32;
20
+
21
+ if (value === 'use 64')
22
+ return 64;
23
+
24
+ return '16';
25
+ }
26
+
27
+ export const report = () => `Use 'reg' instead of 'ureg'`;
28
+
29
+ export const fix = ({path, names}) => {
30
+ const bitness = getBitness(path);
31
+
32
+ for (const name of names) {
33
+ rename(path, name, REG[bitness][name]);
34
+ }
35
+
36
+ if (path.node.returnType)
37
+ path.node.returnType.typeAnnotation.typeName.name = `i${bitness}`;
38
+ };
39
+
40
+ const isUReg = (a) => {
41
+ return keys(REG_16).includes(a);
42
+ };
43
+
44
+ const REG_16 = {
45
+ uax: 'ax',
46
+ ubx: 'bx',
47
+ ucx: 'cx',
48
+ udx: 'dx',
49
+ usi: 'si',
50
+ udi: 'di',
51
+ usp: 'sp',
52
+ ubp: 'bp',
53
+ };
54
+
55
+ const REG_32 = {
56
+ uax: 'eax',
57
+ ubx: 'ebx',
58
+ ucx: 'ecx',
59
+ udx: 'edx',
60
+ usi: 'esi',
61
+ udi: 'edi',
62
+ usp: 'esp',
63
+ ubp: 'ebp',
64
+ };
65
+
66
+ const REG_64 = {
67
+ uax: 'rax',
68
+ ubx: 'rbx',
69
+ ucx: 'rcx',
70
+ udx: 'rdx',
71
+ usi: 'rsi',
72
+ udi: 'rdi',
73
+ usp: 'rsp',
74
+ ubp: 'rbp',
75
+ };
76
+
77
+ const REG = {
78
+ 16: REG_16,
79
+ 32: REG_32,
80
+ 64: REG_64,
81
+ };
82
+
83
+ export const traverse = ({push}) => ({
84
+ Function(path) {
85
+ const {bindings} = path.scope;
86
+ const names = [];
87
+
88
+ for (const name of keys(bindings)) {
89
+ if (!isUReg(name))
90
+ continue;
91
+
92
+ names.push(name);
93
+ }
94
+
95
+ if (!names.length)
96
+ return;
97
+
98
+ push({
99
+ path,
100
+ names,
101
+ });
102
+ },
103
+ Program: {
104
+ exit(path) {
105
+ path.node.directives = [];
106
+ },
107
+ },
108
+ });
@@ -0,0 +1,158 @@
1
+ import {
2
+ template,
3
+ types,
4
+ operator,
5
+ print,
6
+ } from 'putout';
7
+
8
+ const {
9
+ compare,
10
+ extract,
11
+ replaceWith,
12
+ insertAfter,
13
+ } = operator;
14
+
15
+ const {
16
+ identifier,
17
+ expressionStatement,
18
+ isCallExpression,
19
+ labeledStatement,
20
+ isBooleanLiteral,
21
+ isArrayExpression,
22
+ blockStatement,
23
+ isBlockStatement,
24
+ } = types;
25
+
26
+ const createStartLabel = (line) => `__nirguna_while_${line}`;
27
+ const createConditionLabel = (line) => `__nirguna_while_condition_${line}`;
28
+
29
+ export const report = () => `Use 'jz' instead of 'while'`;
30
+
31
+ export const replace = () => ({
32
+ 'while(__a) __b': ({__a, __b}, path) => {
33
+ const {line} = path.node.loc.start;
34
+ const startLabel = createStartLabel(line);
35
+ const conditionLabel = createConditionLabel(line);
36
+ const [one, two, jnz, test] = parseWhileArgs(__a);
37
+ const endLabel = createEndLabel(path, line);
38
+
39
+ let conditionExpression = createExpression(__a, {
40
+ one,
41
+ two,
42
+ test,
43
+ });
44
+
45
+ const wasContinue = maybeReplaceContinueWithJmp(path, conditionLabel);
46
+
47
+ if (wasContinue)
48
+ conditionExpression = labeledStatement(identifier(conditionLabel), conditionExpression);
49
+
50
+ const body = isBlockStatement(__b) ? __b : blockStatement([expressionStatement(__b)]);
51
+ body.body.unshift(expressionStatement(template.ast(`${jnz}(${endLabel})`)));
52
+ body.body.unshift(conditionExpression);
53
+
54
+ body.body.push(expressionStatement(template.ast(`jmp(${startLabel})`)));
55
+
56
+ maybeReplaceBreak(path, endLabel);
57
+
58
+ return labeledStatement(identifier(startLabel), body);
59
+ },
60
+ });
61
+
62
+ const parseWhileArgs = (__a) => {
63
+ if (isBooleanLiteral(__a) && __a.value)
64
+ return [
65
+ 'al',
66
+ 'al',
67
+ 'je',
68
+ 'cmp',
69
+ ];
70
+
71
+ if (isBooleanLiteral(__a) && !__a.value)
72
+ return [
73
+ 'al',
74
+ 'al',
75
+ 'je',
76
+ 'cmp',
77
+ ];
78
+
79
+ if (isArrayExpression(__a))
80
+ return [
81
+ 'al',
82
+ 'al',
83
+ 'jz',
84
+ 'test',
85
+ ];
86
+
87
+ if (compare(__a, '__a === __b'))
88
+ return [
89
+ extract(__a.left),
90
+ extract(__a.right),
91
+ 'jz',
92
+ 'test',
93
+ ];
94
+
95
+ return [
96
+ __a.name,
97
+ __a.name,
98
+ 'jz',
99
+ 'test',
100
+ ];
101
+ };
102
+
103
+ const printExpression = (a) => print(a).slice(0, -2);
104
+
105
+ function createExpression(__a, {one, two, test}) {
106
+ if (isCallExpression(__a)) {
107
+ const op = printExpression(__a);
108
+
109
+ return blockStatement([
110
+ expressionStatement(template.ast(op)),
111
+ expressionStatement(template.ast(`${test}(al, al)`)),
112
+ ]);
113
+ }
114
+
115
+ if (isArrayExpression(__a)) {
116
+ const source = printExpression(__a);
117
+
118
+ return blockStatement([
119
+ expressionStatement(template.ast(`mov(al, ${source})`)),
120
+ expressionStatement(template.ast(`${test}(al, al)`)),
121
+ ]);
122
+ }
123
+
124
+ return expressionStatement(template.ast(`${test}(${one}, ${two})`));
125
+ }
126
+
127
+ function maybeReplaceContinueWithJmp(path, startLabel) {
128
+ let was = false;
129
+
130
+ path.traverse({
131
+ ContinueStatement(path) {
132
+ path.replaceWithSourceString(`jmp(${startLabel})`);
133
+ was = true;
134
+ },
135
+ });
136
+ return was;
137
+ }
138
+
139
+ function maybeReplaceBreak(path, endLabel) {
140
+ path.traverse({
141
+ BreakStatement(path) {
142
+ path.replaceWithSourceString(`jmp(${endLabel})`);
143
+ },
144
+ });
145
+ }
146
+
147
+ function createEndLabel(path, line) {
148
+ const endLabel = `__nirguna_while_end_${line}`;
149
+ const nextPath = path.getNextSibling();
150
+ const labeledNode = labeledStatement(identifier(endLabel), nextPath.node || expressionStatement(template.ast('nop()')));
151
+
152
+ if (nextPath.node)
153
+ replaceWith(nextPath, labeledNode);
154
+ else
155
+ insertAfter(path, labeledNode);
156
+
157
+ return endLabel;
158
+ }
@@ -0,0 +1,68 @@
1
+ import {types, operator} from 'putout';
2
+
3
+ const {getTemplateValues} = operator;
4
+
5
+ const {
6
+ isProgram,
7
+ isBlockStatement,
8
+ isLabeledStatement,
9
+ } = types;
10
+
11
+ export const report = ({path}) => {
12
+ const {name} = path.node.label;
13
+
14
+ return `Extract 'labeled' block: '${name}'`;
15
+ };
16
+
17
+ export const fix = ({path, first, other}) => {
18
+ path.node.body = first;
19
+
20
+ const index = path.parentPath.node.body.indexOf(path.node);
21
+ const {body} = path.parentPath.node;
22
+
23
+ body.splice(index + 1, 0, ...other);
24
+ };
25
+ export const traverse = ({push}) => ({
26
+ '__a: __b: {__body}': (path) => {
27
+ const {parentPath} = path;
28
+
29
+ if (isProgram(parentPath))
30
+ return;
31
+
32
+ if (isLabeledStatement(parentPath))
33
+ return;
34
+
35
+ if (isLabeledStatement(path.node.body))
36
+ return;
37
+
38
+ const {__body} = getTemplateValues(path, '__a: __b: {__body}');
39
+
40
+ const [first, ...other] = __body.body;
41
+
42
+ if (!isBlockStatement(first))
43
+ push({
44
+ path,
45
+ first,
46
+ other,
47
+ });
48
+ },
49
+ '__a: {__body}': (path) => {
50
+ const {parentPath} = path;
51
+
52
+ if (isLabeledStatement(parentPath))
53
+ return;
54
+
55
+ if (isProgram(parentPath))
56
+ return;
57
+
58
+ const {__body} = getTemplateValues(path, '__a: {__body}');
59
+ const [first, ...other] = __body.body;
60
+
61
+ if (!isBlockStatement(first))
62
+ push({
63
+ path,
64
+ first,
65
+ other,
66
+ });
67
+ },
68
+ });
package/lib/index.js ADDED
@@ -0,0 +1,93 @@
1
+ import * as removeUselessPromise from './remove-useless-promise/index.js';
2
+ import * as applyInclude from './apply-include/index.js';
3
+ import * as switchCmpOperands from './switch-cmp-operands/index.js';
4
+ import * as splitBinaryExpression from './split-binary-expression/index.js';
5
+ import * as convertLinuxExitToSyscall from './convert-linux-exit-to-syscall/index.js';
6
+ import * as convertLinuxWriteToSyscall from './convert-linux-write-to-syscall/index.js';
7
+ import * as convertWhileToJz from './convert-while-to-jz/index.js';
8
+ import * as convertUregToReg from './convert-ureg-to-reg/index.js';
9
+ import * as convertConstToEqu from './convert-const-to-equ/index.js';
10
+ import * as removeUselessBraces from './remove-useless-braces/index.js';
11
+ import * as applyRegisters from './apply-registers/index.js';
12
+ import * as convertAssignToOr from './convert-assign-to-or/index.js';
13
+ import * as convertAssignToAnd from './convert-assign-to-and/index.js';
14
+ import * as applyTypes from './apply-types/index.js';
15
+ import * as convertArgsToRegs from './convert-args-to-regs/index.js';
16
+ import * as convertTernaryToIf from './convert-ternary-to-if/index.js';
17
+ import * as convertStrncmpToRepeCmpsb from './convert-strncmp-to-repe-cmpsb/index.js';
18
+ import * as convertBiosRebootToJmpFar from './convert-bios-reboot-to-jmp-far/index.js';
19
+ import * as convertBiosReadSectorToInt13 from './convert-bios-read-sector-to-int-13/index.js';
20
+ import * as convertBiosReadCharToInt16 from './convert-bios-read-char-to-int-16/index.js';
21
+ import * as convertBiosScrollToInt10 from './convert-bios-scroll-to-int-10/index.js';
22
+ import * as splitAssignAwaitWithAssignEax from './split-assign-await-with-assign-eax/index.js';
23
+ import * as convertDoWhileToJnz from './convert-do-while-to-jnz/index.js';
24
+ import * as convertBiosPrintLineToInt10 from './convert-bios-print-line-to-int-10/index.js';
25
+ import * as convertBiosClearScreenToInt10 from './convert-bios-clear-screen-to-int-10/index.js';
26
+ import * as convertAssignToSub from './convert-assign-to-sub/index.js';
27
+ import * as applyEquality from './apply-equality/index.js';
28
+ import * as extractLabeledBlock from './extract-labeled-block/index.js';
29
+ import * as convertIfToJmp from './convert-if-to-jmp/index.js';
30
+ import * as removeUselessDeclarations from './remove-useless-declarations/index.js';
31
+ import * as addLabelPrefix from './add-label-prefix/index.js';
32
+ import * as convertDeclarationToToMov from './convert-declaration-to-mov/index.js';
33
+ import * as convertMovToAdd from './convert-mov-to-add/index.js';
34
+ import * as convertReturnToEax from './convert-return-to-eax/index.js';
35
+ import * as applyInc from './apply-inc/index.js';
36
+ import * as convEquCallToMember from './convert-equ-call-to-member/index.js';
37
+ import * as convertDecToHex from './convert-dec-to-hex/index.js';
38
+ import * as convertAssignToMember from './convert-assign-to-member/index.js';
39
+ import * as convertAssignToAdd from './convert-assign-to-add/index.js';
40
+ import * as convertAssignToMov from './convert-assign-to-mov/index.js';
41
+ import * as convertAssignToXor from './convert-assign-to-xor/index.js';
42
+ import * as convertAssignToShl from './convert-assign-to-shl/index.js';
43
+ import * as convertAwaitToCall from './convert-await-to-call/index.js';
44
+ import * as splitStackOperations from './split-stack-operations/index.js';
45
+ import * as convertFunctionToLabel from './convert-function-to-label/index.js';
46
+
47
+ export const rules = {
48
+ 'apply-types': applyTypes,
49
+ 'convert-dec-to-hex': convertDecToHex,
50
+ 'convert-equ-call-to-member': convEquCallToMember,
51
+ 'convert-assign-to-member': convertAssignToMember,
52
+ 'convert-assign-to-add': convertAssignToAdd,
53
+ 'convert-assign-to-mov': convertAssignToMov,
54
+ 'convert-assign-to-xor': convertAssignToXor,
55
+ 'convert-assign-to-shl': convertAssignToShl,
56
+ 'convert-function-to-label': convertFunctionToLabel,
57
+ 'convert-await-to-call': convertAwaitToCall,
58
+ 'split-stack-operations': splitStackOperations,
59
+ 'apply-inc': applyInc,
60
+ 'convert-return-to-eax': convertReturnToEax,
61
+ 'convert-mov-to-add': convertMovToAdd,
62
+ 'convert-declaration-to-mov': convertDeclarationToToMov,
63
+ 'add-label-prefix': addLabelPrefix,
64
+ 'remove-useless-declarations': removeUselessDeclarations,
65
+ 'convert-if-to-jmp': convertIfToJmp,
66
+ 'extract-labeled-block': extractLabeledBlock,
67
+ 'apply-equality': applyEquality,
68
+ 'convert-assign-to-sub': convertAssignToSub,
69
+ 'convert-bios-clear-screen-to-int-10': convertBiosClearScreenToInt10,
70
+ 'convert-bios-print-line-to-int-10': convertBiosPrintLineToInt10,
71
+ 'convert-do-while-to-jnz': convertDoWhileToJnz,
72
+ 'split-assign-await-with-assign-eax': splitAssignAwaitWithAssignEax,
73
+ 'convert-bios-scroll-to-int-10': convertBiosScrollToInt10,
74
+ 'convert-bios-read-char-to-int-16': convertBiosReadCharToInt16,
75
+ 'convert-bios-read-sector-to-int-13': convertBiosReadSectorToInt13,
76
+ 'convert-bios-reboot-to-jmp-far': convertBiosRebootToJmpFar,
77
+ 'convert-strncmp-to-repe-cmpsb': convertStrncmpToRepeCmpsb,
78
+ 'convert-ternary-to-if': convertTernaryToIf,
79
+ 'convert-args-to-regs': convertArgsToRegs,
80
+ 'convert-assign-to-and': convertAssignToAnd,
81
+ 'convert-assign-to-or': convertAssignToOr,
82
+ 'apply-registers': applyRegisters,
83
+ 'remove-useless-braces': removeUselessBraces,
84
+ 'convert-const-to-equ': convertConstToEqu,
85
+ 'convert-ureg-to-reg': convertUregToReg,
86
+ 'convert-while-to-jz': convertWhileToJz,
87
+ 'convert-linux-write-to-syscall': convertLinuxWriteToSyscall,
88
+ 'convert-linux-exit-to-syscall': convertLinuxExitToSyscall,
89
+ 'split-binary-expression': splitBinaryExpression,
90
+ 'switch-cmp-operands': switchCmpOperands,
91
+ 'apply-include': applyInclude,
92
+ 'remove-useless-promise': removeUselessPromise,
93
+ };
@@ -0,0 +1,5 @@
1
+ export const report = () => `Avoid useless braces`;
2
+
3
+ export const replace = () => ({
4
+ '[[__b]]': '[__b]',
5
+ });
@@ -0,0 +1,7 @@
1
+ export const report = () => `Avoid useless import of '#operator-fasm'`;
2
+
3
+ export const replace = () => ({
4
+ 'import __imports from "#operator-fasm"': '',
5
+ 'import __imports from "@nirguna/operator-fasm"': '',
6
+ 'export {__exports}': '',
7
+ });
@@ -0,0 +1,5 @@
1
+ export const report = () => `Avoid useless 'Promise' type`;
2
+
3
+ export const replace = () => ({
4
+ 'async function __a(__args): Promise<__b> {__body}': 'async function __a(__args): __b {__body}',
5
+ });
@@ -0,0 +1,41 @@
1
+ import {
2
+ is32bit,
3
+ is64bit,
4
+ is8bit,
5
+ } from '@nirguna/operator-fasm/regs';
6
+
7
+ export const report = () => `Get result from 'eax'`;
8
+
9
+ const getEax = (name) => {
10
+ if (is8bit(name))
11
+ return 'al';
12
+
13
+ if (is32bit(name))
14
+ return 'eax';
15
+
16
+ if (is64bit(name))
17
+ return 'rax';
18
+
19
+ return 'ax';
20
+ };
21
+
22
+ export const replace = () => ({
23
+ '__a = await __b(__args)': ({__a}) => {
24
+ const eax = getEax(__a.name);
25
+
26
+ return `{
27
+ __a = ${eax};
28
+ await __b(__args);
29
+ xchg(__a, ${eax});
30
+ }`;
31
+ },
32
+ '__a: __b = await __c(__args)': ({__b}) => {
33
+ const eax = getEax(__b.name);
34
+
35
+ return `{
36
+ __b = ${eax};
37
+ __a: await __c(__args);
38
+ xchg(__b, ${eax});
39
+ }`;
40
+ },
41
+ });
@@ -0,0 +1,31 @@
1
+ import {operator, types} from 'putout';
2
+
3
+ const {
4
+ isIdentifier,
5
+ isMemberExpression,
6
+ } = types;
7
+
8
+ const {compare} = operator;
9
+
10
+ export const report = () => `Split 'binary expression'`;
11
+
12
+ export const match = () => ({
13
+ '__a = __b + __c': ({__c, __a}) => {
14
+ if (isIdentifier(__c) && /[A-Z]/.test(__c.name))
15
+ return false;
16
+
17
+ return !isMemberExpression(__a);
18
+ },
19
+ });
20
+
21
+ export const replace = () => ({
22
+ '__a = __b + __c': ({__a, __b}) => {
23
+ if (compare(__a, __b))
24
+ return '__a += __c';
25
+
26
+ return `{
27
+ __a = __b;
28
+ __a += __c
29
+ }`;
30
+ },
31
+ });