@grey-ts/transpiler 1.2.0 → 1.4.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 +487 -430
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ class NodeHandler {
|
|
|
25
25
|
if (!handler) {
|
|
26
26
|
console.log(`Unsupported syntax ${ts.SyntaxKind[node.kind]} (kind ${node.kind}) was not transpiled: ${node.getText()}`);
|
|
27
27
|
this.printLineAndCol(node);
|
|
28
|
-
return "null";
|
|
28
|
+
return ts.isBlock(node.parent) || ts.isSourceFile(node.parent) ? "" : "null";
|
|
29
29
|
}
|
|
30
30
|
try {
|
|
31
31
|
const result = handler(node, this.transpileContext);
|
|
@@ -33,7 +33,7 @@ class NodeHandler {
|
|
|
33
33
|
} catch (error) {
|
|
34
34
|
console.error(error);
|
|
35
35
|
this.printLineAndCol(node);
|
|
36
|
-
return "null";
|
|
36
|
+
return ts.isBlock(node.parent) || ts.isSourceFile(node.parent) ? "" : "null";
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
static printLineAndCol(node) {
|
|
@@ -149,7 +149,6 @@ var apiNameMap = {
|
|
|
149
149
|
"GreyHack.programPath": "program_path",
|
|
150
150
|
"GreyHack.resetCtfPassword": "reset_ctf_password",
|
|
151
151
|
"GreyHack.getType": "typeof",
|
|
152
|
-
"GreyHack.isType": "is_type",
|
|
153
152
|
"GreyHack.userBankNumber": "user_bank_number",
|
|
154
153
|
"GreyHack.userInput": "user_input",
|
|
155
154
|
"GreyHack.userMailAddress": "user_mail_address",
|
|
@@ -215,9 +214,11 @@ var apiNameMap = {
|
|
|
215
214
|
"String.length": "len",
|
|
216
215
|
"String.toLowerCase": "lower",
|
|
217
216
|
"String.toUpperCase": "upper",
|
|
217
|
+
"String.repeat": "repeatSelf",
|
|
218
218
|
"Object.size": "len",
|
|
219
219
|
"Array.length": "len",
|
|
220
|
-
"Array.shift": "pull"
|
|
220
|
+
"Array.shift": "pull",
|
|
221
|
+
"Array.push": "push_many"
|
|
221
222
|
};
|
|
222
223
|
var propertyAccessReplacements = {
|
|
223
224
|
"Math.PI": "pi",
|
|
@@ -384,9 +385,28 @@ function findProjectRoot(dir, fileToSearch = "package.json") {
|
|
|
384
385
|
return dir;
|
|
385
386
|
}
|
|
386
387
|
function callUtilFunction(functionName, ...params) {
|
|
387
|
-
|
|
388
|
+
utilitiesToInsert.set(functionName, utilFunctions[functionName]);
|
|
388
389
|
return `${functionName}(${params.join(", ")})`;
|
|
389
390
|
}
|
|
391
|
+
var assignmentOperators = new Set([
|
|
392
|
+
"=",
|
|
393
|
+
"??=",
|
|
394
|
+
"||=",
|
|
395
|
+
"-=",
|
|
396
|
+
"+="
|
|
397
|
+
]);
|
|
398
|
+
function valueIsBeingAssignedToNode(node) {
|
|
399
|
+
if (ts3.hasOnlyExpressionInitializer(node.parent) && node === node.parent.name)
|
|
400
|
+
return true;
|
|
401
|
+
const assignAncestor = ts3.findAncestor(node, (ancestor) => {
|
|
402
|
+
if (ancestor.parent && ts3.isBinaryExpression(ancestor.parent) && ancestor === ancestor.parent.left) {
|
|
403
|
+
const token = ts3.tokenToString(ancestor.parent.operatorToken.kind) || ancestor.parent.operatorToken.getText();
|
|
404
|
+
return assignmentOperators.has(token);
|
|
405
|
+
}
|
|
406
|
+
return false;
|
|
407
|
+
});
|
|
408
|
+
return !!assignAncestor;
|
|
409
|
+
}
|
|
390
410
|
|
|
391
411
|
// src/visitors/assignments.ts
|
|
392
412
|
import ts4 from "typescript";
|
|
@@ -495,7 +515,7 @@ end function`;
|
|
|
495
515
|
});
|
|
496
516
|
|
|
497
517
|
// src/visitors/expressions.ts
|
|
498
|
-
import
|
|
518
|
+
import ts7 from "typescript";
|
|
499
519
|
|
|
500
520
|
// src/call_transformers/callTransformer.ts
|
|
501
521
|
import path2 from "node:path";
|
|
@@ -508,6 +528,13 @@ class CallTransformer {
|
|
|
508
528
|
this.handlers.set(symbolFullName, handler);
|
|
509
529
|
}
|
|
510
530
|
static handle(symbolFullName, functionName, callArgs, node, ctx) {
|
|
531
|
+
if (symbolFullName in extensionFunctions) {
|
|
532
|
+
if (symbolFullName.startsWith("Math"))
|
|
533
|
+
utilitiesToInsert.set("create_math", "Math = {}");
|
|
534
|
+
utilitiesToInsert.set(symbolFullName, extensionFunctions[symbolFullName]);
|
|
535
|
+
const params = callArgs.length ? `(${callArgs.join(",")})` : "";
|
|
536
|
+
return `${functionName}${params}`;
|
|
537
|
+
}
|
|
511
538
|
const handler = this.handlers.get(symbolFullName);
|
|
512
539
|
if (!handler)
|
|
513
540
|
return null;
|
|
@@ -522,12 +549,6 @@ CallTransformer.register("Function.toString", (name) => {
|
|
|
522
549
|
const func = name.slice(0, name.lastIndexOf("."));
|
|
523
550
|
return `str(@${func})`;
|
|
524
551
|
});
|
|
525
|
-
CallTransformer.register("Math.min", (name, args) => {
|
|
526
|
-
return callUtilFunction("math_min", `${args.join(",")}`);
|
|
527
|
-
});
|
|
528
|
-
CallTransformer.register("Math.max", (name, args) => {
|
|
529
|
-
return callUtilFunction("math_max", `${args.join(",")}`);
|
|
530
|
-
});
|
|
531
552
|
CallTransformer.register("GreyHack.include", (name, args, node, ctx) => {
|
|
532
553
|
if (!node.arguments.length)
|
|
533
554
|
return "";
|
|
@@ -541,6 +562,9 @@ CallTransformer.register("GreyHack.include", (name, args, node, ctx) => {
|
|
|
541
562
|
}
|
|
542
563
|
return "";
|
|
543
564
|
});
|
|
565
|
+
CallTransformer.register("GreyHack.isType", (name, args) => {
|
|
566
|
+
return callUtilFunction("is_type", args.join(","));
|
|
567
|
+
});
|
|
544
568
|
CallTransformer.register("Boolean", (name, args) => {
|
|
545
569
|
if (!args.length)
|
|
546
570
|
return "0";
|
|
@@ -557,129 +581,12 @@ CallTransformer.register("String", (name, args) => {
|
|
|
557
581
|
return `str(${args[0]})`;
|
|
558
582
|
});
|
|
559
583
|
|
|
560
|
-
// src/visitors/objects.ts
|
|
561
|
-
import ts7 from "typescript";
|
|
562
|
-
var assignmentOperators = new Set([
|
|
563
|
-
"=",
|
|
564
|
-
"??=",
|
|
565
|
-
"||=",
|
|
566
|
-
"-=",
|
|
567
|
-
"+="
|
|
568
|
-
]);
|
|
569
|
-
function valueIsBeingAssignedToNode(node) {
|
|
570
|
-
const assignAncestor = ts7.findAncestor(node, (ancestor) => {
|
|
571
|
-
if (ancestor.parent && ts7.isBinaryExpression(ancestor.parent) && ancestor === ancestor.parent.left) {
|
|
572
|
-
const token = ts7.tokenToString(ancestor.parent.operatorToken.kind) || ancestor.parent.operatorToken.getText();
|
|
573
|
-
return assignmentOperators.has(token);
|
|
574
|
-
}
|
|
575
|
-
return false;
|
|
576
|
-
});
|
|
577
|
-
return !!assignAncestor;
|
|
578
|
-
}
|
|
579
|
-
NodeHandler.register(ts7.SyntaxKind.PropertyAccessExpression, (node, ctx) => {
|
|
580
|
-
const left = NodeHandler.handle(node.expression);
|
|
581
|
-
let right = NodeHandler.handle(node.name);
|
|
582
|
-
right = replaceIdentifier(right, checker.getTypeAtLocation(node.expression), right);
|
|
583
|
-
const nodeSymbol = checker.getSymbolAtLocation(node);
|
|
584
|
-
if (ctx.namespaceImports[ctx.currentFilePath]?.has(left))
|
|
585
|
-
return right;
|
|
586
|
-
let getSafely = !!node.questionDotToken && !ts7.isNonNullExpression(node.parent);
|
|
587
|
-
const rightType = checker.getTypeAtLocation(node.name);
|
|
588
|
-
if (rightType.isUnion()) {
|
|
589
|
-
const hasUndefined = rightType.types.some((t) => t.flags === ts7.TypeFlags.Undefined);
|
|
590
|
-
if (hasUndefined)
|
|
591
|
-
getSafely = true;
|
|
592
|
-
}
|
|
593
|
-
if (!valueIsBeingAssignedToNode(node) && getSafely)
|
|
594
|
-
return callUtilFunction("get_property", left, `"${right}"`);
|
|
595
|
-
let output = `${left}.${right}`;
|
|
596
|
-
output = replacePropertyAccess(output, nodeSymbol);
|
|
597
|
-
if (nodeIsFunctionReference(node))
|
|
598
|
-
output = asRef(output);
|
|
599
|
-
return output;
|
|
600
|
-
});
|
|
601
|
-
NodeHandler.register(ts7.SyntaxKind.ElementAccessExpression, (node, ctx) => {
|
|
602
|
-
const left = NodeHandler.handle(node.expression);
|
|
603
|
-
let right;
|
|
604
|
-
if (ts7.isStringLiteral(node.argumentExpression)) {
|
|
605
|
-
const leftType = checker.getTypeAtLocation(node.expression);
|
|
606
|
-
right = `"${replaceIdentifier(node.argumentExpression.text, leftType, node.argumentExpression.text)}"`;
|
|
607
|
-
} else {
|
|
608
|
-
right = NodeHandler.handle(node.argumentExpression);
|
|
609
|
-
}
|
|
610
|
-
if (!valueIsBeingAssignedToNode(node) && !ts7.isNumericLiteral(node.argumentExpression)) {
|
|
611
|
-
return callUtilFunction("get_property", left, `${right}`);
|
|
612
|
-
}
|
|
613
|
-
return `${left}[${right}]`;
|
|
614
|
-
});
|
|
615
|
-
function handleObjectLiteralExpression(node, ctx, currObj, outObjects, funcs) {
|
|
616
|
-
currObj ??= [];
|
|
617
|
-
outObjects ??= [];
|
|
618
|
-
funcs ??= [];
|
|
619
|
-
const objectName = ts7.hasOnlyExpressionInitializer(node.parent) ? NodeHandler.handle(node.parent.name) : ts7.isBinaryExpression(node.parent) && node === node.parent.right ? NodeHandler.handle(node.parent.left) : "";
|
|
620
|
-
function pushObj() {
|
|
621
|
-
if (!currObj?.length)
|
|
622
|
-
return "";
|
|
623
|
-
const res = currObj.filter((s) => s != "").join(",");
|
|
624
|
-
if (res) {
|
|
625
|
-
outObjects?.push(`{ ${res} }`);
|
|
626
|
-
}
|
|
627
|
-
currObj.length = 0;
|
|
628
|
-
return res;
|
|
629
|
-
}
|
|
630
|
-
for (const item of node.properties) {
|
|
631
|
-
if (ts7.isFunctionLike(item)) {
|
|
632
|
-
if (!objectName)
|
|
633
|
-
throw "You can't have method declarations inside an object that is not being assigned to a variable";
|
|
634
|
-
funcs.push(`${objectName}.${NodeHandler.handle(item)}`);
|
|
635
|
-
continue;
|
|
636
|
-
}
|
|
637
|
-
if (ts7.isPropertyAssignment(item) && ts7.isFunctionLike(item.initializer)) {
|
|
638
|
-
if (!objectName)
|
|
639
|
-
throw "You can't have method declarations inside an object that is not being assigned to a variable";
|
|
640
|
-
funcs.push(`${objectName}.${NodeHandler.handle(item.name)} = ${NodeHandler.handle(item.initializer)}`);
|
|
641
|
-
continue;
|
|
642
|
-
}
|
|
643
|
-
if (ts7.isSpreadAssignment(item)) {
|
|
644
|
-
if (ts7.isObjectLiteralExpression(item.expression)) {
|
|
645
|
-
handleObjectLiteralExpression(item.expression, ctx, currObj, outObjects);
|
|
646
|
-
continue;
|
|
647
|
-
}
|
|
648
|
-
if (ts7.isIdentifier(item.expression)) {
|
|
649
|
-
pushObj();
|
|
650
|
-
outObjects.push(NodeHandler.handle(item.expression));
|
|
651
|
-
continue;
|
|
652
|
-
}
|
|
653
|
-
if (ts7.isArrayLiteralExpression(item.expression)) {
|
|
654
|
-
pushObj();
|
|
655
|
-
outObjects.push(NodeHandler.handle(item.expression));
|
|
656
|
-
continue;
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
currObj.push(NodeHandler.handle(item));
|
|
660
|
-
}
|
|
661
|
-
pushObj();
|
|
662
|
-
if (!outObjects.length)
|
|
663
|
-
outObjects.push("{}");
|
|
664
|
-
let output = outObjects[0];
|
|
665
|
-
if (outObjects.length > 1) {
|
|
666
|
-
output = callUtilFunction("assign_objects", output, `[${outObjects.slice(1).join(",")}]`);
|
|
667
|
-
}
|
|
668
|
-
if (funcs.length) {
|
|
669
|
-
output += `
|
|
670
|
-
` + funcs.join(`
|
|
671
|
-
`);
|
|
672
|
-
}
|
|
673
|
-
return output;
|
|
674
|
-
}
|
|
675
|
-
NodeHandler.register(ts7.SyntaxKind.ObjectLiteralExpression, handleObjectLiteralExpression);
|
|
676
|
-
|
|
677
584
|
// src/visitors/expressions.ts
|
|
678
585
|
function hasRestParam(params) {
|
|
679
586
|
if (!params.length)
|
|
680
587
|
return false;
|
|
681
588
|
const lastParam = params[params.length - 1];
|
|
682
|
-
return !!(lastParam.valueDeclaration &&
|
|
589
|
+
return !!(lastParam.valueDeclaration && ts7.isParameter(lastParam.valueDeclaration) && lastParam.valueDeclaration.dotDotDotToken);
|
|
683
590
|
}
|
|
684
591
|
function handleCallArgs(callNode, ctx) {
|
|
685
592
|
const args = callNode.arguments;
|
|
@@ -703,11 +610,11 @@ function handleCallArgs(callNode, ctx) {
|
|
|
703
610
|
}
|
|
704
611
|
}
|
|
705
612
|
for (const arg of args) {
|
|
706
|
-
if (!
|
|
613
|
+
if (!ts7.isSpreadElement(arg)) {
|
|
707
614
|
pushArgs(false, NodeHandler.handle(arg));
|
|
708
615
|
continue;
|
|
709
616
|
}
|
|
710
|
-
if (
|
|
617
|
+
if (ts7.isArrayLiteralExpression(arg.expression)) {
|
|
711
618
|
const arrayItems = [];
|
|
712
619
|
const outArrs = [];
|
|
713
620
|
handleArrayLiteralExpression(arg.expression, ctx, arrayItems, outArrs);
|
|
@@ -759,7 +666,7 @@ function handleCallArgs(callNode, ctx) {
|
|
|
759
666
|
result.push("[]");
|
|
760
667
|
return result;
|
|
761
668
|
}
|
|
762
|
-
NodeHandler.register(
|
|
669
|
+
NodeHandler.register(ts7.SyntaxKind.CallExpression, (node, ctx) => {
|
|
763
670
|
const args = handleCallArgs(node, ctx);
|
|
764
671
|
let name = NodeHandler.handle(node.expression);
|
|
765
672
|
const type = checker.getTypeAtLocation(node.expression);
|
|
@@ -771,14 +678,11 @@ NodeHandler.register(ts8.SyntaxKind.CallExpression, (node, ctx) => {
|
|
|
771
678
|
const transformed = CallTransformer.handle(symbolFullName, name, args, node, ctx);
|
|
772
679
|
if (transformed !== null)
|
|
773
680
|
return transformed;
|
|
774
|
-
if (name === "is_type" && !calledUtilFunctions.has("is_type")) {
|
|
775
|
-
calledUtilFunctions.add("is_type");
|
|
776
|
-
}
|
|
777
681
|
if (!args.length)
|
|
778
682
|
return name;
|
|
779
683
|
return `${name}(${args.join(", ")})`;
|
|
780
684
|
});
|
|
781
|
-
NodeHandler.register(
|
|
685
|
+
NodeHandler.register(ts7.SyntaxKind.NewExpression, (node, ctx) => {
|
|
782
686
|
const args = handleCallArgs(node, ctx);
|
|
783
687
|
let output = `(new ${NodeHandler.handle(node.expression)}).constructor`;
|
|
784
688
|
if (args.length)
|
|
@@ -788,12 +692,12 @@ NodeHandler.register(ts8.SyntaxKind.NewExpression, (node, ctx) => {
|
|
|
788
692
|
function shouldHaveOuterPrefix(node, operator) {
|
|
789
693
|
if (!assignmentOperators.has(operator))
|
|
790
694
|
return false;
|
|
791
|
-
if (!
|
|
695
|
+
if (!ts7.isIdentifier(node.left))
|
|
792
696
|
return false;
|
|
793
|
-
const functionAncestor =
|
|
697
|
+
const functionAncestor = ts7.findAncestor(node.parent, (n) => ts7.isFunctionLike(n));
|
|
794
698
|
if (!functionAncestor)
|
|
795
699
|
return false;
|
|
796
|
-
if (!
|
|
700
|
+
if (!ts7.findAncestor(functionAncestor.parent, (n) => ts7.isFunctionLike(n)))
|
|
797
701
|
return false;
|
|
798
702
|
const leftSymbol = checker.getSymbolAtLocation(node.left);
|
|
799
703
|
if (!leftSymbol?.valueDeclaration)
|
|
@@ -803,26 +707,26 @@ function shouldHaveOuterPrefix(node, operator) {
|
|
|
803
707
|
function isAssignmentChain(node, operator) {
|
|
804
708
|
if (!assignmentOperators.has(operator))
|
|
805
709
|
return false;
|
|
806
|
-
if (
|
|
710
|
+
if (ts7.isBinaryExpression(node.right) && assignmentOperators.has(ts7.tokenToString(node.right.operatorToken.kind) || ""))
|
|
807
711
|
return true;
|
|
808
|
-
if (
|
|
712
|
+
if (ts7.hasOnlyExpressionInitializer(node.parent))
|
|
809
713
|
return true;
|
|
810
714
|
return false;
|
|
811
715
|
}
|
|
812
|
-
NodeHandler.register(
|
|
716
|
+
NodeHandler.register(ts7.SyntaxKind.BinaryExpression, (node) => {
|
|
813
717
|
let operatorToken = getOperatorToken(node.operatorToken) || node.operatorToken.getText();
|
|
814
718
|
if (isAssignmentChain(node, operatorToken))
|
|
815
719
|
throw `Assignment chaining is not supported`;
|
|
816
720
|
let right = NodeHandler.handle(node.right);
|
|
817
721
|
if (nodeIsFunctionReference(node.right))
|
|
818
722
|
right = asRef(right);
|
|
819
|
-
if (
|
|
723
|
+
if (ts7.isPropertyAccessExpression(node.left)) {
|
|
820
724
|
const leftType = checker.getTypeAtLocation(node.left.expression);
|
|
821
725
|
const symbol = leftType.getProperty(node.left.name.text);
|
|
822
|
-
if (symbol?.declarations?.some((decl) =>
|
|
726
|
+
if (symbol?.declarations?.some((decl) => ts7.isSetAccessor(decl))) {
|
|
823
727
|
const objName = NodeHandler.handle(node.left.expression);
|
|
824
728
|
const key = node.left.name.text;
|
|
825
|
-
if (operatorToken !== "=" && symbol.declarations.some((decl) =>
|
|
729
|
+
if (operatorToken !== "=" && symbol.declarations.some((decl) => ts7.isGetAccessor(decl)))
|
|
826
730
|
throw `Can't handle '${operatorToken}' because '${objName}' doesn't have a getter '${key}'`;
|
|
827
731
|
if (operatorToken === "+=" || operatorToken === "-=") {
|
|
828
732
|
right = `${objName}.${key} ${operatorToken[0]} ${right}`;
|
|
@@ -837,22 +741,12 @@ NodeHandler.register(ts8.SyntaxKind.BinaryExpression, (node) => {
|
|
|
837
741
|
left = "outer." + left;
|
|
838
742
|
if (nodeIsFunctionReference(node.left))
|
|
839
743
|
left = asRef(left);
|
|
840
|
-
if (operatorToken === "or" &&
|
|
744
|
+
if (operatorToken === "or" && ts7.hasOnlyExpressionInitializer(node.parent)) {
|
|
841
745
|
return callUtilFunction("or_op", left, right);
|
|
842
746
|
}
|
|
843
|
-
if (operatorToken === "instanceof") {
|
|
844
|
-
const rightSymbol = checker.getSymbolAtLocation(node.right);
|
|
845
|
-
const classIdMember = rightSymbol?.members?.get(ts8.escapeLeadingUnderscores("classID"));
|
|
846
|
-
if (!classIdMember) {
|
|
847
|
-
throw `Can't handle this 'instanceof' operator because '${right}' doesn't have a 'classID' member, which is needed in GreyScript to check a type`;
|
|
848
|
-
}
|
|
849
|
-
const declaration = classIdMember.valueDeclaration;
|
|
850
|
-
if (!declaration || !("initializer" in declaration) || !declaration.initializer) {
|
|
851
|
-
throw `The 'classID' property of '${right}' isn't initialized`;
|
|
852
|
-
}
|
|
853
|
-
return `${left}.classID == typeof(${right})`;
|
|
854
|
-
}
|
|
855
747
|
switch (operatorToken) {
|
|
748
|
+
case "instanceof":
|
|
749
|
+
return callUtilFunction("instance_of", left, right);
|
|
856
750
|
case "??":
|
|
857
751
|
return callUtilFunction("nullish_coalescing_op", left, right);
|
|
858
752
|
case "??=":
|
|
@@ -879,41 +773,44 @@ NodeHandler.register(ts8.SyntaxKind.BinaryExpression, (node) => {
|
|
|
879
773
|
operatorToken = "^";
|
|
880
774
|
return `${left} ${operatorToken} ${right}`;
|
|
881
775
|
});
|
|
882
|
-
NodeHandler.register(
|
|
776
|
+
NodeHandler.register(ts7.SyntaxKind.ParenthesizedExpression, (node) => {
|
|
883
777
|
return `(${NodeHandler.handle(node.expression)})`;
|
|
884
778
|
});
|
|
885
779
|
function handleUnaryExpression(node) {
|
|
886
780
|
const operand = NodeHandler.handle(node.operand);
|
|
887
|
-
const operator =
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
781
|
+
const operator = ts7.tokenToString(node.operator);
|
|
782
|
+
switch (operator) {
|
|
783
|
+
case "++":
|
|
784
|
+
case "--":
|
|
785
|
+
if (ts7.hasOnlyExpressionInitializer(node.parent) || ts7.isBinaryExpression(node.parent))
|
|
786
|
+
throw `Operator ${operator} is not supported for this kind of expression yet`;
|
|
787
|
+
return `${operand} = ${operand} ${operator[0]} 1`;
|
|
788
|
+
case "!":
|
|
789
|
+
if (ts7.isPrefixUnaryExpression(node.parent) && ts7.tokenToString(node.parent.operator) === "!") {
|
|
790
|
+
return `(not ${operand})`;
|
|
791
|
+
}
|
|
792
|
+
return `not ${operand}`;
|
|
793
|
+
case "-":
|
|
794
|
+
return `-${operand}`;
|
|
795
|
+
case "+":
|
|
796
|
+
return `str(${operand}).val`;
|
|
797
|
+
case "~":
|
|
798
|
+
return `bitwise("~", ${operand})`;
|
|
799
|
+
default:
|
|
800
|
+
throw `Couldn't handle this UnaryExpression: ${node.getText()}`;
|
|
801
|
+
}
|
|
905
802
|
}
|
|
906
|
-
NodeHandler.register(
|
|
907
|
-
NodeHandler.register(
|
|
803
|
+
NodeHandler.register(ts7.SyntaxKind.PrefixUnaryExpression, handleUnaryExpression);
|
|
804
|
+
NodeHandler.register(ts7.SyntaxKind.PostfixUnaryExpression, handleUnaryExpression);
|
|
908
805
|
function handleArrayLiteralExpression(node, ctx, itemStrings, out) {
|
|
909
806
|
itemStrings ??= [];
|
|
910
807
|
out ??= [];
|
|
911
808
|
for (const item of node.elements) {
|
|
912
|
-
if (!
|
|
809
|
+
if (!ts7.isSpreadElement(item)) {
|
|
913
810
|
itemStrings.push(NodeHandler.handle(item));
|
|
914
811
|
continue;
|
|
915
812
|
}
|
|
916
|
-
if (
|
|
813
|
+
if (ts7.isArrayLiteralExpression(item.expression)) {
|
|
917
814
|
handleArrayLiteralExpression(item.expression, ctx, itemStrings, out);
|
|
918
815
|
continue;
|
|
919
816
|
}
|
|
@@ -923,14 +820,14 @@ function handleArrayLiteralExpression(node, ctx, itemStrings, out) {
|
|
|
923
820
|
}
|
|
924
821
|
out.push(NodeHandler.handle(item.expression));
|
|
925
822
|
}
|
|
926
|
-
if ((!out.length || itemStrings.length) && !
|
|
823
|
+
if ((!out.length || itemStrings.length) && !ts7.isSpreadElement(node.parent)) {
|
|
927
824
|
out.push(`[${itemStrings.join(",")}]`);
|
|
928
825
|
itemStrings.length = 0;
|
|
929
826
|
}
|
|
930
827
|
return out.join(" + ");
|
|
931
828
|
}
|
|
932
|
-
NodeHandler.register(
|
|
933
|
-
NodeHandler.register(
|
|
829
|
+
NodeHandler.register(ts7.SyntaxKind.ArrayLiteralExpression, handleArrayLiteralExpression);
|
|
830
|
+
NodeHandler.register(ts7.SyntaxKind.TemplateExpression, (node) => {
|
|
934
831
|
const head = NodeHandler.handle(node.head);
|
|
935
832
|
const strings = [
|
|
936
833
|
...head ? [`"${head}"`] : [],
|
|
@@ -939,22 +836,22 @@ NodeHandler.register(ts8.SyntaxKind.TemplateExpression, (node) => {
|
|
|
939
836
|
const output = strings.join(" + ");
|
|
940
837
|
return output;
|
|
941
838
|
});
|
|
942
|
-
NodeHandler.register(
|
|
839
|
+
NodeHandler.register(ts7.SyntaxKind.TemplateHead, (node) => {
|
|
943
840
|
return transformString(node.text);
|
|
944
841
|
});
|
|
945
|
-
NodeHandler.register(
|
|
842
|
+
NodeHandler.register(ts7.SyntaxKind.TemplateSpan, (node) => {
|
|
946
843
|
let output = NodeHandler.handle(node.expression);
|
|
947
|
-
if (
|
|
844
|
+
if (ts7.isBinaryExpression(node.expression))
|
|
948
845
|
output = `str(${output})`;
|
|
949
846
|
if (node.literal.text)
|
|
950
847
|
output += ` + "${transformString(node.literal.text)}"`;
|
|
951
848
|
return output;
|
|
952
849
|
});
|
|
953
|
-
NodeHandler.register(
|
|
850
|
+
NodeHandler.register(ts7.SyntaxKind.NoSubstitutionTemplateLiteral, (node) => {
|
|
954
851
|
return `"${transformString(node.text)}"`;
|
|
955
852
|
});
|
|
956
|
-
NodeHandler.register(
|
|
957
|
-
if (
|
|
853
|
+
NodeHandler.register(ts7.SyntaxKind.ConditionalExpression, (node) => {
|
|
854
|
+
if (ts7.isCallExpression(node.whenTrue) || ts7.isCallExpression(node.whenFalse)) {
|
|
958
855
|
throw "Call expressions are not supported inside conditional expressions yet";
|
|
959
856
|
}
|
|
960
857
|
const condition = NodeHandler.handle(node.condition);
|
|
@@ -962,28 +859,28 @@ NodeHandler.register(ts8.SyntaxKind.ConditionalExpression, (node) => {
|
|
|
962
859
|
const whenFalse = NodeHandler.handle(node.whenFalse);
|
|
963
860
|
return callUtilFunction("conditional_expr", condition, whenTrue, whenFalse);
|
|
964
861
|
});
|
|
965
|
-
NodeHandler.register(
|
|
862
|
+
NodeHandler.register(ts7.SyntaxKind.ExpressionStatement, (node) => {
|
|
966
863
|
return NodeHandler.handle(node.expression);
|
|
967
864
|
});
|
|
968
|
-
NodeHandler.register(
|
|
865
|
+
NodeHandler.register(ts7.SyntaxKind.NonNullExpression, (node) => {
|
|
969
866
|
return NodeHandler.handle(node.expression);
|
|
970
867
|
});
|
|
971
|
-
NodeHandler.register(
|
|
868
|
+
NodeHandler.register(ts7.SyntaxKind.AsExpression, (node) => {
|
|
972
869
|
return NodeHandler.handle(node.expression);
|
|
973
870
|
});
|
|
974
|
-
NodeHandler.register(
|
|
975
|
-
if (
|
|
871
|
+
NodeHandler.register(ts7.SyntaxKind.DeleteExpression, (node) => {
|
|
872
|
+
if (ts7.isPropertyAccessExpression(node.expression)) {
|
|
976
873
|
const pnode = node.expression;
|
|
977
874
|
const left = NodeHandler.handle(pnode.expression);
|
|
978
875
|
const leftType = checker.getTypeAtLocation(pnode.expression);
|
|
979
876
|
const right = replaceIdentifier(NodeHandler.handle(pnode.name), leftType, pnode.name.text);
|
|
980
877
|
return `${left}.remove("${right}")`;
|
|
981
878
|
}
|
|
982
|
-
if (
|
|
879
|
+
if (ts7.isElementAccessExpression(node.expression)) {
|
|
983
880
|
const pnode = node.expression;
|
|
984
881
|
const left = NodeHandler.handle(pnode.expression);
|
|
985
882
|
let right;
|
|
986
|
-
if (
|
|
883
|
+
if (ts7.isStringLiteral(pnode.argumentExpression)) {
|
|
987
884
|
const leftType = checker.getTypeAtLocation(pnode.expression);
|
|
988
885
|
right = `"${replaceIdentifier(pnode.argumentExpression.text, leftType, pnode.argumentExpression.text)}"`;
|
|
989
886
|
} else {
|
|
@@ -991,11 +888,11 @@ NodeHandler.register(ts8.SyntaxKind.DeleteExpression, (node) => {
|
|
|
991
888
|
}
|
|
992
889
|
return `${left}.remove(${right})`;
|
|
993
890
|
}
|
|
994
|
-
throw `Cant handle delete expression for ${
|
|
891
|
+
throw `Cant handle delete expression for ${ts7.SyntaxKind[node.expression.kind]}`;
|
|
995
892
|
});
|
|
996
893
|
|
|
997
894
|
// src/visitors/functions.ts
|
|
998
|
-
import
|
|
895
|
+
import ts8 from "typescript";
|
|
999
896
|
function transpileFunctionBody(node) {
|
|
1000
897
|
const params = node.parameters.map((param) => NodeHandler.handle(param)).join(", ");
|
|
1001
898
|
const body = node.body ? NodeHandler.handle(node.body) : "";
|
|
@@ -1003,7 +900,7 @@ function transpileFunctionBody(node) {
|
|
|
1003
900
|
${body}
|
|
1004
901
|
end function`;
|
|
1005
902
|
}
|
|
1006
|
-
NodeHandler.register(
|
|
903
|
+
NodeHandler.register(ts8.SyntaxKind.Block, (node) => {
|
|
1007
904
|
const output = node.statements.map((val) => {
|
|
1008
905
|
let statement = NodeHandler.handle(val);
|
|
1009
906
|
statement = statement.split(`
|
|
@@ -1014,38 +911,38 @@ NodeHandler.register(ts9.SyntaxKind.Block, (node) => {
|
|
|
1014
911
|
`);
|
|
1015
912
|
return output;
|
|
1016
913
|
});
|
|
1017
|
-
NodeHandler.register(
|
|
914
|
+
NodeHandler.register(ts8.SyntaxKind.MethodDeclaration, (node) => {
|
|
1018
915
|
return `${NodeHandler.handle(node.name)} = ${transpileFunctionBody(node)}`;
|
|
1019
916
|
});
|
|
1020
|
-
NodeHandler.register(
|
|
917
|
+
NodeHandler.register(ts8.SyntaxKind.FunctionDeclaration, (node) => {
|
|
1021
918
|
if (!node.body)
|
|
1022
919
|
return "";
|
|
1023
|
-
if (node.modifiers?.some((m) => m.kind ===
|
|
920
|
+
if (node.modifiers?.some((m) => m.kind === ts8.SyntaxKind.DeclareKeyword))
|
|
1024
921
|
return "";
|
|
1025
922
|
const name = node.name ? node.name.text : "anon";
|
|
1026
923
|
return `${name} = ${transpileFunctionBody(node)}`;
|
|
1027
924
|
});
|
|
1028
|
-
NodeHandler.register(
|
|
925
|
+
NodeHandler.register(ts8.SyntaxKind.ArrowFunction, (node) => {
|
|
1029
926
|
const params = node.parameters.map((param) => NodeHandler.handle(param));
|
|
1030
|
-
const body =
|
|
1031
|
-
if (
|
|
927
|
+
const body = ts8.isBlock(node.body) ? NodeHandler.handle(node.body) : ` return ${NodeHandler.handle(node.body)}`;
|
|
928
|
+
if (ts8.isCallOrNewExpression(node.parent) || ts8.isParenthesizedExpression(node.parent)) {
|
|
1032
929
|
return "@" + createAnonFunction(body, params).name;
|
|
1033
930
|
}
|
|
1034
|
-
if (
|
|
931
|
+
if (ts8.hasOnlyExpressionInitializer(node.parent) || ts8.isBinaryExpression(node.parent) || ts8.isReturnStatement(node.parent)) {
|
|
1035
932
|
return `function(${params.join(", ")})
|
|
1036
933
|
${body}
|
|
1037
934
|
end function`;
|
|
1038
935
|
}
|
|
1039
|
-
const kind =
|
|
936
|
+
const kind = ts8.SyntaxKind[node.parent.kind];
|
|
1040
937
|
throw `This kind of arrow function is not yet supported (parent: ${kind} (${node.parent.kind}))`;
|
|
1041
938
|
});
|
|
1042
|
-
NodeHandler.register(
|
|
939
|
+
NodeHandler.register(ts8.SyntaxKind.FunctionExpression, (node) => {
|
|
1043
940
|
return transpileFunctionBody(node);
|
|
1044
941
|
});
|
|
1045
942
|
|
|
1046
943
|
// src/visitors/identifiers.ts
|
|
1047
|
-
import
|
|
1048
|
-
NodeHandler.register(
|
|
944
|
+
import ts9 from "typescript";
|
|
945
|
+
NodeHandler.register(ts9.SyntaxKind.Identifier, (node, ctx) => {
|
|
1049
946
|
const type = checker.getTypeAtLocation(node);
|
|
1050
947
|
let name = node.text;
|
|
1051
948
|
if (name === "undefined")
|
|
@@ -1063,31 +960,31 @@ NodeHandler.register(ts10.SyntaxKind.Identifier, (node, ctx) => {
|
|
|
1063
960
|
if (ctx.namedImports[ctx.currentFilePath]?.[name]) {
|
|
1064
961
|
name = ctx.namedImports[ctx.currentFilePath][name];
|
|
1065
962
|
}
|
|
1066
|
-
if (
|
|
963
|
+
if (ts9.isCallOrNewExpression(node.parent) && node != node.parent.expression) {
|
|
1067
964
|
if (nodeIsFunctionReference(node, type))
|
|
1068
965
|
name = asRef(name);
|
|
1069
966
|
}
|
|
1070
967
|
return name;
|
|
1071
968
|
});
|
|
1072
|
-
NodeHandler.register(
|
|
969
|
+
NodeHandler.register(ts9.SyntaxKind.Parameter, (node) => {
|
|
1073
970
|
const name = NodeHandler.handle(node.name);
|
|
1074
971
|
if (!node.initializer)
|
|
1075
972
|
return name;
|
|
1076
973
|
const initializer = NodeHandler.handle(node.initializer);
|
|
1077
974
|
const initializerType = checker.getTypeAtLocation(node.initializer);
|
|
1078
|
-
if (initializerType.flags ===
|
|
975
|
+
if (initializerType.flags === ts9.TypeFlags.Object) {
|
|
1079
976
|
throw `You can't initialize parameter '${name}' with an Array or an Object as that won't work in GreyScript and it would be null`;
|
|
1080
977
|
}
|
|
1081
978
|
return `${name} = ${initializer}`;
|
|
1082
979
|
});
|
|
1083
|
-
NodeHandler.register(
|
|
1084
|
-
NodeHandler.register(
|
|
1085
|
-
NodeHandler.register(
|
|
1086
|
-
NodeHandler.register(
|
|
1087
|
-
NodeHandler.register(
|
|
1088
|
-
NodeHandler.register(
|
|
1089
|
-
NodeHandler.register(
|
|
1090
|
-
const propDeclarationAncestor =
|
|
980
|
+
NodeHandler.register(ts9.SyntaxKind.NumericLiteral, (node) => node.text);
|
|
981
|
+
NodeHandler.register(ts9.SyntaxKind.StringLiteral, (node) => `"${transformString(node.text)}"`);
|
|
982
|
+
NodeHandler.register(ts9.SyntaxKind.NullKeyword, () => "null");
|
|
983
|
+
NodeHandler.register(ts9.SyntaxKind.UndefinedKeyword, () => "null");
|
|
984
|
+
NodeHandler.register(ts9.SyntaxKind.FalseKeyword, () => "0");
|
|
985
|
+
NodeHandler.register(ts9.SyntaxKind.TrueKeyword, () => "1");
|
|
986
|
+
NodeHandler.register(ts9.SyntaxKind.ThisKeyword, (node) => {
|
|
987
|
+
const propDeclarationAncestor = ts9.findAncestor(node.parent, (n) => ts9.isPropertyDeclaration(n));
|
|
1091
988
|
if (propDeclarationAncestor) {
|
|
1092
989
|
if (!propDeclarationAncestor.parent.name)
|
|
1093
990
|
throw `Can't handle this 'this' keyword becuase the class doesn't have a name and it's needed for this case`;
|
|
@@ -1095,12 +992,12 @@ NodeHandler.register(ts10.SyntaxKind.ThisKeyword, (node) => {
|
|
|
1095
992
|
}
|
|
1096
993
|
return "self";
|
|
1097
994
|
});
|
|
1098
|
-
NodeHandler.register(
|
|
1099
|
-
if (
|
|
995
|
+
NodeHandler.register(ts9.SyntaxKind.SuperKeyword, (node) => {
|
|
996
|
+
if (ts9.isPropertyAccessExpression(node.parent) || ts9.isElementAccessExpression(node.parent))
|
|
1100
997
|
return "super";
|
|
1101
998
|
return "super.constructor";
|
|
1102
999
|
});
|
|
1103
|
-
NodeHandler.register(
|
|
1000
|
+
NodeHandler.register(ts9.SyntaxKind.RegularExpressionLiteral, (node) => {
|
|
1104
1001
|
const start = node.text.indexOf("/") + 1;
|
|
1105
1002
|
const end = node.text.lastIndexOf("/");
|
|
1106
1003
|
const flags = node.text.slice(end + 1);
|
|
@@ -1111,7 +1008,7 @@ NodeHandler.register(ts10.SyntaxKind.RegularExpressionLiteral, (node) => {
|
|
|
1111
1008
|
|
|
1112
1009
|
// src/visitors/imports.ts
|
|
1113
1010
|
import path3 from "node:path";
|
|
1114
|
-
import
|
|
1011
|
+
import ts10 from "typescript";
|
|
1115
1012
|
function importFile(filePath, ctx, returnResult) {
|
|
1116
1013
|
let srcPath = path3.resolve(ctx.currentFolder, filePath);
|
|
1117
1014
|
if (!path3.extname(srcPath))
|
|
@@ -1123,7 +1020,7 @@ function importFile(filePath, ctx, returnResult) {
|
|
|
1123
1020
|
}
|
|
1124
1021
|
return transpileSourceFile(source, ctx, returnResult);
|
|
1125
1022
|
}
|
|
1126
|
-
NodeHandler.register(
|
|
1023
|
+
NodeHandler.register(ts10.SyntaxKind.ImportDeclaration, (node, ctx) => {
|
|
1127
1024
|
if (!node.importClause) {
|
|
1128
1025
|
const moduleName = node.moduleSpecifier.text;
|
|
1129
1026
|
const transpiledFile = importFile(moduleName, ctx, true);
|
|
@@ -1146,7 +1043,7 @@ NodeHandler.register(ts11.SyntaxKind.ImportDeclaration, (node, ctx) => {
|
|
|
1146
1043
|
throw `Can't import default exports yet (imported as ${node.importClause.name.text})`;
|
|
1147
1044
|
const bindings = node.importClause.namedBindings;
|
|
1148
1045
|
if (bindings) {
|
|
1149
|
-
if (
|
|
1046
|
+
if (ts10.isNamespaceImport(bindings)) {
|
|
1150
1047
|
ctx.namespaceImports[ctx.currentFilePath]?.add(bindings.name.text);
|
|
1151
1048
|
} else {
|
|
1152
1049
|
bindings.elements.forEach((el) => {
|
|
@@ -1160,6 +1057,109 @@ NodeHandler.register(ts11.SyntaxKind.ImportDeclaration, (node, ctx) => {
|
|
|
1160
1057
|
return importFile(moduleSpecifier, ctx);
|
|
1161
1058
|
});
|
|
1162
1059
|
|
|
1060
|
+
// src/visitors/objects.ts
|
|
1061
|
+
import ts11 from "typescript";
|
|
1062
|
+
NodeHandler.register(ts11.SyntaxKind.PropertyAccessExpression, (node, ctx) => {
|
|
1063
|
+
const left = NodeHandler.handle(node.expression);
|
|
1064
|
+
let right = NodeHandler.handle(node.name);
|
|
1065
|
+
right = replaceIdentifier(right, checker.getTypeAtLocation(node.expression), right);
|
|
1066
|
+
const nodeSymbol = checker.getSymbolAtLocation(node);
|
|
1067
|
+
if (ctx.namespaceImports[ctx.currentFilePath]?.has(left))
|
|
1068
|
+
return right;
|
|
1069
|
+
let getSafely = !!node.questionDotToken && !ts11.isNonNullExpression(node.parent);
|
|
1070
|
+
const rightType = checker.getTypeAtLocation(node.name);
|
|
1071
|
+
if (rightType.isUnion()) {
|
|
1072
|
+
const hasUndefined = rightType.types.some((t) => t.flags === ts11.TypeFlags.Undefined);
|
|
1073
|
+
if (hasUndefined)
|
|
1074
|
+
getSafely = true;
|
|
1075
|
+
}
|
|
1076
|
+
if (!valueIsBeingAssignedToNode(node) && getSafely)
|
|
1077
|
+
return callUtilFunction("get_property", left, `"${right}"`);
|
|
1078
|
+
let output = `${left}.${right}`;
|
|
1079
|
+
output = replacePropertyAccess(output, nodeSymbol);
|
|
1080
|
+
if (nodeIsFunctionReference(node))
|
|
1081
|
+
output = asRef(output);
|
|
1082
|
+
return output;
|
|
1083
|
+
});
|
|
1084
|
+
NodeHandler.register(ts11.SyntaxKind.ElementAccessExpression, (node, ctx) => {
|
|
1085
|
+
const left = NodeHandler.handle(node.expression);
|
|
1086
|
+
let right;
|
|
1087
|
+
if (ts11.isStringLiteral(node.argumentExpression)) {
|
|
1088
|
+
const leftType = checker.getTypeAtLocation(node.expression);
|
|
1089
|
+
right = `"${replaceIdentifier(node.argumentExpression.text, leftType, node.argumentExpression.text)}"`;
|
|
1090
|
+
} else {
|
|
1091
|
+
right = NodeHandler.handle(node.argumentExpression);
|
|
1092
|
+
}
|
|
1093
|
+
if (!valueIsBeingAssignedToNode(node) && !ts11.isNumericLiteral(node.argumentExpression)) {
|
|
1094
|
+
return callUtilFunction("get_property", left, `${right}`);
|
|
1095
|
+
}
|
|
1096
|
+
return `${left}[${right}]`;
|
|
1097
|
+
});
|
|
1098
|
+
function handleObjectLiteralExpression(node, ctx, currObj, outObjects, funcs) {
|
|
1099
|
+
currObj ??= [];
|
|
1100
|
+
outObjects ??= [];
|
|
1101
|
+
funcs ??= [];
|
|
1102
|
+
let objectName = "";
|
|
1103
|
+
if (ts11.hasOnlyExpressionInitializer(node.parent))
|
|
1104
|
+
objectName = NodeHandler.handle(node.parent.name);
|
|
1105
|
+
else if (ts11.isBinaryExpression(node.parent) && node === node.parent.right)
|
|
1106
|
+
objectName = NodeHandler.handle(node.parent.left);
|
|
1107
|
+
function pushObj() {
|
|
1108
|
+
if (!currObj?.length)
|
|
1109
|
+
return "";
|
|
1110
|
+
const res = currObj.filter((s) => s != "").join(",");
|
|
1111
|
+
if (res) {
|
|
1112
|
+
outObjects?.push(`{ ${res} }`);
|
|
1113
|
+
}
|
|
1114
|
+
currObj.length = 0;
|
|
1115
|
+
return res;
|
|
1116
|
+
}
|
|
1117
|
+
for (const item of node.properties) {
|
|
1118
|
+
if (ts11.isFunctionLike(item)) {
|
|
1119
|
+
funcs.push(NodeHandler.handle(item));
|
|
1120
|
+
continue;
|
|
1121
|
+
}
|
|
1122
|
+
if (ts11.isPropertyAssignment(item) && ts11.isFunctionLike(item.initializer)) {
|
|
1123
|
+
funcs.push(`${NodeHandler.handle(item.name)} = ${NodeHandler.handle(item.initializer)}`);
|
|
1124
|
+
continue;
|
|
1125
|
+
}
|
|
1126
|
+
if (ts11.isSpreadAssignment(item)) {
|
|
1127
|
+
if (ts11.isObjectLiteralExpression(item.expression)) {
|
|
1128
|
+
handleObjectLiteralExpression(item.expression, ctx, currObj, outObjects);
|
|
1129
|
+
continue;
|
|
1130
|
+
}
|
|
1131
|
+
if (ts11.isIdentifier(item.expression)) {
|
|
1132
|
+
pushObj();
|
|
1133
|
+
outObjects.push(NodeHandler.handle(item.expression));
|
|
1134
|
+
continue;
|
|
1135
|
+
}
|
|
1136
|
+
if (ts11.isArrayLiteralExpression(item.expression)) {
|
|
1137
|
+
pushObj();
|
|
1138
|
+
outObjects.push(NodeHandler.handle(item.expression));
|
|
1139
|
+
continue;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
currObj.push(NodeHandler.handle(item));
|
|
1143
|
+
}
|
|
1144
|
+
pushObj();
|
|
1145
|
+
if (!outObjects.length)
|
|
1146
|
+
outObjects.push("{}");
|
|
1147
|
+
let output = outObjects[0];
|
|
1148
|
+
if (outObjects.length > 1) {
|
|
1149
|
+
output = callUtilFunction("assign_objects", output, `[${outObjects.slice(1).join(",")}]`);
|
|
1150
|
+
}
|
|
1151
|
+
if (funcs.length) {
|
|
1152
|
+
if (ts11.isPropertyAssignment(node.parent) || !objectName) {
|
|
1153
|
+
throw "You can't have method declarations inside an object that is not being assigned to a variable";
|
|
1154
|
+
}
|
|
1155
|
+
output += `
|
|
1156
|
+
` + funcs.map((func) => `${objectName}.${func}`).join(`
|
|
1157
|
+
`);
|
|
1158
|
+
}
|
|
1159
|
+
return output;
|
|
1160
|
+
}
|
|
1161
|
+
NodeHandler.register(ts11.SyntaxKind.ObjectLiteralExpression, handleObjectLiteralExpression);
|
|
1162
|
+
|
|
1163
1163
|
// src/visitors/statements.ts
|
|
1164
1164
|
import ts12 from "typescript";
|
|
1165
1165
|
NodeHandler.register(ts12.SyntaxKind.ForStatement, (node) => {
|
|
@@ -1376,56 +1376,13 @@ NodeHandler.register(ts13.SyntaxKind.EnumDeclaration, (node) => {
|
|
|
1376
1376
|
});
|
|
1377
1377
|
|
|
1378
1378
|
// src/call_transformers/array.ts
|
|
1379
|
-
CallTransformer.register("Array.concat", (name, args) => {
|
|
1380
|
-
const dotI = name.lastIndexOf(".");
|
|
1381
|
-
const arrayName = name.slice(0, dotI);
|
|
1382
|
-
return callUtilFunction("array_concat", arrayName, args.join(","));
|
|
1383
|
-
});
|
|
1384
|
-
CallTransformer.register("Array.map", (name, args) => {
|
|
1385
|
-
if (!args.length)
|
|
1386
|
-
throw "Invalid argument count";
|
|
1387
|
-
return callUtilFunction("array_map", name.slice(0, name.lastIndexOf(".")), args[0]);
|
|
1388
|
-
});
|
|
1389
|
-
CallTransformer.register("Array.filter", (name, args) => {
|
|
1390
|
-
if (!args.length)
|
|
1391
|
-
throw "Invalid argument count";
|
|
1392
|
-
return callUtilFunction("array_filter", name.slice(0, name.lastIndexOf(".")), args[0]);
|
|
1393
|
-
});
|
|
1394
|
-
CallTransformer.register("Array.find", (name, args) => {
|
|
1395
|
-
if (!args.length)
|
|
1396
|
-
throw "Invalid argument count";
|
|
1397
|
-
return callUtilFunction("array_find", name.slice(0, name.lastIndexOf(".")), args[0]);
|
|
1398
|
-
});
|
|
1399
|
-
CallTransformer.register("Array.some", (name, args) => {
|
|
1400
|
-
if (!args.length)
|
|
1401
|
-
throw "Invalid argument count";
|
|
1402
|
-
return callUtilFunction("array_some", name.slice(0, name.lastIndexOf(".")), args[0]);
|
|
1403
|
-
});
|
|
1404
|
-
CallTransformer.register("Array.every", (name, args) => {
|
|
1405
|
-
if (!args.length)
|
|
1406
|
-
throw "Invalid argument count";
|
|
1407
|
-
return callUtilFunction("array_every", name.slice(0, name.lastIndexOf(".")), args[0]);
|
|
1408
|
-
});
|
|
1409
1379
|
CallTransformer.register("Array.slice", (name, args) => {
|
|
1410
1380
|
return name.slice(0, name.lastIndexOf(".")) + `[${args[0] ?? ""}:${args[1] ?? ""}]`;
|
|
1411
1381
|
});
|
|
1412
|
-
CallTransformer.register("Array.push", (name, args) => {
|
|
1413
|
-
if (!args.length)
|
|
1414
|
-
throw "Invalid argument count";
|
|
1415
|
-
return callUtilFunction("array_push", name.slice(0, name.lastIndexOf(".")), args[0]);
|
|
1416
|
-
});
|
|
1417
|
-
CallTransformer.register("Array.unshift", (name, args) => {
|
|
1418
|
-
if (!args.length)
|
|
1419
|
-
throw "Invalid argument count";
|
|
1420
|
-
return callUtilFunction("array_unshift", name.slice(0, name.lastIndexOf(".")), args[0]);
|
|
1421
|
-
});
|
|
1422
1382
|
CallTransformer.register("Array.toString", (name) => {
|
|
1423
1383
|
const arrayName = name.slice(0, name.lastIndexOf("."));
|
|
1424
1384
|
return `str(${arrayName})`;
|
|
1425
1385
|
});
|
|
1426
|
-
CallTransformer.register("Array.reverse", (name) => {
|
|
1427
|
-
return callUtilFunction("array_reverse", name.slice(0, name.lastIndexOf(".")));
|
|
1428
|
-
});
|
|
1429
1386
|
|
|
1430
1387
|
// src/call_transformers/object.ts
|
|
1431
1388
|
CallTransformer.register("ObjectConstructor.hasOwn", (name, args) => {
|
|
@@ -1471,21 +1428,6 @@ CallTransformer.register("Object.toString", (name) => {
|
|
|
1471
1428
|
});
|
|
1472
1429
|
|
|
1473
1430
|
// src/call_transformers/string.ts
|
|
1474
|
-
CallTransformer.register("String.startsWith", (name, args) => {
|
|
1475
|
-
if (!args.length)
|
|
1476
|
-
throw "Invalid argument count";
|
|
1477
|
-
return callUtilFunction("str_starts_with", name.slice(0, name.lastIndexOf(".")), ...args);
|
|
1478
|
-
});
|
|
1479
|
-
CallTransformer.register("String.endsWith", (name, args) => {
|
|
1480
|
-
if (!args.length)
|
|
1481
|
-
throw "Invalid argument count";
|
|
1482
|
-
return callUtilFunction("str_ends_with", name.slice(0, name.lastIndexOf(".")), ...args);
|
|
1483
|
-
});
|
|
1484
|
-
CallTransformer.register("String.repeat", (name, args) => {
|
|
1485
|
-
if (!args.length)
|
|
1486
|
-
throw "Invalid argument count";
|
|
1487
|
-
return callUtilFunction("str_repeat", name.slice(0, name.lastIndexOf(".")), ...args);
|
|
1488
|
-
});
|
|
1489
1431
|
CallTransformer.register("String.slice", (name, args) => {
|
|
1490
1432
|
return name.slice(0, name.lastIndexOf(".")) + `[${args[0] ?? ""}:${args[1] ?? ""}]`;
|
|
1491
1433
|
});
|
|
@@ -1496,132 +1438,68 @@ CallTransformer.register("String.toString", (name) => {
|
|
|
1496
1438
|
// src/transpiler.ts
|
|
1497
1439
|
var program;
|
|
1498
1440
|
var checker;
|
|
1499
|
-
var
|
|
1500
|
-
var
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
"get_property = function(obj, key)",
|
|
1504
|
-
"\tif not obj then return null",
|
|
1505
|
-
"\tif obj.hasIndex(key) then return obj[key]",
|
|
1506
|
-
"\tisaobj = obj",
|
|
1507
|
-
'\twhile isaobj.hasIndex("__isa")',
|
|
1508
|
-
'\t\tisaobj = obj["__isa"]',
|
|
1509
|
-
"\t\tif isaobj.hasIndex(key) then",
|
|
1510
|
-
"\t\t\tres = obj[key]",
|
|
1511
|
-
'\t\t\tif typeof(@res) == "function" and str(@res)[8:][1:-1].indexOf("self") == 0 then return res(obj)',
|
|
1512
|
-
"\t\t\treturn obj[key]",
|
|
1513
|
-
"\t\tend if",
|
|
1514
|
-
"\tend while",
|
|
1515
|
-
"\treturn null",
|
|
1516
|
-
"end function"
|
|
1517
|
-
].join(`
|
|
1518
|
-
`),
|
|
1519
|
-
assign_objects: [
|
|
1520
|
-
"assign_objects = function(target, source1, source2, source3)",
|
|
1521
|
-
"\tassign_to_list = function(target, source)",
|
|
1522
|
-
"\t\tif source isa list then",
|
|
1523
|
-
"\t\t\tfor i in range(0, source.len - 1, 1)",
|
|
1524
|
-
"\t\t\t\tif target.len <= i then target.push(null)",
|
|
1525
|
-
"\t\t\t\ttarget[i] = source[i]",
|
|
1526
|
-
"\t\t\tend for",
|
|
1527
|
-
"\t\telse if source isa map then",
|
|
1528
|
-
"\t\t\tfor item in source",
|
|
1529
|
-
"\t\t\t\tkey = str(item.key).to_int",
|
|
1530
|
-
"\t\t\t\tif key isa number then target[key] = item.value",
|
|
1531
|
-
"\t\t\tend for",
|
|
1532
|
-
"\t\tend if",
|
|
1533
|
-
"\t\treturn target",
|
|
1534
|
-
"\tend function",
|
|
1535
|
-
"\tcounter = 0",
|
|
1536
|
-
"\tassign_object = function(target, source)",
|
|
1537
|
-
"\t\tif target isa list then return assign_to_list(target, source)",
|
|
1538
|
-
"\t\tif source isa list then",
|
|
1539
|
-
"\t\t\tfor i in range(0, source.len - 1, 1)",
|
|
1540
|
-
"\t\t\t\ttarget[str(i)] = source[i]",
|
|
1541
|
-
"\t\t\tend for",
|
|
1542
|
-
"\t\telse if source isa map then",
|
|
1543
|
-
"\t\t\tfor item in source",
|
|
1544
|
-
"\t\t\t\ttarget[item.key] = item.value",
|
|
1545
|
-
"\t\t\tend for",
|
|
1546
|
-
"\t\telse",
|
|
1547
|
-
"\t\t\ttarget[str(outer.counter)] = source",
|
|
1548
|
-
"\t\t\touter.counter = outer.counter + 1",
|
|
1549
|
-
"\t\tend if",
|
|
1550
|
-
"\tend function",
|
|
1551
|
-
"\tif source1 isa list then",
|
|
1552
|
-
"\t\tif target isa list then return assign_to_list(target, source1)",
|
|
1553
|
-
"\t\tfor source in source1",
|
|
1554
|
-
"\t\t\tassign_object(target, source)",
|
|
1555
|
-
"\t\tend for",
|
|
1556
|
-
"\t\treturn target",
|
|
1557
|
-
"\tend if",
|
|
1558
|
-
"\tif source1 then assign_object(target, source1)",
|
|
1559
|
-
"\tif source2 then assign_object(target, source2)",
|
|
1560
|
-
"\tif source3 then assign_object(target, source3)",
|
|
1561
|
-
"\treturn target",
|
|
1562
|
-
"end function"
|
|
1563
|
-
].join(`
|
|
1564
|
-
`),
|
|
1565
|
-
array_map: [
|
|
1566
|
-
"array_map = function(array, callback)",
|
|
1441
|
+
var utilitiesToInsert = new Map;
|
|
1442
|
+
var extensionFunctions = {
|
|
1443
|
+
"Array.map": [
|
|
1444
|
+
"list.map = function(callback)",
|
|
1567
1445
|
"\tindex = 0",
|
|
1568
1446
|
"\tout = []",
|
|
1569
|
-
"\tfor item in
|
|
1570
|
-
"\t\tout.push(callback(item, index,
|
|
1447
|
+
"\tfor item in self",
|
|
1448
|
+
"\t\tout.push(callback(item, index, self))",
|
|
1571
1449
|
"\t\tindex = index + 1",
|
|
1572
1450
|
"\tend for",
|
|
1573
1451
|
"\treturn out",
|
|
1574
1452
|
"end function"
|
|
1575
1453
|
].join(`
|
|
1576
1454
|
`),
|
|
1577
|
-
|
|
1578
|
-
"
|
|
1455
|
+
"Array.filter": [
|
|
1456
|
+
"list.filter = function(predicate)",
|
|
1579
1457
|
"\tindex = 0",
|
|
1580
1458
|
"\tout = []",
|
|
1581
|
-
"\tfor item in
|
|
1582
|
-
"\t\tif predicate(item, index,
|
|
1459
|
+
"\tfor item in self",
|
|
1460
|
+
"\t\tif predicate(item, index, self) then out.push(item)",
|
|
1583
1461
|
"\t\tindex = index + 1",
|
|
1584
1462
|
"\tend for",
|
|
1585
1463
|
"\treturn out",
|
|
1586
1464
|
"end function"
|
|
1587
1465
|
].join(`
|
|
1588
1466
|
`),
|
|
1589
|
-
|
|
1590
|
-
"
|
|
1467
|
+
"Array.find": [
|
|
1468
|
+
"list.find = function(predicate)",
|
|
1591
1469
|
"\tindex = 0",
|
|
1592
|
-
"\tfor item in
|
|
1593
|
-
"\t\tif predicate(item, index,
|
|
1470
|
+
"\tfor item in self",
|
|
1471
|
+
"\t\tif predicate(item, index, self) then return item",
|
|
1594
1472
|
"\t\tindex = index + 1",
|
|
1595
1473
|
"\tend for",
|
|
1596
1474
|
"\treturn null",
|
|
1597
1475
|
"end function"
|
|
1598
1476
|
].join(`
|
|
1599
1477
|
`),
|
|
1600
|
-
|
|
1601
|
-
"
|
|
1478
|
+
"Array.some": [
|
|
1479
|
+
"list.some = function(predicate)",
|
|
1602
1480
|
"\tindex = 0",
|
|
1603
|
-
"\tfor item in
|
|
1604
|
-
"\t\tif predicate(item, index,
|
|
1481
|
+
"\tfor item in self",
|
|
1482
|
+
"\t\tif predicate(item, index, self) then return 1",
|
|
1605
1483
|
"\t\tindex = index + 1",
|
|
1606
1484
|
"\tend for",
|
|
1607
1485
|
"\treturn 0",
|
|
1608
1486
|
"end function"
|
|
1609
1487
|
].join(`
|
|
1610
1488
|
`),
|
|
1611
|
-
|
|
1612
|
-
"
|
|
1489
|
+
"Array.every": [
|
|
1490
|
+
"list.every = function(predicate)",
|
|
1613
1491
|
"\tindex = 0",
|
|
1614
|
-
"\tfor item in
|
|
1615
|
-
"\t\tif not predicate(item, index,
|
|
1492
|
+
"\tfor item in self",
|
|
1493
|
+
"\t\tif not predicate(item, index, self) then return 0",
|
|
1616
1494
|
"\t\tindex = index + 1",
|
|
1617
1495
|
"\tend for",
|
|
1618
1496
|
"\treturn 1",
|
|
1619
1497
|
"end function"
|
|
1620
1498
|
].join(`
|
|
1621
1499
|
`),
|
|
1622
|
-
|
|
1623
|
-
"
|
|
1624
|
-
"\tout =
|
|
1500
|
+
"Array.concat": [
|
|
1501
|
+
"list.concat = function(items)",
|
|
1502
|
+
"\tout = self[0:]",
|
|
1625
1503
|
"\tfor item in items",
|
|
1626
1504
|
"\t\tif item isa list then out = out + item else out.push(item)",
|
|
1627
1505
|
"\tend for",
|
|
@@ -1629,58 +1507,141 @@ var utilFunctions2 = {
|
|
|
1629
1507
|
"end function"
|
|
1630
1508
|
].join(`
|
|
1631
1509
|
`),
|
|
1632
|
-
|
|
1633
|
-
"
|
|
1510
|
+
"Array.push": [
|
|
1511
|
+
"list.push_many = function(items)",
|
|
1634
1512
|
"\tfor item in items[:]",
|
|
1635
|
-
"\t\
|
|
1513
|
+
"\t\tself.push(@item)",
|
|
1636
1514
|
"\tend for",
|
|
1637
|
-
"\treturn
|
|
1515
|
+
"\treturn self.len",
|
|
1638
1516
|
"end function"
|
|
1639
1517
|
].join(`
|
|
1640
1518
|
`),
|
|
1641
|
-
|
|
1642
|
-
"
|
|
1643
|
-
"\tif not items.len then return
|
|
1519
|
+
"Array.unshift": [
|
|
1520
|
+
"list.unshift = function(items)",
|
|
1521
|
+
"\tif not items.len then return self.len",
|
|
1644
1522
|
"\tfor i in range(items.len-1)",
|
|
1645
|
-
"\t\
|
|
1523
|
+
"\t\tself.insert(0, items[i])",
|
|
1646
1524
|
"\tend for",
|
|
1647
|
-
"\treturn
|
|
1525
|
+
"\treturn self.len",
|
|
1648
1526
|
"end function"
|
|
1649
1527
|
].join(`
|
|
1650
1528
|
`),
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
"str_starts_with = function(str, search, pos = 0)",
|
|
1657
|
-
"\tif pos < 0 then pos = 0",
|
|
1658
|
-
"\treturn str.indexOf(search) == pos",
|
|
1529
|
+
"Array.reverse": [
|
|
1530
|
+
"list.old_reverse = @list.reverse",
|
|
1531
|
+
"list.reverse = function",
|
|
1532
|
+
"\tself.old_reverse",
|
|
1533
|
+
"\treturn self",
|
|
1659
1534
|
"end function"
|
|
1660
1535
|
].join(`
|
|
1661
1536
|
`),
|
|
1662
|
-
|
|
1663
|
-
"
|
|
1664
|
-
"\
|
|
1537
|
+
"Array.includes": [
|
|
1538
|
+
"list.includes = function(value, pos = 0)",
|
|
1539
|
+
"\tindex = self.indexOf(value)",
|
|
1540
|
+
"\tif index == null then return 0",
|
|
1665
1541
|
"\tif pos < 0 then pos = 0",
|
|
1666
|
-
"\treturn
|
|
1542
|
+
"\treturn index >= pos",
|
|
1667
1543
|
"end function"
|
|
1668
1544
|
].join(`
|
|
1669
1545
|
`),
|
|
1670
|
-
|
|
1671
|
-
"
|
|
1672
|
-
|
|
1673
|
-
"\tif
|
|
1674
|
-
"\
|
|
1675
|
-
"\
|
|
1676
|
-
"\
|
|
1546
|
+
"Array.splice": [
|
|
1547
|
+
"list.splice = function(start, count)",
|
|
1548
|
+
"\tdeleted = []",
|
|
1549
|
+
"\tif start < 0 then start = self.len + start",
|
|
1550
|
+
"\tif start < 0 then start = 0",
|
|
1551
|
+
"\tif count == null then count = self.len - start",
|
|
1552
|
+
"\tif count <= 0 then return deleted",
|
|
1553
|
+
"\twhile deleted.len < count",
|
|
1554
|
+
"\t\tif not self.hasIndex(start) then return deleted",
|
|
1555
|
+
"\t\tdeleted.push(self[start])",
|
|
1556
|
+
"\t\tself.remove(start)",
|
|
1557
|
+
"\tend while",
|
|
1558
|
+
"\treturn deleted",
|
|
1559
|
+
"end function"
|
|
1560
|
+
].join(`
|
|
1561
|
+
`),
|
|
1562
|
+
"Array.fill": [
|
|
1563
|
+
"list.fill = function(value, start, endI)",
|
|
1564
|
+
"\tlen = self.len",
|
|
1565
|
+
"\tif not len then return self",
|
|
1566
|
+
"\tif start == null then start = 0",
|
|
1567
|
+
"\tif endI == null then endI = len - 1",
|
|
1568
|
+
"\tif start < 0 then start = len + start",
|
|
1569
|
+
"\tif start < 0 then start = 0",
|
|
1570
|
+
"\tif endI < 0 then endI = len + endI",
|
|
1571
|
+
"\tif endI < 0 then endI = 0",
|
|
1572
|
+
"\tfor i in range(start, endI-1, 1)",
|
|
1573
|
+
"\t\tif i >= len then break",
|
|
1574
|
+
"\t\tself[i] = value",
|
|
1677
1575
|
"\tend for",
|
|
1678
|
-
"\treturn
|
|
1576
|
+
"\treturn self",
|
|
1577
|
+
"end function"
|
|
1578
|
+
].join(`
|
|
1579
|
+
`),
|
|
1580
|
+
"String.startsWith": [
|
|
1581
|
+
"string.startsWith = function(search, pos = 0)",
|
|
1582
|
+
"\tif pos < 0 then pos = 0",
|
|
1583
|
+
"\treturn self.indexOf(search) == pos",
|
|
1584
|
+
"end function"
|
|
1585
|
+
].join(`
|
|
1586
|
+
`),
|
|
1587
|
+
"String.endsWith": [
|
|
1588
|
+
"string.endsWith = function(search, pos = null)",
|
|
1589
|
+
"\tif pos == null then pos = self.len",
|
|
1590
|
+
"\tif pos < 0 then pos = 0",
|
|
1591
|
+
"\treturn self.indexOf(search) + search.len == pos",
|
|
1592
|
+
"end function"
|
|
1593
|
+
].join(`
|
|
1594
|
+
`),
|
|
1595
|
+
"String.repeat": [
|
|
1596
|
+
"string.repeatSelf = function(count = 0)",
|
|
1597
|
+
"\treturn self * count",
|
|
1598
|
+
"end function"
|
|
1599
|
+
].join(`
|
|
1600
|
+
`),
|
|
1601
|
+
"String.includes": [
|
|
1602
|
+
"string.includes = function(search, pos = 0)",
|
|
1603
|
+
"\tindex = self.indexOf(search)",
|
|
1604
|
+
"\tif index == null then return 0",
|
|
1605
|
+
"\tif pos < 0 then pos = 0",
|
|
1606
|
+
"\treturn index >= pos",
|
|
1607
|
+
"end function"
|
|
1608
|
+
].join(`
|
|
1609
|
+
`),
|
|
1610
|
+
"String.trimStart": [
|
|
1611
|
+
"string.trimStart = function()",
|
|
1612
|
+
'\treturn self.replace("^\\s+", "")',
|
|
1613
|
+
"end function"
|
|
1614
|
+
].join(`
|
|
1615
|
+
`),
|
|
1616
|
+
"String.trimEnd": [
|
|
1617
|
+
"string.trimEnd = function()",
|
|
1618
|
+
'\treturn self.replace("\\s+$", "")',
|
|
1679
1619
|
"end function"
|
|
1680
1620
|
].join(`
|
|
1681
1621
|
`),
|
|
1682
|
-
|
|
1683
|
-
"
|
|
1622
|
+
"Number.toFixed": [
|
|
1623
|
+
"number.toFixed = function(digits = 0)",
|
|
1624
|
+
"\tdigits = floor(digits)",
|
|
1625
|
+
"\tif digits <= 0 then return str(round(self))",
|
|
1626
|
+
"\tvalue = self",
|
|
1627
|
+
"\tvalue = value * (10 ^ digits)",
|
|
1628
|
+
"\tvalue = round(value)",
|
|
1629
|
+
"\tvalue = value / (10 ^ digits)",
|
|
1630
|
+
"\t",
|
|
1631
|
+
"\tstr_value = str(value)",
|
|
1632
|
+
'\tdot_index = str_value.indexOf(".")',
|
|
1633
|
+
"\tif dot_index == null then",
|
|
1634
|
+
'\t\tstr_value = str_value + "." + ("0" * digits)',
|
|
1635
|
+
"\telse if str_value[dot_index + 1:].len < digits then",
|
|
1636
|
+
"\t\trepeat_count = digits - str_value[dot_index + 1:].len",
|
|
1637
|
+
'\t\tstr_value = str_value + ("0" * repeat_count)',
|
|
1638
|
+
"\tend if",
|
|
1639
|
+
"\treturn str_value",
|
|
1640
|
+
"end function"
|
|
1641
|
+
].join(`
|
|
1642
|
+
`),
|
|
1643
|
+
"Math.min": [
|
|
1644
|
+
"Math.min = function(numbers)",
|
|
1684
1645
|
"\tcurr_min = null",
|
|
1685
1646
|
"\tfor num in numbers",
|
|
1686
1647
|
"\t\tif curr_min == null or num < curr_min then curr_min = num",
|
|
@@ -1689,8 +1650,8 @@ end function`,
|
|
|
1689
1650
|
"end function"
|
|
1690
1651
|
].join(`
|
|
1691
1652
|
`),
|
|
1692
|
-
|
|
1693
|
-
"
|
|
1653
|
+
"Math.max": [
|
|
1654
|
+
"Math.max = function(numbers)",
|
|
1694
1655
|
"\tcurr_max = null",
|
|
1695
1656
|
"\tfor num in numbers",
|
|
1696
1657
|
"\t\tif curr_max == null or num > curr_max then curr_max = num",
|
|
@@ -1698,6 +1659,83 @@ end function`,
|
|
|
1698
1659
|
"\treturn curr_max",
|
|
1699
1660
|
"end function"
|
|
1700
1661
|
].join(`
|
|
1662
|
+
`)
|
|
1663
|
+
};
|
|
1664
|
+
var utilFunctions = {
|
|
1665
|
+
get_property: [
|
|
1666
|
+
"get_property = function(obj, key)",
|
|
1667
|
+
"\tif not obj then return null",
|
|
1668
|
+
"\tif obj.hasIndex(key) then return obj[key]",
|
|
1669
|
+
"\tisaobj = obj",
|
|
1670
|
+
'\twhile isaobj.hasIndex("__isa")',
|
|
1671
|
+
'\t\tisaobj = obj["__isa"]',
|
|
1672
|
+
"\t\tif isaobj.hasIndex(key) then",
|
|
1673
|
+
"\t\t\tres = obj[key]",
|
|
1674
|
+
'\t\t\tif typeof(@res) == "function" and str(@res)[8:][1:-1].indexOf("self") == 0 then return res(obj)',
|
|
1675
|
+
"\t\t\treturn obj[key]",
|
|
1676
|
+
"\t\tend if",
|
|
1677
|
+
"\tend while",
|
|
1678
|
+
"\treturn null",
|
|
1679
|
+
"end function"
|
|
1680
|
+
].join(`
|
|
1681
|
+
`),
|
|
1682
|
+
assign_objects: [
|
|
1683
|
+
"assign_objects = function(target, source1, source2, source3)",
|
|
1684
|
+
"\tassign_to_list = function(target, source)",
|
|
1685
|
+
"\t\tif source isa list then",
|
|
1686
|
+
"\t\t\tfor i in range(0, source.len - 1, 1)",
|
|
1687
|
+
"\t\t\t\tif target.len <= i then target.push(null)",
|
|
1688
|
+
"\t\t\t\ttarget[i] = source[i]",
|
|
1689
|
+
"\t\t\tend for",
|
|
1690
|
+
"\t\telse if source isa map then",
|
|
1691
|
+
"\t\t\tfor item in source",
|
|
1692
|
+
"\t\t\t\tkey = str(item.key).to_int",
|
|
1693
|
+
"\t\t\t\tif key isa number then target[key] = item.value",
|
|
1694
|
+
"\t\t\tend for",
|
|
1695
|
+
"\t\tend if",
|
|
1696
|
+
"\t\treturn target",
|
|
1697
|
+
"\tend function",
|
|
1698
|
+
"\tcounter = 0",
|
|
1699
|
+
"\tassign_object = function(target, source)",
|
|
1700
|
+
"\t\tif target isa list then return assign_to_list(target, source)",
|
|
1701
|
+
"\t\tif source isa list then",
|
|
1702
|
+
"\t\t\tfor i in range(0, source.len - 1, 1)",
|
|
1703
|
+
"\t\t\t\ttarget[str(i)] = source[i]",
|
|
1704
|
+
"\t\t\tend for",
|
|
1705
|
+
"\t\telse if source isa map then",
|
|
1706
|
+
"\t\t\tfor item in source",
|
|
1707
|
+
"\t\t\t\ttarget[item.key] = item.value",
|
|
1708
|
+
"\t\t\tend for",
|
|
1709
|
+
"\t\telse",
|
|
1710
|
+
"\t\t\ttarget[str(outer.counter)] = source",
|
|
1711
|
+
"\t\t\touter.counter = outer.counter + 1",
|
|
1712
|
+
"\t\tend if",
|
|
1713
|
+
"\tend function",
|
|
1714
|
+
"\tif source1 isa list then",
|
|
1715
|
+
"\t\tif target isa list then return assign_to_list(target, source1)",
|
|
1716
|
+
"\t\tfor source in source1",
|
|
1717
|
+
"\t\t\tassign_object(target, source)",
|
|
1718
|
+
"\t\tend for",
|
|
1719
|
+
"\t\treturn target",
|
|
1720
|
+
"\tend if",
|
|
1721
|
+
"\tif source1 then assign_object(target, source1)",
|
|
1722
|
+
"\tif source2 then assign_object(target, source2)",
|
|
1723
|
+
"\tif source3 then assign_object(target, source3)",
|
|
1724
|
+
"\treturn target",
|
|
1725
|
+
"end function"
|
|
1726
|
+
].join(`
|
|
1727
|
+
`),
|
|
1728
|
+
instance_of: [
|
|
1729
|
+
"instance_of = function(obj, class)",
|
|
1730
|
+
'\tif not obj.hasIndex("__isa") then return 0',
|
|
1731
|
+
"\tisaobj = obj",
|
|
1732
|
+
'\twhile isaobj.hasIndex("__isa")',
|
|
1733
|
+
'\t\tif isaobj["__isa"] == class then return 1',
|
|
1734
|
+
'\t\tisaobj = isaobj["__isa"]',
|
|
1735
|
+
"\tend while",
|
|
1736
|
+
"\treturn 0",
|
|
1737
|
+
"end function"
|
|
1738
|
+
].join(`
|
|
1701
1739
|
`),
|
|
1702
1740
|
nullish_coalescing_op: `nullish_coalescing_op = function(left, right)
|
|
1703
1741
|
if left == null then return @right
|
|
@@ -1708,8 +1746,7 @@ end function`,
|
|
|
1708
1746
|
return @left
|
|
1709
1747
|
end function`,
|
|
1710
1748
|
is_type: `is_type = function(value, type)
|
|
1711
|
-
|
|
1712
|
-
return 0
|
|
1749
|
+
return typeof(value) == type
|
|
1713
1750
|
end function`,
|
|
1714
1751
|
conditional_expr: `conditional_expr = function(cond, when_true, when_false)
|
|
1715
1752
|
if cond then return when_true
|
|
@@ -1718,12 +1755,12 @@ end function`
|
|
|
1718
1755
|
};
|
|
1719
1756
|
function createAnonFunction(body, params) {
|
|
1720
1757
|
const defaultParams = new Array(3).fill(0).map((_, i) => `param${i}`);
|
|
1721
|
-
const nextName = `func_${
|
|
1758
|
+
const nextName = `func_${utilitiesToInsert.size}`;
|
|
1722
1759
|
const paramString = Object.assign(defaultParams, params).join(",");
|
|
1723
1760
|
const result = `${nextName} = function(${paramString})
|
|
1724
1761
|
${body}
|
|
1725
1762
|
end function`;
|
|
1726
|
-
|
|
1763
|
+
utilitiesToInsert.set(nextName, result);
|
|
1727
1764
|
return { name: nextName, str: result };
|
|
1728
1765
|
}
|
|
1729
1766
|
function transpileProgram(entryFileRelativePath) {
|
|
@@ -1764,19 +1801,12 @@ function transpileProgram(entryFileRelativePath) {
|
|
|
1764
1801
|
process.exit(1);
|
|
1765
1802
|
}
|
|
1766
1803
|
transpileSourceFile(entry, ctx);
|
|
1767
|
-
if (
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
anonFunctions.clear();
|
|
1771
|
-
}
|
|
1772
|
-
if (calledUtilFunctions.size) {
|
|
1773
|
-
for (const call of calledUtilFunctions.keys())
|
|
1774
|
-
ctx.output.unshift(utilFunctions2[call]);
|
|
1775
|
-
calledUtilFunctions.clear();
|
|
1804
|
+
if (utilitiesToInsert.size) {
|
|
1805
|
+
ctx.output.unshift(...utilitiesToInsert.values());
|
|
1806
|
+
utilitiesToInsert.clear();
|
|
1776
1807
|
}
|
|
1777
1808
|
console.log(`Transpiling took ${Date.now() - start} ms`);
|
|
1778
|
-
return ctx.output
|
|
1779
|
-
`);
|
|
1809
|
+
return ctx.output;
|
|
1780
1810
|
}
|
|
1781
1811
|
function transpileSourceFile(sourceFile, ctx, returnResult) {
|
|
1782
1812
|
if (ctx.visitedFiles[sourceFile.fileName])
|
|
@@ -1828,27 +1858,54 @@ for (let i = 2;i < process.argv.length; i++) {
|
|
|
1828
1858
|
args.push(arg);
|
|
1829
1859
|
}
|
|
1830
1860
|
var root = findProjectRoot(process.cwd());
|
|
1861
|
+
var outDirPath = `${root}/out`;
|
|
1831
1862
|
if (!command) {
|
|
1832
1863
|
console.error("No command specified.");
|
|
1833
1864
|
process.exit(2);
|
|
1834
1865
|
}
|
|
1866
|
+
function createOutputFile(fileIndex, basename, content) {
|
|
1867
|
+
if (fileIndex > 0)
|
|
1868
|
+
basename = `${basename}-${fileIndex}`;
|
|
1869
|
+
const outFileName = args.length > 1 ? args[1] : `${basename}.src`;
|
|
1870
|
+
const outFilePath = path5.join(outDirPath, outFileName);
|
|
1871
|
+
fs3.writeFileSync(outFilePath, content);
|
|
1872
|
+
}
|
|
1835
1873
|
if (command === "transpile") {
|
|
1836
1874
|
if (!args.length) {
|
|
1837
1875
|
console.error("No entry file specified.");
|
|
1838
1876
|
process.exit(2);
|
|
1839
1877
|
}
|
|
1840
1878
|
const entryFile = args[0];
|
|
1841
|
-
const
|
|
1879
|
+
const basename = path5.basename(entryFile, ".ts");
|
|
1880
|
+
const transpiledStatements = transpileProgram(entryFile);
|
|
1842
1881
|
if (flags.includes("--print") || flags.includes("-p")) {
|
|
1843
|
-
console.log(
|
|
1882
|
+
console.log(transpiledStatements.join(`
|
|
1883
|
+
`));
|
|
1844
1884
|
process.exit(0);
|
|
1845
1885
|
}
|
|
1846
|
-
const outDirPath = `${root}/out`;
|
|
1847
1886
|
if (!fs3.existsSync(outDirPath))
|
|
1848
1887
|
fs3.mkdirSync(outDirPath);
|
|
1849
|
-
|
|
1850
|
-
const
|
|
1851
|
-
|
|
1888
|
+
let content = "";
|
|
1889
|
+
const fileContents = [];
|
|
1890
|
+
while (transpiledStatements.length) {
|
|
1891
|
+
const statement = transpiledStatements.shift();
|
|
1892
|
+
if (content.length + statement.length > 155000 && content.length) {
|
|
1893
|
+
fileContents.push(content);
|
|
1894
|
+
content = "";
|
|
1895
|
+
continue;
|
|
1896
|
+
}
|
|
1897
|
+
content += statement + `
|
|
1898
|
+
`;
|
|
1899
|
+
}
|
|
1900
|
+
if (content.length)
|
|
1901
|
+
fileContents.push(content);
|
|
1902
|
+
for (let i = 0;i < fileContents.length; i++) {
|
|
1903
|
+
if (i + 1 < fileContents.length) {
|
|
1904
|
+
const nextFileName = `${basename}-${i + 1}.src`;
|
|
1905
|
+
fileContents[i] += `import_code("${nextFileName}")`;
|
|
1906
|
+
}
|
|
1907
|
+
createOutputFile(i, basename, fileContents[i]);
|
|
1908
|
+
}
|
|
1852
1909
|
} else {
|
|
1853
1910
|
console.log(`Invalid command: ${command}`);
|
|
1854
1911
|
process.exit(127);
|