@grey-ts/transpiler 1.4.3 → 2.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.
- package/dist/index.js +312 -216
- package/package.json +6 -5
package/dist/index.js
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import * as fs3 from "node:fs";
|
|
5
|
-
import
|
|
5
|
+
import path6 from "node:path";
|
|
6
6
|
|
|
7
7
|
// src/transpiler.ts
|
|
8
8
|
import * as fs2 from "node:fs";
|
|
9
|
-
import * as
|
|
9
|
+
import * as path5 from "node:path";
|
|
10
10
|
import ts14 from "typescript";
|
|
11
11
|
|
|
12
12
|
// src/nodeHandler.ts
|
|
13
|
+
import * as path from "node:path";
|
|
13
14
|
import ts from "typescript";
|
|
14
|
-
|
|
15
15
|
class NodeHandler {
|
|
16
16
|
static handlers = new Map;
|
|
17
17
|
static transpileContext;
|
|
@@ -29,13 +29,32 @@ class NodeHandler {
|
|
|
29
29
|
}
|
|
30
30
|
try {
|
|
31
31
|
const result = handler(node, this.transpileContext);
|
|
32
|
-
|
|
32
|
+
const extra = this.transpileContext.extraOutput.get(node);
|
|
33
|
+
if (!extra)
|
|
34
|
+
return result;
|
|
35
|
+
return [
|
|
36
|
+
...extra.before ? [extra.before] : [],
|
|
37
|
+
result,
|
|
38
|
+
...extra.after ? [extra.after] : []
|
|
39
|
+
].join(`
|
|
40
|
+
`);
|
|
33
41
|
} catch (error) {
|
|
34
42
|
console.error(error);
|
|
35
43
|
this.printLineAndCol(node);
|
|
36
44
|
return ts.isBlock(node.parent) || ts.isSourceFile(node.parent) ? "" : "null";
|
|
37
45
|
}
|
|
38
46
|
}
|
|
47
|
+
static addExtraOutput(node, before, after) {
|
|
48
|
+
let extra = this.transpileContext.extraOutput.get(node);
|
|
49
|
+
if (!extra) {
|
|
50
|
+
extra = { before: "", after: "" };
|
|
51
|
+
this.transpileContext.extraOutput.set(node, extra);
|
|
52
|
+
}
|
|
53
|
+
if (before)
|
|
54
|
+
extra.before += before;
|
|
55
|
+
if (after)
|
|
56
|
+
extra.after += after;
|
|
57
|
+
}
|
|
39
58
|
static printLineAndCol(node) {
|
|
40
59
|
const source = node.getSourceFile();
|
|
41
60
|
const lineAndChar = source.getLineAndCharacterOfPosition(node.pos);
|
|
@@ -47,6 +66,29 @@ NodeHandler.register(ts.SyntaxKind.InterfaceDeclaration, () => "");
|
|
|
47
66
|
NodeHandler.register(ts.SyntaxKind.ModuleDeclaration, () => "");
|
|
48
67
|
NodeHandler.register(ts.SyntaxKind.EndOfFileToken, () => "");
|
|
49
68
|
NodeHandler.register(ts.SyntaxKind.EmptyStatement, () => "");
|
|
69
|
+
NodeHandler.register(ts.SyntaxKind.SourceFile, (sourceFile, ctx) => {
|
|
70
|
+
if (ctx.visitedFiles.has(sourceFile.fileName))
|
|
71
|
+
return "";
|
|
72
|
+
ctx.visitedFiles.add(sourceFile.fileName);
|
|
73
|
+
if (sourceFile.isDeclarationFile)
|
|
74
|
+
return "";
|
|
75
|
+
if (program.isSourceFileDefaultLibrary(sourceFile) || program.isSourceFileFromExternalLibrary(sourceFile))
|
|
76
|
+
return "";
|
|
77
|
+
const prevFile = ctx.currentFilePath;
|
|
78
|
+
ctx.currentFilePath = sourceFile.fileName;
|
|
79
|
+
ctx.currentFolder = path.dirname(sourceFile.fileName);
|
|
80
|
+
ctx.namedImports[sourceFile.fileName] = {};
|
|
81
|
+
ctx.namespaceImports[sourceFile.fileName] = new Set;
|
|
82
|
+
sourceFile.forEachChild((node) => {
|
|
83
|
+
const result = NodeHandler.handle(node);
|
|
84
|
+
if (!result)
|
|
85
|
+
return;
|
|
86
|
+
ctx.output.push(result);
|
|
87
|
+
});
|
|
88
|
+
ctx.currentFilePath = prevFile;
|
|
89
|
+
ctx.currentFolder = path.dirname(prevFile);
|
|
90
|
+
return "";
|
|
91
|
+
});
|
|
50
92
|
|
|
51
93
|
// src/parser.ts
|
|
52
94
|
import ts2 from "typescript";
|
|
@@ -57,7 +99,7 @@ var parser_default = parseCode;
|
|
|
57
99
|
|
|
58
100
|
// src/utils.ts
|
|
59
101
|
import fs from "node:fs";
|
|
60
|
-
import
|
|
102
|
+
import path2 from "node:path";
|
|
61
103
|
import ts3 from "typescript";
|
|
62
104
|
|
|
63
105
|
// src/replaceKeywords.ts
|
|
@@ -127,7 +169,6 @@ var apiNameMap = {
|
|
|
127
169
|
"GreyHack.File.setGroup": "set_group",
|
|
128
170
|
"GreyHack.File.setOwner": "set_owner",
|
|
129
171
|
"GreyHack.activeUser": "active_user",
|
|
130
|
-
"GreyHack.clearScreen": "clear_screen",
|
|
131
172
|
"GreyHack.commandInfo": "command_info",
|
|
132
173
|
"GreyHack.currentDate": "current_date",
|
|
133
174
|
"GreyHack.currentPath": "current_path",
|
|
@@ -218,26 +259,11 @@ var apiNameMap = {
|
|
|
218
259
|
"Object.size": "len",
|
|
219
260
|
"Array.length": "len",
|
|
220
261
|
"Array.shift": "pull",
|
|
221
|
-
"Array.push": "push_many"
|
|
262
|
+
"Array.push": "push_many",
|
|
263
|
+
"Map.size": "data.len",
|
|
264
|
+
"Set.size": "data.len"
|
|
222
265
|
};
|
|
223
266
|
var propertyAccessReplacements = {
|
|
224
|
-
"Math.PI": "pi",
|
|
225
|
-
"Math.abs": "abs",
|
|
226
|
-
"Math.acos": "acos",
|
|
227
|
-
"Math.asin": "asin",
|
|
228
|
-
"Math.atan": "atan",
|
|
229
|
-
"Math.ceil": "ceil",
|
|
230
|
-
"Math.floor": "floor",
|
|
231
|
-
"Math.cos": "cos",
|
|
232
|
-
"Math.sin": "sin",
|
|
233
|
-
"Math.tan": "tan",
|
|
234
|
-
"Math.sqrt": "sqrt",
|
|
235
|
-
"Math.sign": "sign",
|
|
236
|
-
"Math.round": "round",
|
|
237
|
-
"Math.random": "rnd",
|
|
238
|
-
"Math.log": "log",
|
|
239
|
-
"console.log": "print",
|
|
240
|
-
"console.clear": "clear_screen",
|
|
241
267
|
"String.prototype": "string",
|
|
242
268
|
"Number.prototype": "number",
|
|
243
269
|
"Boolean.prototype": "number",
|
|
@@ -263,6 +289,7 @@ var knownOperators = new Set([
|
|
|
263
289
|
"!==",
|
|
264
290
|
"??",
|
|
265
291
|
"??=",
|
|
292
|
+
"||=",
|
|
266
293
|
"in",
|
|
267
294
|
"||",
|
|
268
295
|
"<",
|
|
@@ -287,13 +314,13 @@ function getOperatorToken(node) {
|
|
|
287
314
|
return null;
|
|
288
315
|
if (!knownOperators.has(operatorToken))
|
|
289
316
|
throw `Can't handle operator '${operatorToken}' yet`;
|
|
290
|
-
if (operatorToken
|
|
317
|
+
if (operatorToken === "||")
|
|
291
318
|
operatorToken = "or";
|
|
292
|
-
else if (operatorToken
|
|
319
|
+
else if (operatorToken === "&&")
|
|
293
320
|
operatorToken = "and";
|
|
294
|
-
else if (operatorToken
|
|
321
|
+
else if (operatorToken === "===")
|
|
295
322
|
operatorToken = "==";
|
|
296
|
-
else if (operatorToken
|
|
323
|
+
else if (operatorToken === "!==")
|
|
297
324
|
operatorToken = "!=";
|
|
298
325
|
return operatorToken;
|
|
299
326
|
}
|
|
@@ -315,7 +342,7 @@ function nodeIsFunctionReference(node, type) {
|
|
|
315
342
|
function asRef(value) {
|
|
316
343
|
if (value[0] === "@")
|
|
317
344
|
return value;
|
|
318
|
-
return
|
|
345
|
+
return `@${value}`;
|
|
319
346
|
}
|
|
320
347
|
function getSourceFiles(absPath) {
|
|
321
348
|
if (!fs.existsSync(absPath))
|
|
@@ -326,7 +353,7 @@ function getSourceFiles(absPath) {
|
|
|
326
353
|
const file = filePaths.shift();
|
|
327
354
|
const stat = fs.statSync(file);
|
|
328
355
|
if (stat.isDirectory()) {
|
|
329
|
-
filePaths.push(...fs.readdirSync(file).map((name) =>
|
|
356
|
+
filePaths.push(...fs.readdirSync(file).map((name) => path2.join(file, name)));
|
|
330
357
|
continue;
|
|
331
358
|
}
|
|
332
359
|
const existing = program.getSourceFile(file);
|
|
@@ -340,20 +367,16 @@ function getSourceFiles(absPath) {
|
|
|
340
367
|
return output;
|
|
341
368
|
}
|
|
342
369
|
function replaceIdentifier(original, type, propertyName) {
|
|
343
|
-
let symbol;
|
|
344
370
|
if (type.isUnion()) {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
}
|
|
351
|
-
} else {
|
|
352
|
-
symbol = type.types.find((t) => t.flags !== ts3.TypeFlags.Undefined && t.symbol)?.symbol;
|
|
371
|
+
let result = original;
|
|
372
|
+
for (const t of type.types) {
|
|
373
|
+
result = replaceIdentifier(original, t, propertyName);
|
|
374
|
+
if (result !== original)
|
|
375
|
+
return result;
|
|
353
376
|
}
|
|
354
|
-
|
|
355
|
-
symbol = propertyName ? type.getProperty(propertyName) : type.symbol;
|
|
377
|
+
return result;
|
|
356
378
|
}
|
|
379
|
+
const symbol = propertyName ? type.getProperty(propertyName) : type.symbol;
|
|
357
380
|
if (!symbol)
|
|
358
381
|
return original;
|
|
359
382
|
const symbolFullName = checker.getFullyQualifiedName(symbol);
|
|
@@ -362,7 +385,7 @@ function replaceIdentifier(original, type, propertyName) {
|
|
|
362
385
|
return original;
|
|
363
386
|
const dotIndex = symbolFullName.lastIndexOf(".");
|
|
364
387
|
const strToReplace = dotIndex !== null ? symbolFullName.slice(dotIndex + 1) : symbolFullName;
|
|
365
|
-
if (strToReplace
|
|
388
|
+
if (strToReplace !== original)
|
|
366
389
|
return original;
|
|
367
390
|
return replaceValue;
|
|
368
391
|
}
|
|
@@ -376,8 +399,8 @@ function replacePropertyAccess(original, symbol) {
|
|
|
376
399
|
return replaceValue;
|
|
377
400
|
}
|
|
378
401
|
function findProjectRoot(dir, fileToSearch = "package.json") {
|
|
379
|
-
while (!fs.existsSync(
|
|
380
|
-
const parent =
|
|
402
|
+
while (!fs.existsSync(path2.join(dir, fileToSearch))) {
|
|
403
|
+
const parent = path2.dirname(dir);
|
|
381
404
|
if (parent === dir)
|
|
382
405
|
throw new Error(`No ${fileToSearch} found`);
|
|
383
406
|
dir = parent;
|
|
@@ -434,7 +457,7 @@ NodeHandler.register(ts5.SyntaxKind.ClassDeclaration, (node) => {
|
|
|
434
457
|
const name = node.name ? node.name.text : "anon";
|
|
435
458
|
const extensions = node.heritageClauses?.filter((h) => h.token === ts5.SyntaxKind.ExtendsKeyword);
|
|
436
459
|
let output = `${name} = {}`;
|
|
437
|
-
if (extensions
|
|
460
|
+
if (extensions?.length && extensions[0].types.length)
|
|
438
461
|
output = `${name} = new ${NodeHandler.handle(extensions[0].types[0].expression)}`;
|
|
439
462
|
const declaredNames = new Set;
|
|
440
463
|
let hasConstructor = false;
|
|
@@ -520,7 +543,7 @@ end function`;
|
|
|
520
543
|
import ts7 from "typescript";
|
|
521
544
|
|
|
522
545
|
// src/call_transformers/callTransformer.ts
|
|
523
|
-
import
|
|
546
|
+
import path3 from "node:path";
|
|
524
547
|
import ts6 from "typescript";
|
|
525
548
|
class CallTransformer {
|
|
526
549
|
static handlers = new Map;
|
|
@@ -529,10 +552,23 @@ class CallTransformer {
|
|
|
529
552
|
throw `Handler for '${symbolFullName}' was already registered`;
|
|
530
553
|
this.handlers.set(symbolFullName, handler);
|
|
531
554
|
}
|
|
532
|
-
static handle(
|
|
555
|
+
static handle(type, functionName, callArgs, node, ctx) {
|
|
556
|
+
let symbolFullName = "";
|
|
557
|
+
if (type.isUnion()) {
|
|
558
|
+
let result = null;
|
|
559
|
+
for (const t of type.types) {
|
|
560
|
+
const res = CallTransformer.handle(t, functionName, callArgs, node, ctx);
|
|
561
|
+
result ??= res;
|
|
562
|
+
}
|
|
563
|
+
return result;
|
|
564
|
+
} else if (type.symbol) {
|
|
565
|
+
symbolFullName = checker.getFullyQualifiedName(type.symbol);
|
|
566
|
+
}
|
|
567
|
+
if (!symbolFullName || symbolFullName.startsWith("__")) {
|
|
568
|
+
const symbol = checker.getSymbolAtLocation(node.expression);
|
|
569
|
+
symbolFullName = symbol ? checker.getFullyQualifiedName(symbol) : "";
|
|
570
|
+
}
|
|
533
571
|
if (symbolFullName in extensionFunctions) {
|
|
534
|
-
if (symbolFullName.startsWith("Math"))
|
|
535
|
-
utilitiesToInsert.set("create_math", "Math = {}");
|
|
536
572
|
utilitiesToInsert.set(symbolFullName, extensionFunctions[symbolFullName]);
|
|
537
573
|
const params = callArgs.length ? `(${callArgs.join(",")})` : "";
|
|
538
574
|
return `${functionName}${params}`;
|
|
@@ -543,41 +579,37 @@ class CallTransformer {
|
|
|
543
579
|
return handler(functionName, callArgs, node, ctx);
|
|
544
580
|
}
|
|
545
581
|
}
|
|
546
|
-
CallTransformer.register("Number.toString", (name) => {
|
|
547
|
-
const number = name.slice(0, name.lastIndexOf("."));
|
|
548
|
-
return `str(${number})`;
|
|
549
|
-
});
|
|
550
582
|
CallTransformer.register("Function.toString", (name) => {
|
|
551
583
|
const func = name.slice(0, name.lastIndexOf("."));
|
|
552
584
|
return `str(@${func})`;
|
|
553
585
|
});
|
|
554
|
-
CallTransformer.register("GreyHack.include", (
|
|
586
|
+
CallTransformer.register("GreyHack.include", (_name, _args, node, ctx) => {
|
|
555
587
|
if (!node.arguments.length)
|
|
556
588
|
return "";
|
|
557
589
|
const fileArg = node.arguments[0];
|
|
558
590
|
if (!ts6.isStringLiteralLike(fileArg))
|
|
559
591
|
throw "You can't include variables";
|
|
560
|
-
const absPath =
|
|
592
|
+
const absPath = path3.resolve(ctx.currentFolder, fileArg.text);
|
|
561
593
|
const sources = getSourceFiles(absPath);
|
|
562
594
|
for (const source of sources) {
|
|
563
|
-
|
|
595
|
+
NodeHandler.handle(source);
|
|
564
596
|
}
|
|
565
597
|
return "";
|
|
566
598
|
});
|
|
567
|
-
CallTransformer.register("GreyHack.isType", (
|
|
599
|
+
CallTransformer.register("GreyHack.isType", (_name, args) => {
|
|
568
600
|
return callUtilFunction("is_type", args.join(","));
|
|
569
601
|
});
|
|
570
|
-
CallTransformer.register("Boolean", (
|
|
602
|
+
CallTransformer.register("Boolean", (_name, args) => {
|
|
571
603
|
if (!args.length)
|
|
572
604
|
return "0";
|
|
573
605
|
return `(not (not ${args[0]}))`;
|
|
574
606
|
});
|
|
575
|
-
CallTransformer.register("Number", (
|
|
607
|
+
CallTransformer.register("Number", (_name, args) => {
|
|
576
608
|
if (!args.length)
|
|
577
609
|
return "0";
|
|
578
610
|
return `str(${args[0]}).val`;
|
|
579
611
|
});
|
|
580
|
-
CallTransformer.register("String", (
|
|
612
|
+
CallTransformer.register("String", (_name, args) => {
|
|
581
613
|
if (!args.length)
|
|
582
614
|
return "";
|
|
583
615
|
return `str(${args[0]})`;
|
|
@@ -670,17 +702,12 @@ function handleCallArgs(callNode, ctx) {
|
|
|
670
702
|
}
|
|
671
703
|
NodeHandler.register(ts7.SyntaxKind.CallExpression, (node, ctx) => {
|
|
672
704
|
const args = handleCallArgs(node, ctx);
|
|
673
|
-
|
|
705
|
+
const name = NodeHandler.handle(node.expression);
|
|
674
706
|
const type = checker.getTypeAtLocation(node.expression);
|
|
675
|
-
|
|
676
|
-
if (!symbolFullName || symbolFullName.startsWith("__")) {
|
|
677
|
-
const symbol = checker.getSymbolAtLocation(node.expression);
|
|
678
|
-
symbolFullName = symbol ? checker.getFullyQualifiedName(symbol) : "";
|
|
679
|
-
}
|
|
680
|
-
const transformed = CallTransformer.handle(symbolFullName, name, args, node, ctx);
|
|
707
|
+
const transformed = CallTransformer.handle(type, name, args, node, ctx);
|
|
681
708
|
if (transformed !== null)
|
|
682
709
|
return transformed;
|
|
683
|
-
if (!args.length)
|
|
710
|
+
if (!args.length && !ts7.isParenthesizedExpression(node.expression))
|
|
684
711
|
return name;
|
|
685
712
|
return `${name}(${args.join(", ")})`;
|
|
686
713
|
});
|
|
@@ -704,7 +731,7 @@ function shouldHaveOuterPrefix(node, operator) {
|
|
|
704
731
|
const leftSymbol = checker.getSymbolAtLocation(node.left);
|
|
705
732
|
if (!leftSymbol?.valueDeclaration)
|
|
706
733
|
return false;
|
|
707
|
-
return leftSymbol.valueDeclaration.
|
|
734
|
+
return leftSymbol.valueDeclaration.end < functionAncestor.pos || leftSymbol.valueDeclaration.pos > functionAncestor.end;
|
|
708
735
|
}
|
|
709
736
|
function isAssignmentChain(node, operator) {
|
|
710
737
|
if (!assignmentOperators.has(operator))
|
|
@@ -715,7 +742,7 @@ function isAssignmentChain(node, operator) {
|
|
|
715
742
|
return true;
|
|
716
743
|
return false;
|
|
717
744
|
}
|
|
718
|
-
NodeHandler.register(ts7.SyntaxKind.BinaryExpression, (node) => {
|
|
745
|
+
NodeHandler.register(ts7.SyntaxKind.BinaryExpression, (node, ctx) => {
|
|
719
746
|
let operatorToken = getOperatorToken(node.operatorToken) || node.operatorToken.getText();
|
|
720
747
|
if (isAssignmentChain(node, operatorToken))
|
|
721
748
|
throw `Assignment chaining is not supported`;
|
|
@@ -740,7 +767,7 @@ NodeHandler.register(ts7.SyntaxKind.BinaryExpression, (node) => {
|
|
|
740
767
|
}
|
|
741
768
|
let left = NodeHandler.handle(node.left);
|
|
742
769
|
if (shouldHaveOuterPrefix(node, operatorToken))
|
|
743
|
-
left =
|
|
770
|
+
left = `outer.${left}`;
|
|
744
771
|
if (nodeIsFunctionReference(node.left))
|
|
745
772
|
left = asRef(left);
|
|
746
773
|
if (operatorToken === "or" && ts7.hasOnlyExpressionInitializer(node.parent)) {
|
|
@@ -752,7 +779,15 @@ NodeHandler.register(ts7.SyntaxKind.BinaryExpression, (node) => {
|
|
|
752
779
|
case "??":
|
|
753
780
|
return callUtilFunction("nullish_coalescing_op", left, right);
|
|
754
781
|
case "??=":
|
|
755
|
-
|
|
782
|
+
case "||=": {
|
|
783
|
+
const util = operatorToken === "??=" ? "nullish_coalescing_op" : "or_op";
|
|
784
|
+
ctx.forceSafeAccess = true;
|
|
785
|
+
let leftSafe = NodeHandler.handle(node.left);
|
|
786
|
+
ctx.forceSafeAccess = false;
|
|
787
|
+
if (nodeIsFunctionReference(node.left))
|
|
788
|
+
leftSafe = asRef(leftSafe);
|
|
789
|
+
return `${left} = ${callUtilFunction(util, leftSafe, right)}`;
|
|
790
|
+
}
|
|
756
791
|
case "in":
|
|
757
792
|
return `${right}.hasIndex(${left})`;
|
|
758
793
|
case "&":
|
|
@@ -906,7 +941,7 @@ NodeHandler.register(ts8.SyntaxKind.Block, (node) => {
|
|
|
906
941
|
const output = node.statements.map((val) => {
|
|
907
942
|
let statement = NodeHandler.handle(val);
|
|
908
943
|
statement = statement.split(`
|
|
909
|
-
`).filter((s) => !!s).map((line) =>
|
|
944
|
+
`).filter((s) => !!s).map((line) => ` ${line}`).join(`
|
|
910
945
|
`);
|
|
911
946
|
return statement;
|
|
912
947
|
}).filter((s) => !!s).join(`
|
|
@@ -928,7 +963,13 @@ NodeHandler.register(ts8.SyntaxKind.ArrowFunction, (node) => {
|
|
|
928
963
|
const params = node.parameters.map((param) => NodeHandler.handle(param));
|
|
929
964
|
const body = ts8.isBlock(node.body) ? NodeHandler.handle(node.body) : ` return ${NodeHandler.handle(node.body)}`;
|
|
930
965
|
if (ts8.isCallOrNewExpression(node.parent) || ts8.isParenthesizedExpression(node.parent)) {
|
|
931
|
-
|
|
966
|
+
const mainNode = ts8.findAncestor(node.parent, (n) => n.parent && (ts8.isBlock(n.parent) || ts8.isSourceFile(n.parent)));
|
|
967
|
+
if (!mainNode) {
|
|
968
|
+
return `@${createAnonFunction(body, params).name}`;
|
|
969
|
+
}
|
|
970
|
+
const anon = createAnonFunction(body, params, false);
|
|
971
|
+
NodeHandler.addExtraOutput(mainNode, anon.str, null);
|
|
972
|
+
return `@${anon.name}`;
|
|
932
973
|
}
|
|
933
974
|
if (ts8.hasOnlyExpressionInitializer(node.parent) || ts8.isBinaryExpression(node.parent) || ts8.isReturnStatement(node.parent)) {
|
|
934
975
|
return `function(${params.join(", ")})
|
|
@@ -949,20 +990,15 @@ NodeHandler.register(ts9.SyntaxKind.Identifier, (node, ctx) => {
|
|
|
949
990
|
let name = node.text;
|
|
950
991
|
if (name === "undefined")
|
|
951
992
|
return "null";
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
if (name != original)
|
|
957
|
-
break;
|
|
958
|
-
}
|
|
959
|
-
} else {
|
|
960
|
-
name = replaceIdentifier(node.text, type);
|
|
993
|
+
name = replaceIdentifier(node.text, type);
|
|
994
|
+
const symbolFullName = type.symbol ? checker.getFullyQualifiedName(type.symbol) : "";
|
|
995
|
+
if (symbolFullName in globalObjects) {
|
|
996
|
+
utilitiesToInsert.set(symbolFullName, globalObjects[symbolFullName]);
|
|
961
997
|
}
|
|
962
|
-
if (ctx.namedImports[ctx.currentFilePath]
|
|
998
|
+
if (ctx.namedImports[ctx.currentFilePath] && Object.hasOwn(ctx.namedImports[ctx.currentFilePath], name)) {
|
|
963
999
|
name = ctx.namedImports[ctx.currentFilePath][name];
|
|
964
1000
|
}
|
|
965
|
-
if (ts9.isCallOrNewExpression(node.parent) && node
|
|
1001
|
+
if (ts9.isCallOrNewExpression(node.parent) && node !== node.parent.expression) {
|
|
966
1002
|
if (nodeIsFunctionReference(node, type))
|
|
967
1003
|
name = asRef(name);
|
|
968
1004
|
}
|
|
@@ -1009,35 +1045,23 @@ NodeHandler.register(ts9.SyntaxKind.RegularExpressionLiteral, (node) => {
|
|
|
1009
1045
|
});
|
|
1010
1046
|
|
|
1011
1047
|
// src/visitors/imports.ts
|
|
1012
|
-
import
|
|
1048
|
+
import path4 from "node:path";
|
|
1013
1049
|
import ts10 from "typescript";
|
|
1014
|
-
function importFile(filePath, ctx
|
|
1015
|
-
let srcPath =
|
|
1016
|
-
if (!
|
|
1050
|
+
function importFile(filePath, ctx) {
|
|
1051
|
+
let srcPath = path4.resolve(ctx.currentFolder, filePath);
|
|
1052
|
+
if (!path4.extname(srcPath))
|
|
1017
1053
|
srcPath += ".ts";
|
|
1018
1054
|
const source = program.getSourceFile(srcPath);
|
|
1019
1055
|
if (!source) {
|
|
1020
1056
|
console.error(`Failed to find source ${srcPath}`);
|
|
1021
1057
|
return "";
|
|
1022
1058
|
}
|
|
1023
|
-
return
|
|
1059
|
+
return NodeHandler.handle(source);
|
|
1024
1060
|
}
|
|
1025
1061
|
NodeHandler.register(ts10.SyntaxKind.ImportDeclaration, (node, ctx) => {
|
|
1026
1062
|
if (!node.importClause) {
|
|
1027
1063
|
const moduleName = node.moduleSpecifier.text;
|
|
1028
|
-
|
|
1029
|
-
if (!transpiledFile)
|
|
1030
|
-
return "";
|
|
1031
|
-
const rndName = "func_" + (Date.now() * Math.random()).toString().slice(0, 6);
|
|
1032
|
-
return [
|
|
1033
|
-
`${rndName} = function`,
|
|
1034
|
-
transpiledFile.split(`
|
|
1035
|
-
`).map((line) => "\t" + line).join(`
|
|
1036
|
-
`),
|
|
1037
|
-
"end function",
|
|
1038
|
-
`${rndName}()`
|
|
1039
|
-
].join(`
|
|
1040
|
-
`);
|
|
1064
|
+
return importFile(moduleName, ctx);
|
|
1041
1065
|
}
|
|
1042
1066
|
if (node.importClause.phaseModifier)
|
|
1043
1067
|
return "";
|
|
@@ -1061,37 +1085,38 @@ NodeHandler.register(ts10.SyntaxKind.ImportDeclaration, (node, ctx) => {
|
|
|
1061
1085
|
|
|
1062
1086
|
// src/visitors/objects.ts
|
|
1063
1087
|
import ts11 from "typescript";
|
|
1064
|
-
function shouldGetSafely(node) {
|
|
1088
|
+
function shouldGetSafely(node, ctx) {
|
|
1065
1089
|
if (ts11.isNonNullExpression(node.parent))
|
|
1066
1090
|
return false;
|
|
1091
|
+
const callParent = ts11.findAncestor(node, (n) => n.parent && ts11.isCallExpression(n.parent) && n.parent.expression === n);
|
|
1092
|
+
if (callParent)
|
|
1093
|
+
return false;
|
|
1094
|
+
if (ctx.forceSafeAccess)
|
|
1095
|
+
return true;
|
|
1067
1096
|
if (valueIsBeingAssignedToNode(node))
|
|
1068
1097
|
return false;
|
|
1069
|
-
if (ts11.
|
|
1070
|
-
const rightType = checker.getTypeAtLocation(node.name);
|
|
1071
|
-
if (!rightType.isUnion())
|
|
1072
|
-
return !!node.questionDotToken;
|
|
1073
|
-
const hasUndefined = rightType.types.some((t) => t.flags === ts11.TypeFlags.Undefined);
|
|
1074
|
-
if (!hasUndefined)
|
|
1075
|
-
return false;
|
|
1076
|
-
if (!ts11.isCallExpression(node.parent))
|
|
1077
|
-
return true;
|
|
1078
|
-
if (node.parent.arguments.length)
|
|
1079
|
-
return false;
|
|
1080
|
-
} else {
|
|
1098
|
+
if (ts11.isElementAccessExpression(node)) {
|
|
1081
1099
|
if (ts11.isNumericLiteral(node.argumentExpression) && !node.questionDotToken)
|
|
1082
1100
|
return false;
|
|
1101
|
+
return true;
|
|
1083
1102
|
}
|
|
1103
|
+
const type = checker.getTypeAtLocation(node);
|
|
1104
|
+
if (!type.isUnion())
|
|
1105
|
+
return !!node.questionDotToken;
|
|
1106
|
+
const hasNullish = type.types.some((t) => t.flags === ts11.TypeFlags.Undefined || ts11.TypeFlags.Null);
|
|
1107
|
+
if (!hasNullish)
|
|
1108
|
+
return false;
|
|
1084
1109
|
return true;
|
|
1085
1110
|
}
|
|
1086
1111
|
NodeHandler.register(ts11.SyntaxKind.PropertyAccessExpression, (node, ctx) => {
|
|
1087
1112
|
const left = NodeHandler.handle(node.expression);
|
|
1088
1113
|
let right = NodeHandler.handle(node.name);
|
|
1089
1114
|
right = replaceIdentifier(right, checker.getTypeAtLocation(node.expression), right);
|
|
1090
|
-
const nodeSymbol = checker.getSymbolAtLocation(node);
|
|
1091
1115
|
if (ctx.namespaceImports[ctx.currentFilePath]?.has(left))
|
|
1092
1116
|
return right;
|
|
1093
|
-
if (shouldGetSafely(node))
|
|
1117
|
+
if (shouldGetSafely(node, ctx))
|
|
1094
1118
|
return callUtilFunction("get_property", left, `"${right}"`);
|
|
1119
|
+
const nodeSymbol = checker.getSymbolAtLocation(node);
|
|
1095
1120
|
let output = `${left}.${right}`;
|
|
1096
1121
|
output = replacePropertyAccess(output, nodeSymbol);
|
|
1097
1122
|
if (nodeIsFunctionReference(node))
|
|
@@ -1107,7 +1132,7 @@ NodeHandler.register(ts11.SyntaxKind.ElementAccessExpression, (node, ctx) => {
|
|
|
1107
1132
|
} else {
|
|
1108
1133
|
right = NodeHandler.handle(node.argumentExpression);
|
|
1109
1134
|
}
|
|
1110
|
-
if (shouldGetSafely(node)) {
|
|
1135
|
+
if (shouldGetSafely(node, ctx)) {
|
|
1111
1136
|
return callUtilFunction("get_property", left, `${right}`);
|
|
1112
1137
|
}
|
|
1113
1138
|
return `${left}[${right}]`;
|
|
@@ -1124,7 +1149,7 @@ function handleObjectLiteralExpression(node, ctx, currObj, outObjects, funcs) {
|
|
|
1124
1149
|
function pushObj() {
|
|
1125
1150
|
if (!currObj?.length)
|
|
1126
1151
|
return "";
|
|
1127
|
-
const res = currObj.filter((s) => s
|
|
1152
|
+
const res = currObj.filter((s) => s !== "").join(",");
|
|
1128
1153
|
if (res) {
|
|
1129
1154
|
outObjects?.push(`{ ${res} }`);
|
|
1130
1155
|
}
|
|
@@ -1170,8 +1195,8 @@ function handleObjectLiteralExpression(node, ctx, currObj, outObjects, funcs) {
|
|
|
1170
1195
|
throw "You can't have method declarations inside an object that is not being assigned to a variable";
|
|
1171
1196
|
}
|
|
1172
1197
|
output += `
|
|
1173
|
-
|
|
1174
|
-
`)
|
|
1198
|
+
${funcs.map((func) => `${objectName}.${func}`).join(`
|
|
1199
|
+
`)}`;
|
|
1175
1200
|
}
|
|
1176
1201
|
return output;
|
|
1177
1202
|
}
|
|
@@ -1209,7 +1234,7 @@ NodeHandler.register(ts12.SyntaxKind.ForStatement, (node) => {
|
|
|
1209
1234
|
].join(`
|
|
1210
1235
|
`);
|
|
1211
1236
|
}
|
|
1212
|
-
const incrementedStateVarName =
|
|
1237
|
+
const incrementedStateVarName = `state_${(Date.now() * Math.random()).toFixed(0).slice(0, 6)}`;
|
|
1213
1238
|
const output = [
|
|
1214
1239
|
`${incrementedStateVarName} = 1`,
|
|
1215
1240
|
`${initializer}`,
|
|
@@ -1290,7 +1315,7 @@ else
|
|
|
1290
1315
|
end if`;
|
|
1291
1316
|
return output;
|
|
1292
1317
|
});
|
|
1293
|
-
NodeHandler.register(ts12.SyntaxKind.WhileStatement, (node
|
|
1318
|
+
NodeHandler.register(ts12.SyntaxKind.WhileStatement, (node) => {
|
|
1294
1319
|
const expression = NodeHandler.handle(node.expression);
|
|
1295
1320
|
const labelIf = ts12.isLabeledStatement(node.parent) ? ` if ${node.parent.label.text}Broke then break` : "";
|
|
1296
1321
|
return [
|
|
@@ -1301,7 +1326,7 @@ NodeHandler.register(ts12.SyntaxKind.WhileStatement, (node, ctx) => {
|
|
|
1301
1326
|
].join(`
|
|
1302
1327
|
`);
|
|
1303
1328
|
});
|
|
1304
|
-
NodeHandler.register(ts12.SyntaxKind.DoStatement, (node
|
|
1329
|
+
NodeHandler.register(ts12.SyntaxKind.DoStatement, (node) => {
|
|
1305
1330
|
const expression = NodeHandler.handle(node.expression);
|
|
1306
1331
|
const labelIf = ts12.isLabeledStatement(node.parent) ? ` if ${node.parent.label.text}Broke then break` : "";
|
|
1307
1332
|
return [
|
|
@@ -1314,7 +1339,7 @@ NodeHandler.register(ts12.SyntaxKind.DoStatement, (node, ctx) => {
|
|
|
1314
1339
|
].join(`
|
|
1315
1340
|
`);
|
|
1316
1341
|
});
|
|
1317
|
-
NodeHandler.register(ts12.SyntaxKind.ContinueStatement, (
|
|
1342
|
+
NodeHandler.register(ts12.SyntaxKind.ContinueStatement, (_node) => {
|
|
1318
1343
|
return "continue";
|
|
1319
1344
|
});
|
|
1320
1345
|
NodeHandler.register(ts12.SyntaxKind.BreakStatement, (node) => {
|
|
@@ -1342,7 +1367,7 @@ ${NodeHandler.handle(node.statement)}`;
|
|
|
1342
1367
|
|
|
1343
1368
|
// src/visitors/variables.ts
|
|
1344
1369
|
import ts13 from "typescript";
|
|
1345
|
-
function handleVariableDeclaration(node
|
|
1370
|
+
function handleVariableDeclaration(node) {
|
|
1346
1371
|
const left = NodeHandler.handle(node.name);
|
|
1347
1372
|
const initializerType = node.initializer ? checker.getTypeAtLocation(node.initializer) : undefined;
|
|
1348
1373
|
if (ts13.isPropertyDeclaration(node) && initializerType?.flags === ts13.TypeFlags.Object && !node.modifiers?.some((mod) => mod.kind === ts13.SyntaxKind.StaticKeyword) && !ts13.isFunctionLike(node.initializer)) {
|
|
@@ -1350,16 +1375,16 @@ function handleVariableDeclaration(node, ctx) {
|
|
|
1350
1375
|
Initialize them in the constructor instead`);
|
|
1351
1376
|
}
|
|
1352
1377
|
let right = node.initializer ? NodeHandler.handle(node.initializer) || "null" : "null";
|
|
1353
|
-
if (right
|
|
1378
|
+
if (right !== "null" && nodeIsFunctionReference(node.initializer, initializerType)) {
|
|
1354
1379
|
right = asRef(right);
|
|
1355
1380
|
}
|
|
1356
1381
|
return `${left} = ${right}`;
|
|
1357
1382
|
}
|
|
1358
|
-
NodeHandler.register(ts13.SyntaxKind.VariableDeclarationList, (node
|
|
1359
|
-
return node.declarations.map((decl) => handleVariableDeclaration(decl
|
|
1383
|
+
NodeHandler.register(ts13.SyntaxKind.VariableDeclarationList, (node) => {
|
|
1384
|
+
return node.declarations.map((decl) => handleVariableDeclaration(decl)).join(`
|
|
1360
1385
|
`);
|
|
1361
1386
|
});
|
|
1362
|
-
NodeHandler.register(ts13.SyntaxKind.VariableStatement, (node
|
|
1387
|
+
NodeHandler.register(ts13.SyntaxKind.VariableStatement, (node) => {
|
|
1363
1388
|
if (node.modifiers?.some((modifier) => modifier.kind === ts13.SyntaxKind.DeclareKeyword))
|
|
1364
1389
|
return "";
|
|
1365
1390
|
return NodeHandler.handle(node.declarationList);
|
|
@@ -1370,7 +1395,7 @@ NodeHandler.register(ts13.SyntaxKind.EnumDeclaration, (node) => {
|
|
|
1370
1395
|
const members = [];
|
|
1371
1396
|
function addMember(name, initializer) {
|
|
1372
1397
|
members.push(`${name}: ${initializer}`);
|
|
1373
|
-
if (isNaN(+initializer))
|
|
1398
|
+
if (Number.isNaN(+initializer))
|
|
1374
1399
|
return;
|
|
1375
1400
|
members.push(`${initializer}: ${name}`);
|
|
1376
1401
|
}
|
|
@@ -1392,51 +1417,42 @@ NodeHandler.register(ts13.SyntaxKind.EnumDeclaration, (node) => {
|
|
|
1392
1417
|
return `${node.name.text} = { ${members.join(", ")} }`;
|
|
1393
1418
|
});
|
|
1394
1419
|
|
|
1395
|
-
// src/call_transformers/array.ts
|
|
1396
|
-
CallTransformer.register("Array.slice", (name, args) => {
|
|
1397
|
-
return name.slice(0, name.lastIndexOf(".")) + `[${args[0] ?? ""}:${args[1] ?? ""}]`;
|
|
1398
|
-
});
|
|
1399
|
-
CallTransformer.register("Array.toString", (name) => {
|
|
1400
|
-
const arrayName = name.slice(0, name.lastIndexOf("."));
|
|
1401
|
-
return `str(${arrayName})`;
|
|
1402
|
-
});
|
|
1403
|
-
|
|
1404
1420
|
// src/call_transformers/object.ts
|
|
1405
|
-
CallTransformer.register("ObjectConstructor.hasOwn", (
|
|
1421
|
+
CallTransformer.register("ObjectConstructor.hasOwn", (_name, args) => {
|
|
1406
1422
|
if (args.length < 2)
|
|
1407
1423
|
throw "Invalid argument count";
|
|
1408
1424
|
return `${args[0]}.hasIndex(${args[1]})`;
|
|
1409
1425
|
});
|
|
1410
|
-
CallTransformer.register("ObjectConstructor.assign", (
|
|
1426
|
+
CallTransformer.register("ObjectConstructor.assign", (_name, args) => {
|
|
1411
1427
|
if (args.length < 2)
|
|
1412
1428
|
throw "Invalid argument count";
|
|
1413
1429
|
return callUtilFunction("assign_objects", args.join(","));
|
|
1414
1430
|
});
|
|
1415
|
-
CallTransformer.register("ObjectConstructor.keys", (
|
|
1431
|
+
CallTransformer.register("ObjectConstructor.keys", (_name, args) => {
|
|
1416
1432
|
return `${args[0]}.indexes`;
|
|
1417
1433
|
});
|
|
1418
|
-
CallTransformer.register("ObjectConstructor.values", (
|
|
1434
|
+
CallTransformer.register("ObjectConstructor.values", (_name, args) => {
|
|
1419
1435
|
return `${args[0]}.values`;
|
|
1420
1436
|
});
|
|
1421
|
-
CallTransformer.register("ObjectConstructor.sum", (
|
|
1437
|
+
CallTransformer.register("ObjectConstructor.sum", (_name, args) => {
|
|
1422
1438
|
return `${args[0]}.sum`;
|
|
1423
1439
|
});
|
|
1424
|
-
CallTransformer.register("ObjectConstructor.shuffle", (
|
|
1440
|
+
CallTransformer.register("ObjectConstructor.shuffle", (_name, args) => {
|
|
1425
1441
|
return `${args[0]}.shuffle`;
|
|
1426
1442
|
});
|
|
1427
|
-
CallTransformer.register("ObjectConstructor.replace", (
|
|
1443
|
+
CallTransformer.register("ObjectConstructor.replace", (_name, args) => {
|
|
1428
1444
|
return `${args[0]}.replace(${args.slice(1).join(",")})`;
|
|
1429
1445
|
});
|
|
1430
|
-
CallTransformer.register("ObjectConstructor.remove", (
|
|
1446
|
+
CallTransformer.register("ObjectConstructor.remove", (_name, args) => {
|
|
1431
1447
|
return `${args[0]}.remove(${args[1]})`;
|
|
1432
1448
|
});
|
|
1433
|
-
CallTransformer.register("ObjectConstructor.shift", (
|
|
1449
|
+
CallTransformer.register("ObjectConstructor.shift", (_name, args) => {
|
|
1434
1450
|
return `${args[0]}.pull`;
|
|
1435
1451
|
});
|
|
1436
|
-
CallTransformer.register("ObjectConstructor.size", (
|
|
1452
|
+
CallTransformer.register("ObjectConstructor.size", (_name, args) => {
|
|
1437
1453
|
return `${args[0]}.len`;
|
|
1438
1454
|
});
|
|
1439
|
-
CallTransformer.register("ObjectConstructor.indexOf", (
|
|
1455
|
+
CallTransformer.register("ObjectConstructor.indexOf", (_name, args) => {
|
|
1440
1456
|
return `${args[0]}.indexOf(${args[1]})`;
|
|
1441
1457
|
});
|
|
1442
1458
|
CallTransformer.register("Object.toString", (name) => {
|
|
@@ -1444,14 +1460,6 @@ CallTransformer.register("Object.toString", (name) => {
|
|
|
1444
1460
|
return `str(${objectName})`;
|
|
1445
1461
|
});
|
|
1446
1462
|
|
|
1447
|
-
// src/call_transformers/string.ts
|
|
1448
|
-
CallTransformer.register("String.slice", (name, args) => {
|
|
1449
|
-
return name.slice(0, name.lastIndexOf(".")) + `[${args[0] ?? ""}:${args[1] ?? ""}]`;
|
|
1450
|
-
});
|
|
1451
|
-
CallTransformer.register("String.toString", (name) => {
|
|
1452
|
-
return name.slice(0, name.lastIndexOf("."));
|
|
1453
|
-
});
|
|
1454
|
-
|
|
1455
1463
|
// src/transpiler.ts
|
|
1456
1464
|
var program;
|
|
1457
1465
|
var checker;
|
|
@@ -1594,6 +1602,12 @@ var extensionFunctions = {
|
|
|
1594
1602
|
"end function"
|
|
1595
1603
|
].join(`
|
|
1596
1604
|
`),
|
|
1605
|
+
"Array.toString": `list.toString = function
|
|
1606
|
+
return str(self)
|
|
1607
|
+
end function`,
|
|
1608
|
+
"Array.slice": `list.slice = function(a, b)
|
|
1609
|
+
return self[a:b]
|
|
1610
|
+
end function`,
|
|
1597
1611
|
"String.startsWith": [
|
|
1598
1612
|
"string.startsWith = function(search, pos = 0)",
|
|
1599
1613
|
"\tif pos < 0 then pos = 0",
|
|
@@ -1636,6 +1650,12 @@ var extensionFunctions = {
|
|
|
1636
1650
|
"end function"
|
|
1637
1651
|
].join(`
|
|
1638
1652
|
`),
|
|
1653
|
+
"String.toString": `string.toString = function
|
|
1654
|
+
return str(self)
|
|
1655
|
+
end function`,
|
|
1656
|
+
"String.slice": `string.slice = function(a, b)
|
|
1657
|
+
return self[a:b]
|
|
1658
|
+
end function`,
|
|
1639
1659
|
"Number.toFixed": [
|
|
1640
1660
|
"number.toFixed = function(digits = 0)",
|
|
1641
1661
|
"\tdigits = floor(digits)",
|
|
@@ -1657,23 +1677,120 @@ var extensionFunctions = {
|
|
|
1657
1677
|
"end function"
|
|
1658
1678
|
].join(`
|
|
1659
1679
|
`),
|
|
1660
|
-
"
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1680
|
+
"Number.toString": `number.toString = function
|
|
1681
|
+
return str(self)
|
|
1682
|
+
end function`,
|
|
1683
|
+
"Function.toString": `funcRef.toString = function
|
|
1684
|
+
return str(@self)
|
|
1685
|
+
end function`
|
|
1686
|
+
};
|
|
1687
|
+
var globalObjects = {
|
|
1688
|
+
MapConstructor: [
|
|
1689
|
+
"Map = {}",
|
|
1690
|
+
"Map.constructor = function(entries)",
|
|
1691
|
+
"\tself.data = {}",
|
|
1692
|
+
"\tif not entries then return self",
|
|
1693
|
+
"\tfor entry in entries",
|
|
1694
|
+
"\t\tself.data[entry[0]] = entry[1]",
|
|
1665
1695
|
"\tend for",
|
|
1666
|
-
"\treturn
|
|
1696
|
+
"\treturn self",
|
|
1697
|
+
"end function",
|
|
1698
|
+
"Map.clear = function",
|
|
1699
|
+
"\tfor key in self.data.indexes",
|
|
1700
|
+
"\t\tself.data.remove(@key)",
|
|
1701
|
+
"\tend for",
|
|
1702
|
+
"end function",
|
|
1703
|
+
"Map.delete = function(key)",
|
|
1704
|
+
"\treturn self.data.remove(key)",
|
|
1705
|
+
"end function",
|
|
1706
|
+
"Map.forEach = function(callback)",
|
|
1707
|
+
"\tfor item in self.data",
|
|
1708
|
+
"\t\tcallback(@item.value, @item.key, self)",
|
|
1709
|
+
"\tend for",
|
|
1710
|
+
"end function",
|
|
1711
|
+
"Map.get = function(key)",
|
|
1712
|
+
"\tif not self.data.hasIndex(@key) then retun null",
|
|
1713
|
+
"\treturn self.data[@key]",
|
|
1714
|
+
"end function",
|
|
1715
|
+
"Map.has = function(key)",
|
|
1716
|
+
"\treturn self.data.hasIndex(@key)",
|
|
1717
|
+
"end function",
|
|
1718
|
+
"Map.set = function(key, value)",
|
|
1719
|
+
"\tself.data[@key] = @value",
|
|
1720
|
+
"\treturn self",
|
|
1721
|
+
"end function",
|
|
1722
|
+
"Map.entries = function",
|
|
1723
|
+
"\tentries = []",
|
|
1724
|
+
"\tfor item in self.data",
|
|
1725
|
+
"\t\tentries.push([@item.key, @item.value])",
|
|
1726
|
+
"\tend for",
|
|
1727
|
+
"\treturn entries",
|
|
1728
|
+
"end function",
|
|
1729
|
+
"Map.keys = function",
|
|
1730
|
+
"\treturn self.data.indexes",
|
|
1731
|
+
"end function",
|
|
1732
|
+
"Map.values = function",
|
|
1733
|
+
"\treturn self.data.values",
|
|
1734
|
+
"end function"
|
|
1735
|
+
].join(`
|
|
1736
|
+
`),
|
|
1737
|
+
SetConstructor: [
|
|
1738
|
+
"Set = {}",
|
|
1739
|
+
"Set.constructor = function(values)",
|
|
1740
|
+
"\tself.data = {}",
|
|
1741
|
+
"\tif not values then return self",
|
|
1742
|
+
"\tfor v in values",
|
|
1743
|
+
"\t\tself.data[@v] = 1",
|
|
1744
|
+
"\tend for",
|
|
1745
|
+
"\treturn self",
|
|
1746
|
+
"end function",
|
|
1747
|
+
"Set.add = function(value)",
|
|
1748
|
+
"\tself.data[@value] = 1",
|
|
1749
|
+
"\treturn self",
|
|
1750
|
+
"end function",
|
|
1751
|
+
"Set.clear = function",
|
|
1752
|
+
"\tfor key in self.data.indexes",
|
|
1753
|
+
"\t\tself.data.remove(@key)",
|
|
1754
|
+
"\tend for",
|
|
1755
|
+
"end function",
|
|
1756
|
+
"Set.delete = function(key)",
|
|
1757
|
+
"\treturn self.data.remove(key)",
|
|
1758
|
+
"end function",
|
|
1759
|
+
"Set.forEach = function(callback)",
|
|
1760
|
+
"\tfor key in self.data.indexes",
|
|
1761
|
+
"\t\tcallback(@key, self)",
|
|
1762
|
+
"\tend for",
|
|
1763
|
+
"end function",
|
|
1764
|
+
"Set.has = function(key)",
|
|
1765
|
+
"\treturn self.data.hasIndex(@key)",
|
|
1766
|
+
"end function",
|
|
1767
|
+
"Set.values = function",
|
|
1768
|
+
"\treturn self.data.indexes",
|
|
1667
1769
|
"end function"
|
|
1668
1770
|
].join(`
|
|
1669
1771
|
`),
|
|
1670
|
-
|
|
1772
|
+
Math: [
|
|
1773
|
+
'Math = { "PI": @pi, "abs": @abs, "acos": @acos, "asin": @asin, "atan": @atan, "ceil": @ceil, "floor": @floor, "cos": @cos, "sin": @sin, "tan": @tan, "sqrt": @sqrt, "sign": @sign, "round": @round, "random": @rnd, "log": @log }',
|
|
1671
1774
|
"Math.max = function(numbers)",
|
|
1672
1775
|
"\tcurr_max = null",
|
|
1673
1776
|
"\tfor num in numbers",
|
|
1674
1777
|
"\t\tif curr_max == null or num > curr_max then curr_max = num",
|
|
1675
1778
|
"\tend for",
|
|
1676
1779
|
"\treturn curr_max",
|
|
1780
|
+
"end function",
|
|
1781
|
+
"Math.min = function(numbers)",
|
|
1782
|
+
"\tcurr_min = null",
|
|
1783
|
+
"\tfor num in numbers",
|
|
1784
|
+
"\t\tif curr_min == null or num < curr_min then curr_min = num",
|
|
1785
|
+
"\tend for",
|
|
1786
|
+
"\treturn curr_min",
|
|
1787
|
+
"end function"
|
|
1788
|
+
].join(`
|
|
1789
|
+
`),
|
|
1790
|
+
Console: [
|
|
1791
|
+
'console = { "clear": @clear_screen }',
|
|
1792
|
+
"console.log = function(data)",
|
|
1793
|
+
'\tprint(data.join(", "))',
|
|
1677
1794
|
"end function"
|
|
1678
1795
|
].join(`
|
|
1679
1796
|
`)
|
|
@@ -1743,50 +1860,57 @@ var utilFunctions = {
|
|
|
1743
1860
|
].join(`
|
|
1744
1861
|
`),
|
|
1745
1862
|
nullish_coalescing_op: `nullish_coalescing_op = function(left, right)
|
|
1746
|
-
if left == null then return @right
|
|
1863
|
+
if @left == null then return @right
|
|
1747
1864
|
return @left
|
|
1748
1865
|
end function`,
|
|
1749
1866
|
or_op: `or_op = function(left, right)
|
|
1750
|
-
if not left then return @right
|
|
1867
|
+
if not @left then return @right
|
|
1751
1868
|
return @left
|
|
1752
1869
|
end function`,
|
|
1753
1870
|
is_type: `is_type = function(value, type)
|
|
1754
|
-
return typeof(value) == type
|
|
1871
|
+
return typeof(@value) == type
|
|
1755
1872
|
end function`,
|
|
1756
1873
|
conditional_expr: `conditional_expr = function(cond, when_true, when_false)
|
|
1757
|
-
if cond then return when_true
|
|
1758
|
-
return when_false
|
|
1874
|
+
if cond then return @when_true
|
|
1875
|
+
return @when_false
|
|
1759
1876
|
end function`
|
|
1760
1877
|
};
|
|
1761
|
-
|
|
1878
|
+
var anonFunctionsCreated = 0;
|
|
1879
|
+
function createAnonFunction(body, params, insertToUtils = true) {
|
|
1762
1880
|
const defaultParams = new Array(3).fill(0).map((_, i) => `param${i}`);
|
|
1763
|
-
const nextName = `func_${
|
|
1881
|
+
const nextName = `func_${anonFunctionsCreated}`;
|
|
1764
1882
|
const paramString = Object.assign(defaultParams, params).join(",");
|
|
1765
1883
|
const result = `${nextName} = function(${paramString})
|
|
1766
1884
|
${body}
|
|
1767
1885
|
end function`;
|
|
1768
|
-
|
|
1886
|
+
anonFunctionsCreated++;
|
|
1887
|
+
if (insertToUtils)
|
|
1888
|
+
utilitiesToInsert.set(nextName, result);
|
|
1769
1889
|
return { name: nextName, str: result };
|
|
1770
1890
|
}
|
|
1771
|
-
function
|
|
1772
|
-
|
|
1773
|
-
currentFolder:
|
|
1774
|
-
currentFilePath:
|
|
1891
|
+
function createContext(currentFileName = "file.ts") {
|
|
1892
|
+
return {
|
|
1893
|
+
currentFolder: process.cwd(),
|
|
1894
|
+
currentFilePath: path5.resolve(process.cwd(), currentFileName),
|
|
1775
1895
|
namedImports: {},
|
|
1776
1896
|
namespaceImports: {},
|
|
1777
|
-
visitedFiles:
|
|
1778
|
-
output: []
|
|
1897
|
+
visitedFiles: new Set,
|
|
1898
|
+
output: [],
|
|
1899
|
+
extraOutput: new Map
|
|
1779
1900
|
};
|
|
1901
|
+
}
|
|
1902
|
+
function transpileProgram(entryFileRelativePath) {
|
|
1903
|
+
const ctx = createContext(entryFileRelativePath);
|
|
1780
1904
|
NodeHandler.transpileContext = ctx;
|
|
1781
|
-
ctx.currentFolder =
|
|
1905
|
+
ctx.currentFolder = path5.dirname(ctx.currentFilePath);
|
|
1782
1906
|
if (!fs2.existsSync(ctx.currentFilePath)) {
|
|
1783
1907
|
console.error(`Error: file '${ctx.currentFilePath}' doesn't exist`);
|
|
1784
1908
|
process.exit(1);
|
|
1785
1909
|
}
|
|
1786
1910
|
let start = Date.now();
|
|
1787
|
-
const tsconfigPath = findProjectRoot(process.cwd(), "tsconfig.json")
|
|
1911
|
+
const tsconfigPath = `${findProjectRoot(process.cwd(), "tsconfig.json")}/tsconfig.json`;
|
|
1788
1912
|
const res = ts14.readConfigFile(tsconfigPath, ts14.sys.readFile);
|
|
1789
|
-
const parsed = ts14.parseJsonConfigFileContent(res.config, ts14.sys,
|
|
1913
|
+
const parsed = ts14.parseJsonConfigFileContent(res.config, ts14.sys, path5.dirname(tsconfigPath));
|
|
1790
1914
|
if (!parsed.options.types)
|
|
1791
1915
|
parsed.options.types = [];
|
|
1792
1916
|
if (!parsed.options.types.includes("@grey-ts/types")) {
|
|
@@ -1805,7 +1929,7 @@ function transpileProgram(entryFileRelativePath) {
|
|
|
1805
1929
|
console.error(`Error: failed to find '${ctx.currentFilePath}' from the included sources`);
|
|
1806
1930
|
process.exit(1);
|
|
1807
1931
|
}
|
|
1808
|
-
|
|
1932
|
+
NodeHandler.handle(entry);
|
|
1809
1933
|
if (utilitiesToInsert.size) {
|
|
1810
1934
|
ctx.output.unshift(...utilitiesToInsert.values());
|
|
1811
1935
|
utilitiesToInsert.clear();
|
|
@@ -1813,34 +1937,6 @@ function transpileProgram(entryFileRelativePath) {
|
|
|
1813
1937
|
console.log(`Transpiling took ${Date.now() - start} ms`);
|
|
1814
1938
|
return ctx.output;
|
|
1815
1939
|
}
|
|
1816
|
-
function transpileSourceFile(sourceFile, ctx, returnResult) {
|
|
1817
|
-
if (ctx.visitedFiles[sourceFile.fileName])
|
|
1818
|
-
return "";
|
|
1819
|
-
ctx.visitedFiles[sourceFile.fileName] = true;
|
|
1820
|
-
if (sourceFile.isDeclarationFile)
|
|
1821
|
-
return "";
|
|
1822
|
-
if (program.isSourceFileDefaultLibrary(sourceFile) || program.isSourceFileFromExternalLibrary(sourceFile))
|
|
1823
|
-
return "";
|
|
1824
|
-
const prevFile = ctx.currentFilePath;
|
|
1825
|
-
ctx.currentFilePath = sourceFile.fileName;
|
|
1826
|
-
ctx.currentFolder = path4.dirname(sourceFile.fileName);
|
|
1827
|
-
ctx.namedImports[sourceFile.fileName] = {};
|
|
1828
|
-
ctx.namespaceImports[sourceFile.fileName] = new Set;
|
|
1829
|
-
const output = [];
|
|
1830
|
-
sourceFile.forEachChild((node) => {
|
|
1831
|
-
const result = NodeHandler.handle(node);
|
|
1832
|
-
if (!result)
|
|
1833
|
-
return;
|
|
1834
|
-
if (!returnResult)
|
|
1835
|
-
ctx.output.push(result);
|
|
1836
|
-
else
|
|
1837
|
-
output.push(result);
|
|
1838
|
-
});
|
|
1839
|
-
ctx.currentFilePath = prevFile;
|
|
1840
|
-
ctx.currentFolder = path4.dirname(prevFile);
|
|
1841
|
-
return output.join(`
|
|
1842
|
-
`);
|
|
1843
|
-
}
|
|
1844
1940
|
|
|
1845
1941
|
// src/index.ts
|
|
1846
1942
|
var noMoreFlags = false;
|
|
@@ -1872,7 +1968,7 @@ function createOutputFile(fileIndex, basename, content) {
|
|
|
1872
1968
|
if (fileIndex > 0)
|
|
1873
1969
|
basename = `${basename}-${fileIndex}`;
|
|
1874
1970
|
const outFileName = args.length > 1 ? args[1] : `${basename}.src`;
|
|
1875
|
-
const outFilePath =
|
|
1971
|
+
const outFilePath = path6.join(outDirPath, outFileName);
|
|
1876
1972
|
fs3.writeFileSync(outFilePath, content);
|
|
1877
1973
|
}
|
|
1878
1974
|
if (command === "transpile") {
|
|
@@ -1881,7 +1977,7 @@ if (command === "transpile") {
|
|
|
1881
1977
|
process.exit(2);
|
|
1882
1978
|
}
|
|
1883
1979
|
const entryFile = args[0];
|
|
1884
|
-
const basename =
|
|
1980
|
+
const basename = path6.basename(entryFile, ".ts");
|
|
1885
1981
|
const transpiledStatements = transpileProgram(entryFile);
|
|
1886
1982
|
if (flags.includes("--print") || flags.includes("-p")) {
|
|
1887
1983
|
console.log(transpiledStatements.join(`
|
|
@@ -1899,7 +1995,7 @@ if (command === "transpile") {
|
|
|
1899
1995
|
content = "";
|
|
1900
1996
|
continue;
|
|
1901
1997
|
}
|
|
1902
|
-
content += statement
|
|
1998
|
+
content += `${statement}
|
|
1903
1999
|
`;
|
|
1904
2000
|
}
|
|
1905
2001
|
if (content.length)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grey-ts/transpiler",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Transpiles TypeScript into GreyScript",
|
|
5
5
|
"author": "Okka",
|
|
6
6
|
"module": "src/index.ts",
|
|
@@ -31,14 +31,15 @@
|
|
|
31
31
|
],
|
|
32
32
|
"scripts": {
|
|
33
33
|
"prepare": "bun run build",
|
|
34
|
-
"build": "bun run scripts/build.ts"
|
|
34
|
+
"build": "bun test --only-failures && bun run scripts/build.ts"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@
|
|
38
|
-
"@grey-ts/types": "
|
|
37
|
+
"@biomejs/biome": "2.3.14",
|
|
38
|
+
"@grey-ts/types": "^3.0.0",
|
|
39
|
+
"@types/bun": "latest"
|
|
39
40
|
},
|
|
40
41
|
"peerDependencies": {
|
|
41
|
-
"typescript": "^5",
|
|
42
|
+
"typescript": "^5.9.3",
|
|
42
43
|
"@grey-ts/types": "^2.2.0"
|
|
43
44
|
}
|
|
44
45
|
}
|