@grey-ts/transpiler 2.0.0 → 2.1.1
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 +268 -193
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import path6 from "node:path";
|
|
|
7
7
|
// src/transpiler.ts
|
|
8
8
|
import * as fs2 from "node:fs";
|
|
9
9
|
import * as path5 from "node:path";
|
|
10
|
-
import
|
|
10
|
+
import ts15 from "typescript";
|
|
11
11
|
|
|
12
12
|
// src/nodeHandler.ts
|
|
13
13
|
import * as path from "node:path";
|
|
@@ -33,9 +33,9 @@ class NodeHandler {
|
|
|
33
33
|
if (!extra)
|
|
34
34
|
return result;
|
|
35
35
|
return [
|
|
36
|
-
...extra.before
|
|
36
|
+
...extra.before,
|
|
37
37
|
result,
|
|
38
|
-
...extra.after
|
|
38
|
+
...extra.after
|
|
39
39
|
].join(`
|
|
40
40
|
`);
|
|
41
41
|
} catch (error) {
|
|
@@ -47,13 +47,13 @@ class NodeHandler {
|
|
|
47
47
|
static addExtraOutput(node, before, after) {
|
|
48
48
|
let extra = this.transpileContext.extraOutput.get(node);
|
|
49
49
|
if (!extra) {
|
|
50
|
-
extra = { before:
|
|
50
|
+
extra = { before: [], after: [] };
|
|
51
51
|
this.transpileContext.extraOutput.set(node, extra);
|
|
52
52
|
}
|
|
53
53
|
if (before)
|
|
54
|
-
extra.before
|
|
54
|
+
extra.before.push(before);
|
|
55
55
|
if (after)
|
|
56
|
-
extra.after
|
|
56
|
+
extra.after.push(after);
|
|
57
57
|
}
|
|
58
58
|
static printLineAndCol(node) {
|
|
59
59
|
const source = node.getSourceFile();
|
|
@@ -259,9 +259,7 @@ var apiNameMap = {
|
|
|
259
259
|
"Object.size": "len",
|
|
260
260
|
"Array.length": "len",
|
|
261
261
|
"Array.shift": "pull",
|
|
262
|
-
"Array.push": "push_many"
|
|
263
|
-
"Map.size": "data.len",
|
|
264
|
-
"Set.size": "data.len"
|
|
262
|
+
"Array.push": "push_many"
|
|
265
263
|
};
|
|
266
264
|
var propertyAccessReplacements = {
|
|
267
265
|
"String.prototype": "string",
|
|
@@ -299,6 +297,13 @@ var knownOperators = new Set([
|
|
|
299
297
|
"*",
|
|
300
298
|
"/",
|
|
301
299
|
"%",
|
|
300
|
+
"*=",
|
|
301
|
+
"/=",
|
|
302
|
+
"%=",
|
|
303
|
+
"**=",
|
|
304
|
+
"<<=",
|
|
305
|
+
">>=",
|
|
306
|
+
">>>=",
|
|
302
307
|
"~",
|
|
303
308
|
"&",
|
|
304
309
|
"|",
|
|
@@ -416,7 +421,14 @@ var assignmentOperators = new Set([
|
|
|
416
421
|
"??=",
|
|
417
422
|
"||=",
|
|
418
423
|
"-=",
|
|
419
|
-
"+="
|
|
424
|
+
"+=",
|
|
425
|
+
"*=",
|
|
426
|
+
"/=",
|
|
427
|
+
"%=",
|
|
428
|
+
"**=",
|
|
429
|
+
"<<=",
|
|
430
|
+
">>=",
|
|
431
|
+
">>>="
|
|
420
432
|
]);
|
|
421
433
|
function valueIsBeingAssignedToNode(node) {
|
|
422
434
|
if (ts3.hasOnlyExpressionInitializer(node.parent) && node === node.parent.name)
|
|
@@ -450,21 +462,90 @@ NodeHandler.register(ts4.SyntaxKind.ComputedPropertyName, (node) => {
|
|
|
450
462
|
});
|
|
451
463
|
|
|
452
464
|
// src/visitors/classes.ts
|
|
465
|
+
import ts6 from "typescript";
|
|
466
|
+
|
|
467
|
+
// src/visitors/functions.ts
|
|
453
468
|
import ts5 from "typescript";
|
|
454
|
-
|
|
469
|
+
function handleFunctionBodyAndParams(node, ctx) {
|
|
470
|
+
const oldBindingElements = Object.keys(ctx.bindingElements);
|
|
471
|
+
const params = node.parameters.map((param) => NodeHandler.handle(param));
|
|
472
|
+
const newBindingElements = Object.keys(ctx.bindingElements).filter((b) => !oldBindingElements.includes(b));
|
|
473
|
+
const body = !node.body ? "" : ts5.isBlock(node.body) ? NodeHandler.handle(node.body) : ` return ${NodeHandler.handle(node.body)}`;
|
|
474
|
+
for (const bindingElement of newBindingElements) {
|
|
475
|
+
delete ctx.bindingElements[bindingElement];
|
|
476
|
+
}
|
|
477
|
+
const functionOutput = [
|
|
478
|
+
`function${params.length ? `(${params.join(", ")})` : ""}`,
|
|
479
|
+
...body ? [body] : [],
|
|
480
|
+
`end function`
|
|
481
|
+
].join(`
|
|
482
|
+
`);
|
|
483
|
+
return {
|
|
484
|
+
body,
|
|
485
|
+
params,
|
|
486
|
+
functionOutput
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
NodeHandler.register(ts5.SyntaxKind.Block, (node) => {
|
|
490
|
+
const output = node.statements.map((val) => {
|
|
491
|
+
let statement = NodeHandler.handle(val);
|
|
492
|
+
statement = statement.split(`
|
|
493
|
+
`).filter((s) => !!s).map((line) => ` ${line}`).join(`
|
|
494
|
+
`);
|
|
495
|
+
return statement;
|
|
496
|
+
}).filter((s) => !!s).join(`
|
|
497
|
+
`);
|
|
498
|
+
return output;
|
|
499
|
+
});
|
|
500
|
+
NodeHandler.register(ts5.SyntaxKind.MethodDeclaration, (node, ctx) => {
|
|
501
|
+
const func = handleFunctionBodyAndParams(node, ctx);
|
|
502
|
+
return `${NodeHandler.handle(node.name)} = ${func.functionOutput}`;
|
|
503
|
+
});
|
|
504
|
+
NodeHandler.register(ts5.SyntaxKind.FunctionDeclaration, (node, ctx) => {
|
|
505
|
+
if (!node.body)
|
|
506
|
+
return "";
|
|
455
507
|
if (node.modifiers?.some((m) => m.kind === ts5.SyntaxKind.DeclareKeyword))
|
|
456
508
|
return "";
|
|
509
|
+
const func = handleFunctionBodyAndParams(node, ctx);
|
|
457
510
|
const name = node.name ? node.name.text : "anon";
|
|
458
|
-
|
|
511
|
+
return `${name} = ${func.functionOutput}`;
|
|
512
|
+
});
|
|
513
|
+
NodeHandler.register(ts5.SyntaxKind.ArrowFunction, (node, ctx) => {
|
|
514
|
+
const func = handleFunctionBodyAndParams(node, ctx);
|
|
515
|
+
if (ts5.isCallOrNewExpression(node.parent) || ts5.isParenthesizedExpression(node.parent)) {
|
|
516
|
+
const mainNode = ts5.findAncestor(node.parent, (n) => n.parent && (ts5.isBlock(n.parent) || ts5.isSourceFile(n.parent)));
|
|
517
|
+
if (!mainNode) {
|
|
518
|
+
return `@${createAnonFunction(func.body, func.params).name}`;
|
|
519
|
+
}
|
|
520
|
+
const anon = createAnonFunction(func.body, func.params, false);
|
|
521
|
+
NodeHandler.addExtraOutput(mainNode, anon.str, null);
|
|
522
|
+
return `@${anon.name}`;
|
|
523
|
+
}
|
|
524
|
+
if (ts5.hasOnlyExpressionInitializer(node.parent) || ts5.isBinaryExpression(node.parent) || ts5.isReturnStatement(node.parent)) {
|
|
525
|
+
return func.functionOutput;
|
|
526
|
+
}
|
|
527
|
+
const kind = ts5.SyntaxKind[node.parent.kind];
|
|
528
|
+
throw `This kind of arrow function is not yet supported (parent: ${kind} (${node.parent.kind}))`;
|
|
529
|
+
});
|
|
530
|
+
NodeHandler.register(ts5.SyntaxKind.FunctionExpression, (node, ctx) => {
|
|
531
|
+
return handleFunctionBodyAndParams(node, ctx).functionOutput;
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
// src/visitors/classes.ts
|
|
535
|
+
NodeHandler.register(ts6.SyntaxKind.ClassDeclaration, (node) => {
|
|
536
|
+
if (node.modifiers?.some((m) => m.kind === ts6.SyntaxKind.DeclareKeyword))
|
|
537
|
+
return "";
|
|
538
|
+
const name = node.name ? node.name.text : "anon";
|
|
539
|
+
const extensions = node.heritageClauses?.filter((h) => h.token === ts6.SyntaxKind.ExtendsKeyword);
|
|
459
540
|
let output = `${name} = {}`;
|
|
460
541
|
if (extensions?.length && extensions[0].types.length)
|
|
461
542
|
output = `${name} = new ${NodeHandler.handle(extensions[0].types[0].expression)}`;
|
|
462
543
|
const declaredNames = new Set;
|
|
463
544
|
let hasConstructor = false;
|
|
464
545
|
for (const member of node.members) {
|
|
465
|
-
if (
|
|
546
|
+
if (ts6.isFunctionLike(member) && "body" in member && !member.body)
|
|
466
547
|
continue;
|
|
467
|
-
if (
|
|
548
|
+
if (ts6.isSemicolonClassElement(member))
|
|
468
549
|
continue;
|
|
469
550
|
if (member.name) {
|
|
470
551
|
const memberName = NodeHandler.handle(member.name);
|
|
@@ -473,78 +554,67 @@ NodeHandler.register(ts5.SyntaxKind.ClassDeclaration, (node) => {
|
|
|
473
554
|
Modifiers such as 'static' are only for TypeScript for now and are not differentiated in the transpiled version from normal declarations for now`;
|
|
474
555
|
declaredNames.add(memberName);
|
|
475
556
|
}
|
|
476
|
-
if (
|
|
557
|
+
if (ts6.isConstructorDeclaration(member))
|
|
477
558
|
hasConstructor = true;
|
|
478
559
|
output += `
|
|
479
560
|
${name}.${NodeHandler.handle(member)}`;
|
|
480
561
|
}
|
|
481
|
-
if (!hasConstructor && !node.modifiers?.some((m) => m.kind ===
|
|
562
|
+
if (!hasConstructor && !node.modifiers?.some((m) => m.kind === ts6.SyntaxKind.AbstractKeyword))
|
|
482
563
|
output += `
|
|
483
564
|
${name}.constructor = function
|
|
484
565
|
return self
|
|
485
566
|
end function`;
|
|
486
567
|
return output;
|
|
487
568
|
});
|
|
488
|
-
NodeHandler.register(
|
|
569
|
+
NodeHandler.register(ts6.SyntaxKind.Constructor, (node, ctx) => {
|
|
489
570
|
if (!node.body)
|
|
490
571
|
return "";
|
|
491
|
-
const
|
|
492
|
-
|
|
493
|
-
const
|
|
494
|
-
if (param.modifiers) {
|
|
495
|
-
const paramName = NodeHandler.handle(param.name);
|
|
496
|
-
const declaration = ` self.${paramName} = ${paramName}`;
|
|
497
|
-
declaredProperties.push(declaration);
|
|
498
|
-
}
|
|
499
|
-
return res;
|
|
500
|
-
}).join(", ");
|
|
501
|
-
let body = NodeHandler.handle(node.body);
|
|
502
|
-
if (declaredProperties.length) {
|
|
503
|
-
const propertiesStr = declaredProperties.join(`
|
|
572
|
+
const func = handleFunctionBodyAndParams(node, ctx);
|
|
573
|
+
if (ctx.parameterProperties.length) {
|
|
574
|
+
const propertiesStr = ctx.parameterProperties.join(`
|
|
504
575
|
`);
|
|
505
|
-
|
|
576
|
+
ctx.parameterProperties.length = 0;
|
|
577
|
+
const lines = func.body.split(`
|
|
506
578
|
`);
|
|
507
579
|
const superIndex = lines.findIndex((line) => line.includes("super.constructor"));
|
|
508
580
|
if (superIndex !== -1) {
|
|
509
|
-
body = `${lines.slice(0, superIndex + 1).join(`
|
|
581
|
+
func.body = `${lines.slice(0, superIndex + 1).join(`
|
|
510
582
|
`)}
|
|
511
583
|
${propertiesStr}
|
|
512
584
|
${lines.slice(superIndex + 1).join(`
|
|
513
585
|
`)}`;
|
|
514
586
|
} else {
|
|
515
|
-
body = `${propertiesStr}
|
|
516
|
-
${body}`;
|
|
587
|
+
func.body = `${propertiesStr}
|
|
588
|
+
${func.body}`;
|
|
517
589
|
}
|
|
518
590
|
}
|
|
519
|
-
return
|
|
520
|
-
${
|
|
521
|
-
|
|
522
|
-
|
|
591
|
+
return [
|
|
592
|
+
`constructor = function${func.params.length ? `(${func.params.join(", ")})` : ""}`,
|
|
593
|
+
...func.body ? [func.body] : [],
|
|
594
|
+
"\treturn self",
|
|
595
|
+
`end function`
|
|
596
|
+
].join(`
|
|
597
|
+
`);
|
|
523
598
|
});
|
|
524
|
-
NodeHandler.register(
|
|
599
|
+
NodeHandler.register(ts6.SyntaxKind.GetAccessor, (node, ctx) => {
|
|
525
600
|
if (!node.body)
|
|
526
601
|
return "";
|
|
527
|
-
const
|
|
528
|
-
return `${NodeHandler.handle(node.name)} =
|
|
529
|
-
${body}
|
|
530
|
-
end function`;
|
|
602
|
+
const func = handleFunctionBodyAndParams(node, ctx);
|
|
603
|
+
return `${NodeHandler.handle(node.name)} = ${func.functionOutput}`;
|
|
531
604
|
});
|
|
532
|
-
NodeHandler.register(
|
|
605
|
+
NodeHandler.register(ts6.SyntaxKind.SetAccessor, (node, ctx) => {
|
|
533
606
|
if (!node.body)
|
|
534
607
|
return "";
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
return `set_${NodeHandler.handle(node.name)} = function(${params.join(", ")})
|
|
538
|
-
${body}
|
|
539
|
-
end function`;
|
|
608
|
+
const func = handleFunctionBodyAndParams(node, ctx);
|
|
609
|
+
return `set_${NodeHandler.handle(node.name)} = ${func.functionOutput}`;
|
|
540
610
|
});
|
|
541
611
|
|
|
542
612
|
// src/visitors/expressions.ts
|
|
543
|
-
import
|
|
613
|
+
import ts8 from "typescript";
|
|
544
614
|
|
|
545
615
|
// src/call_transformers/callTransformer.ts
|
|
546
616
|
import path3 from "node:path";
|
|
547
|
-
import
|
|
617
|
+
import ts7 from "typescript";
|
|
548
618
|
class CallTransformer {
|
|
549
619
|
static handlers = new Map;
|
|
550
620
|
static register(symbolFullName, handler) {
|
|
@@ -587,7 +657,7 @@ CallTransformer.register("GreyHack.include", (_name, _args, node, ctx) => {
|
|
|
587
657
|
if (!node.arguments.length)
|
|
588
658
|
return "";
|
|
589
659
|
const fileArg = node.arguments[0];
|
|
590
|
-
if (!
|
|
660
|
+
if (!ts7.isStringLiteralLike(fileArg))
|
|
591
661
|
throw "You can't include variables";
|
|
592
662
|
const absPath = path3.resolve(ctx.currentFolder, fileArg.text);
|
|
593
663
|
const sources = getSourceFiles(absPath);
|
|
@@ -620,7 +690,7 @@ function hasRestParam(params) {
|
|
|
620
690
|
if (!params.length)
|
|
621
691
|
return false;
|
|
622
692
|
const lastParam = params[params.length - 1];
|
|
623
|
-
return !!(lastParam.valueDeclaration &&
|
|
693
|
+
return !!(lastParam.valueDeclaration && ts8.isParameter(lastParam.valueDeclaration) && lastParam.valueDeclaration.dotDotDotToken);
|
|
624
694
|
}
|
|
625
695
|
function handleCallArgs(callNode, ctx) {
|
|
626
696
|
const args = callNode.arguments;
|
|
@@ -644,11 +714,11 @@ function handleCallArgs(callNode, ctx) {
|
|
|
644
714
|
}
|
|
645
715
|
}
|
|
646
716
|
for (const arg of args) {
|
|
647
|
-
if (!
|
|
717
|
+
if (!ts8.isSpreadElement(arg)) {
|
|
648
718
|
pushArgs(false, NodeHandler.handle(arg));
|
|
649
719
|
continue;
|
|
650
720
|
}
|
|
651
|
-
if (
|
|
721
|
+
if (ts8.isArrayLiteralExpression(arg.expression)) {
|
|
652
722
|
const arrayItems = [];
|
|
653
723
|
const outArrs = [];
|
|
654
724
|
handleArrayLiteralExpression(arg.expression, ctx, arrayItems, outArrs);
|
|
@@ -700,33 +770,35 @@ function handleCallArgs(callNode, ctx) {
|
|
|
700
770
|
result.push("[]");
|
|
701
771
|
return result;
|
|
702
772
|
}
|
|
703
|
-
NodeHandler.register(
|
|
773
|
+
NodeHandler.register(ts8.SyntaxKind.CallExpression, (node, ctx) => {
|
|
704
774
|
const args = handleCallArgs(node, ctx);
|
|
705
775
|
const name = NodeHandler.handle(node.expression);
|
|
706
776
|
const type = checker.getTypeAtLocation(node.expression);
|
|
707
777
|
const transformed = CallTransformer.handle(type, name, args, node, ctx);
|
|
708
778
|
if (transformed !== null)
|
|
709
779
|
return transformed;
|
|
710
|
-
if (!args.length && !
|
|
780
|
+
if (!args.length && !ts8.isParenthesizedExpression(node.expression))
|
|
711
781
|
return name;
|
|
712
782
|
return `${name}(${args.join(", ")})`;
|
|
713
783
|
});
|
|
714
|
-
NodeHandler.register(
|
|
784
|
+
NodeHandler.register(ts8.SyntaxKind.NewExpression, (node, ctx) => {
|
|
715
785
|
const args = handleCallArgs(node, ctx);
|
|
716
786
|
let output = `(new ${NodeHandler.handle(node.expression)}).constructor`;
|
|
717
787
|
if (args.length)
|
|
718
788
|
output += `(${args.join(",")})`;
|
|
719
789
|
return output;
|
|
720
790
|
});
|
|
721
|
-
function shouldHaveOuterPrefix(node, operator) {
|
|
791
|
+
function shouldHaveOuterPrefix(node, operator, ctx) {
|
|
722
792
|
if (!assignmentOperators.has(operator))
|
|
723
793
|
return false;
|
|
724
|
-
if (!
|
|
794
|
+
if (!ts8.isIdentifier(node.left))
|
|
725
795
|
return false;
|
|
726
|
-
|
|
796
|
+
if (ctx.forceOuterPrefix)
|
|
797
|
+
return true;
|
|
798
|
+
const functionAncestor = ts8.findAncestor(node.parent, (n) => ts8.isFunctionLike(n));
|
|
727
799
|
if (!functionAncestor)
|
|
728
800
|
return false;
|
|
729
|
-
if (!
|
|
801
|
+
if (!ts8.findAncestor(functionAncestor.parent, (n) => ts8.isFunctionLike(n)))
|
|
730
802
|
return false;
|
|
731
803
|
const leftSymbol = checker.getSymbolAtLocation(node.left);
|
|
732
804
|
if (!leftSymbol?.valueDeclaration)
|
|
@@ -736,26 +808,26 @@ function shouldHaveOuterPrefix(node, operator) {
|
|
|
736
808
|
function isAssignmentChain(node, operator) {
|
|
737
809
|
if (!assignmentOperators.has(operator))
|
|
738
810
|
return false;
|
|
739
|
-
if (
|
|
811
|
+
if (ts8.isBinaryExpression(node.right) && assignmentOperators.has(ts8.tokenToString(node.right.operatorToken.kind) || ""))
|
|
740
812
|
return true;
|
|
741
|
-
if (
|
|
813
|
+
if (ts8.hasOnlyExpressionInitializer(node.parent))
|
|
742
814
|
return true;
|
|
743
815
|
return false;
|
|
744
816
|
}
|
|
745
|
-
NodeHandler.register(
|
|
817
|
+
NodeHandler.register(ts8.SyntaxKind.BinaryExpression, (node, ctx) => {
|
|
746
818
|
let operatorToken = getOperatorToken(node.operatorToken) || node.operatorToken.getText();
|
|
747
819
|
if (isAssignmentChain(node, operatorToken))
|
|
748
820
|
throw `Assignment chaining is not supported`;
|
|
749
821
|
let right = NodeHandler.handle(node.right);
|
|
750
822
|
if (nodeIsFunctionReference(node.right))
|
|
751
823
|
right = asRef(right);
|
|
752
|
-
if (
|
|
824
|
+
if (ts8.isPropertyAccessExpression(node.left)) {
|
|
753
825
|
const leftType = checker.getTypeAtLocation(node.left.expression);
|
|
754
826
|
const symbol = leftType.getProperty(node.left.name.text);
|
|
755
|
-
if (symbol?.declarations?.some((decl) =>
|
|
827
|
+
if (symbol?.declarations?.some((decl) => ts8.isSetAccessor(decl))) {
|
|
756
828
|
const objName = NodeHandler.handle(node.left.expression);
|
|
757
829
|
const key = node.left.name.text;
|
|
758
|
-
if (operatorToken !== "=" && symbol.declarations.some((decl) =>
|
|
830
|
+
if (operatorToken !== "=" && symbol.declarations.some((decl) => ts8.isGetAccessor(decl)))
|
|
759
831
|
throw `Can't handle '${operatorToken}' because '${objName}' doesn't have a getter '${key}'`;
|
|
760
832
|
if (operatorToken === "+=" || operatorToken === "-=") {
|
|
761
833
|
right = `${objName}.${key} ${operatorToken[0]} ${right}`;
|
|
@@ -766,11 +838,11 @@ NodeHandler.register(ts7.SyntaxKind.BinaryExpression, (node, ctx) => {
|
|
|
766
838
|
}
|
|
767
839
|
}
|
|
768
840
|
let left = NodeHandler.handle(node.left);
|
|
769
|
-
if (shouldHaveOuterPrefix(node, operatorToken))
|
|
841
|
+
if (shouldHaveOuterPrefix(node, operatorToken, ctx))
|
|
770
842
|
left = `outer.${left}`;
|
|
771
843
|
if (nodeIsFunctionReference(node.left))
|
|
772
844
|
left = asRef(left);
|
|
773
|
-
if (operatorToken === "or" &&
|
|
845
|
+
if (operatorToken === "or" && ts8.hasOnlyExpressionInitializer(node.parent)) {
|
|
774
846
|
return callUtilFunction("or_op", left, right);
|
|
775
847
|
}
|
|
776
848
|
switch (operatorToken) {
|
|
@@ -802,28 +874,37 @@ NodeHandler.register(ts7.SyntaxKind.BinaryExpression, (node, ctx) => {
|
|
|
802
874
|
return `bitwise(">>", ${left}, ${right})`;
|
|
803
875
|
case ">>>":
|
|
804
876
|
return `bitwise(">>>", ${left}, ${right})`;
|
|
877
|
+
case "<<=":
|
|
878
|
+
case ">>=":
|
|
879
|
+
case ">>>=":
|
|
880
|
+
return `${left} = bitwise("${operatorToken.slice(0, -1)}", ${left}, ${right})`;
|
|
881
|
+
case "**=":
|
|
882
|
+
return `${left} = ${left} ^ ${right}`;
|
|
805
883
|
case "+=":
|
|
806
884
|
case "-=":
|
|
885
|
+
case "*=":
|
|
886
|
+
case "/=":
|
|
887
|
+
case "%=":
|
|
807
888
|
return `${left} = ${left} ${operatorToken[0]} ${right}`;
|
|
808
889
|
}
|
|
809
890
|
if (operatorToken === "**")
|
|
810
891
|
operatorToken = "^";
|
|
811
892
|
return `${left} ${operatorToken} ${right}`;
|
|
812
893
|
});
|
|
813
|
-
NodeHandler.register(
|
|
894
|
+
NodeHandler.register(ts8.SyntaxKind.ParenthesizedExpression, (node) => {
|
|
814
895
|
return `(${NodeHandler.handle(node.expression)})`;
|
|
815
896
|
});
|
|
816
897
|
function handleUnaryExpression(node) {
|
|
817
898
|
const operand = NodeHandler.handle(node.operand);
|
|
818
|
-
const operator =
|
|
899
|
+
const operator = ts8.tokenToString(node.operator);
|
|
819
900
|
switch (operator) {
|
|
820
901
|
case "++":
|
|
821
902
|
case "--":
|
|
822
|
-
if (
|
|
903
|
+
if (ts8.hasOnlyExpressionInitializer(node.parent) || ts8.isBinaryExpression(node.parent))
|
|
823
904
|
throw `Operator ${operator} is not supported for this kind of expression yet`;
|
|
824
905
|
return `${operand} = ${operand} ${operator[0]} 1`;
|
|
825
906
|
case "!":
|
|
826
|
-
if (
|
|
907
|
+
if (ts8.isPrefixUnaryExpression(node.parent) && ts8.tokenToString(node.parent.operator) === "!") {
|
|
827
908
|
return `(not ${operand})`;
|
|
828
909
|
}
|
|
829
910
|
return `not ${operand}`;
|
|
@@ -837,17 +918,17 @@ function handleUnaryExpression(node) {
|
|
|
837
918
|
throw `Couldn't handle this UnaryExpression: ${node.getText()}`;
|
|
838
919
|
}
|
|
839
920
|
}
|
|
840
|
-
NodeHandler.register(
|
|
841
|
-
NodeHandler.register(
|
|
921
|
+
NodeHandler.register(ts8.SyntaxKind.PrefixUnaryExpression, handleUnaryExpression);
|
|
922
|
+
NodeHandler.register(ts8.SyntaxKind.PostfixUnaryExpression, handleUnaryExpression);
|
|
842
923
|
function handleArrayLiteralExpression(node, ctx, itemStrings, out) {
|
|
843
924
|
itemStrings ??= [];
|
|
844
925
|
out ??= [];
|
|
845
926
|
for (const item of node.elements) {
|
|
846
|
-
if (!
|
|
927
|
+
if (!ts8.isSpreadElement(item)) {
|
|
847
928
|
itemStrings.push(NodeHandler.handle(item));
|
|
848
929
|
continue;
|
|
849
930
|
}
|
|
850
|
-
if (
|
|
931
|
+
if (ts8.isArrayLiteralExpression(item.expression)) {
|
|
851
932
|
handleArrayLiteralExpression(item.expression, ctx, itemStrings, out);
|
|
852
933
|
continue;
|
|
853
934
|
}
|
|
@@ -857,14 +938,14 @@ function handleArrayLiteralExpression(node, ctx, itemStrings, out) {
|
|
|
857
938
|
}
|
|
858
939
|
out.push(NodeHandler.handle(item.expression));
|
|
859
940
|
}
|
|
860
|
-
if ((!out.length || itemStrings.length) && !
|
|
941
|
+
if ((!out.length || itemStrings.length) && !ts8.isSpreadElement(node.parent)) {
|
|
861
942
|
out.push(`[${itemStrings.join(",")}]`);
|
|
862
943
|
itemStrings.length = 0;
|
|
863
944
|
}
|
|
864
945
|
return out.join(" + ");
|
|
865
946
|
}
|
|
866
|
-
NodeHandler.register(
|
|
867
|
-
NodeHandler.register(
|
|
947
|
+
NodeHandler.register(ts8.SyntaxKind.ArrayLiteralExpression, handleArrayLiteralExpression);
|
|
948
|
+
NodeHandler.register(ts8.SyntaxKind.TemplateExpression, (node) => {
|
|
868
949
|
const head = NodeHandler.handle(node.head);
|
|
869
950
|
const strings = [
|
|
870
951
|
...head ? [`"${head}"`] : [],
|
|
@@ -873,51 +954,54 @@ NodeHandler.register(ts7.SyntaxKind.TemplateExpression, (node) => {
|
|
|
873
954
|
const output = strings.join(" + ");
|
|
874
955
|
return output;
|
|
875
956
|
});
|
|
876
|
-
NodeHandler.register(
|
|
957
|
+
NodeHandler.register(ts8.SyntaxKind.TemplateHead, (node) => {
|
|
877
958
|
return transformString(node.text);
|
|
878
959
|
});
|
|
879
|
-
NodeHandler.register(
|
|
960
|
+
NodeHandler.register(ts8.SyntaxKind.TemplateSpan, (node) => {
|
|
880
961
|
let output = NodeHandler.handle(node.expression);
|
|
881
|
-
if (
|
|
962
|
+
if (ts8.isBinaryExpression(node.expression))
|
|
882
963
|
output = `str(${output})`;
|
|
883
964
|
if (node.literal.text)
|
|
884
965
|
output += ` + "${transformString(node.literal.text)}"`;
|
|
885
966
|
return output;
|
|
886
967
|
});
|
|
887
|
-
NodeHandler.register(
|
|
968
|
+
NodeHandler.register(ts8.SyntaxKind.NoSubstitutionTemplateLiteral, (node) => {
|
|
888
969
|
return `"${transformString(node.text)}"`;
|
|
889
970
|
});
|
|
890
|
-
NodeHandler.register(
|
|
891
|
-
if (
|
|
971
|
+
NodeHandler.register(ts8.SyntaxKind.ConditionalExpression, (node) => {
|
|
972
|
+
if (ts8.isCallExpression(node.whenTrue) || ts8.isCallExpression(node.whenFalse)) {
|
|
892
973
|
throw "Call expressions are not supported inside conditional expressions yet";
|
|
893
974
|
}
|
|
975
|
+
if (ts8.isBinaryExpression(node.whenTrue) || ts8.isBinaryExpression(node.whenFalse)) {
|
|
976
|
+
throw "Binary expressions are not supported inside conditional expressions yet";
|
|
977
|
+
}
|
|
894
978
|
const condition = NodeHandler.handle(node.condition);
|
|
895
979
|
const whenTrue = NodeHandler.handle(node.whenTrue);
|
|
896
980
|
const whenFalse = NodeHandler.handle(node.whenFalse);
|
|
897
981
|
return callUtilFunction("conditional_expr", condition, whenTrue, whenFalse);
|
|
898
982
|
});
|
|
899
|
-
NodeHandler.register(
|
|
983
|
+
NodeHandler.register(ts8.SyntaxKind.ExpressionStatement, (node) => {
|
|
900
984
|
return NodeHandler.handle(node.expression);
|
|
901
985
|
});
|
|
902
|
-
NodeHandler.register(
|
|
986
|
+
NodeHandler.register(ts8.SyntaxKind.NonNullExpression, (node) => {
|
|
903
987
|
return NodeHandler.handle(node.expression);
|
|
904
988
|
});
|
|
905
|
-
NodeHandler.register(
|
|
989
|
+
NodeHandler.register(ts8.SyntaxKind.AsExpression, (node) => {
|
|
906
990
|
return NodeHandler.handle(node.expression);
|
|
907
991
|
});
|
|
908
|
-
NodeHandler.register(
|
|
909
|
-
if (
|
|
992
|
+
NodeHandler.register(ts8.SyntaxKind.DeleteExpression, (node) => {
|
|
993
|
+
if (ts8.isPropertyAccessExpression(node.expression)) {
|
|
910
994
|
const pnode = node.expression;
|
|
911
995
|
const left = NodeHandler.handle(pnode.expression);
|
|
912
996
|
const leftType = checker.getTypeAtLocation(pnode.expression);
|
|
913
997
|
const right = replaceIdentifier(NodeHandler.handle(pnode.name), leftType, pnode.name.text);
|
|
914
998
|
return `${left}.remove("${right}")`;
|
|
915
999
|
}
|
|
916
|
-
if (
|
|
1000
|
+
if (ts8.isElementAccessExpression(node.expression)) {
|
|
917
1001
|
const pnode = node.expression;
|
|
918
1002
|
const left = NodeHandler.handle(pnode.expression);
|
|
919
1003
|
let right;
|
|
920
|
-
if (
|
|
1004
|
+
if (ts8.isStringLiteral(pnode.argumentExpression)) {
|
|
921
1005
|
const leftType = checker.getTypeAtLocation(pnode.expression);
|
|
922
1006
|
right = `"${replaceIdentifier(pnode.argumentExpression.text, leftType, pnode.argumentExpression.text)}"`;
|
|
923
1007
|
} else {
|
|
@@ -925,62 +1009,7 @@ NodeHandler.register(ts7.SyntaxKind.DeleteExpression, (node) => {
|
|
|
925
1009
|
}
|
|
926
1010
|
return `${left}.remove(${right})`;
|
|
927
1011
|
}
|
|
928
|
-
throw `Cant handle delete expression for ${
|
|
929
|
-
});
|
|
930
|
-
|
|
931
|
-
// src/visitors/functions.ts
|
|
932
|
-
import ts8 from "typescript";
|
|
933
|
-
function transpileFunctionBody(node) {
|
|
934
|
-
const params = node.parameters.map((param) => NodeHandler.handle(param)).join(", ");
|
|
935
|
-
const body = node.body ? NodeHandler.handle(node.body) : "";
|
|
936
|
-
return `function(${params})
|
|
937
|
-
${body}
|
|
938
|
-
end function`;
|
|
939
|
-
}
|
|
940
|
-
NodeHandler.register(ts8.SyntaxKind.Block, (node) => {
|
|
941
|
-
const output = node.statements.map((val) => {
|
|
942
|
-
let statement = NodeHandler.handle(val);
|
|
943
|
-
statement = statement.split(`
|
|
944
|
-
`).filter((s) => !!s).map((line) => ` ${line}`).join(`
|
|
945
|
-
`);
|
|
946
|
-
return statement;
|
|
947
|
-
}).filter((s) => !!s).join(`
|
|
948
|
-
`);
|
|
949
|
-
return output;
|
|
950
|
-
});
|
|
951
|
-
NodeHandler.register(ts8.SyntaxKind.MethodDeclaration, (node) => {
|
|
952
|
-
return `${NodeHandler.handle(node.name)} = ${transpileFunctionBody(node)}`;
|
|
953
|
-
});
|
|
954
|
-
NodeHandler.register(ts8.SyntaxKind.FunctionDeclaration, (node) => {
|
|
955
|
-
if (!node.body)
|
|
956
|
-
return "";
|
|
957
|
-
if (node.modifiers?.some((m) => m.kind === ts8.SyntaxKind.DeclareKeyword))
|
|
958
|
-
return "";
|
|
959
|
-
const name = node.name ? node.name.text : "anon";
|
|
960
|
-
return `${name} = ${transpileFunctionBody(node)}`;
|
|
961
|
-
});
|
|
962
|
-
NodeHandler.register(ts8.SyntaxKind.ArrowFunction, (node) => {
|
|
963
|
-
const params = node.parameters.map((param) => NodeHandler.handle(param));
|
|
964
|
-
const body = ts8.isBlock(node.body) ? NodeHandler.handle(node.body) : ` return ${NodeHandler.handle(node.body)}`;
|
|
965
|
-
if (ts8.isCallOrNewExpression(node.parent) || ts8.isParenthesizedExpression(node.parent)) {
|
|
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}`;
|
|
973
|
-
}
|
|
974
|
-
if (ts8.hasOnlyExpressionInitializer(node.parent) || ts8.isBinaryExpression(node.parent) || ts8.isReturnStatement(node.parent)) {
|
|
975
|
-
return `function(${params.join(", ")})
|
|
976
|
-
${body}
|
|
977
|
-
end function`;
|
|
978
|
-
}
|
|
979
|
-
const kind = ts8.SyntaxKind[node.parent.kind];
|
|
980
|
-
throw `This kind of arrow function is not yet supported (parent: ${kind} (${node.parent.kind}))`;
|
|
981
|
-
});
|
|
982
|
-
NodeHandler.register(ts8.SyntaxKind.FunctionExpression, (node) => {
|
|
983
|
-
return transpileFunctionBody(node);
|
|
1012
|
+
throw `Cant handle delete expression for ${ts8.SyntaxKind[node.expression.kind]}`;
|
|
984
1013
|
});
|
|
985
1014
|
|
|
986
1015
|
// src/visitors/identifiers.ts
|
|
@@ -998,14 +1027,22 @@ NodeHandler.register(ts9.SyntaxKind.Identifier, (node, ctx) => {
|
|
|
998
1027
|
if (ctx.namedImports[ctx.currentFilePath] && Object.hasOwn(ctx.namedImports[ctx.currentFilePath], name)) {
|
|
999
1028
|
name = ctx.namedImports[ctx.currentFilePath][name];
|
|
1000
1029
|
}
|
|
1030
|
+
if (Object.hasOwn(ctx.bindingElements, name)) {
|
|
1031
|
+
return ctx.bindingElements[name];
|
|
1032
|
+
}
|
|
1001
1033
|
if (ts9.isCallOrNewExpression(node.parent) && node !== node.parent.expression) {
|
|
1002
1034
|
if (nodeIsFunctionReference(node, type))
|
|
1003
1035
|
name = asRef(name);
|
|
1004
1036
|
}
|
|
1005
1037
|
return name;
|
|
1006
1038
|
});
|
|
1007
|
-
NodeHandler.register(ts9.SyntaxKind.Parameter, (node) => {
|
|
1039
|
+
NodeHandler.register(ts9.SyntaxKind.Parameter, (node, ctx) => {
|
|
1008
1040
|
const name = NodeHandler.handle(node.name);
|
|
1041
|
+
if (node.modifiers && ts9.isConstructorDeclaration(node.parent)) {
|
|
1042
|
+
const paramName = name;
|
|
1043
|
+
const declaration = ` self.${paramName} = ${paramName}`;
|
|
1044
|
+
ctx.parameterProperties.push(declaration);
|
|
1045
|
+
}
|
|
1009
1046
|
if (!node.initializer)
|
|
1010
1047
|
return name;
|
|
1011
1048
|
const initializer = NodeHandler.handle(node.initializer);
|
|
@@ -1041,7 +1078,7 @@ NodeHandler.register(ts9.SyntaxKind.RegularExpressionLiteral, (node) => {
|
|
|
1041
1078
|
const flags = node.text.slice(end + 1);
|
|
1042
1079
|
if (flags)
|
|
1043
1080
|
throw "Regex flags are not supported yet";
|
|
1044
|
-
return `"${node.text.slice(start, end)}"`;
|
|
1081
|
+
return `"${node.text.slice(start, end).replaceAll('"', '""')}"`;
|
|
1045
1082
|
});
|
|
1046
1083
|
|
|
1047
1084
|
// src/visitors/imports.ts
|
|
@@ -1202,9 +1239,35 @@ ${funcs.map((func) => `${objectName}.${func}`).join(`
|
|
|
1202
1239
|
}
|
|
1203
1240
|
NodeHandler.register(ts11.SyntaxKind.ObjectLiteralExpression, handleObjectLiteralExpression);
|
|
1204
1241
|
|
|
1205
|
-
// src/visitors/
|
|
1242
|
+
// src/visitors/patterns.ts
|
|
1206
1243
|
import ts12 from "typescript";
|
|
1207
|
-
NodeHandler.register(ts12.SyntaxKind.
|
|
1244
|
+
NodeHandler.register(ts12.SyntaxKind.ArrayBindingPattern, (node, ctx) => {
|
|
1245
|
+
if (!ts12.isParameter(node.parent))
|
|
1246
|
+
throw `This kind of ArrayBindingPattern is not yet supported (parent: ${ts12.SyntaxKind[node.parent.kind]})`;
|
|
1247
|
+
const index = Object.entries(ctx.bindingElements).length;
|
|
1248
|
+
const paramName = `arr${index || ""}`;
|
|
1249
|
+
for (let i = 0;i < node.elements.length; i++) {
|
|
1250
|
+
const element = node.elements[i];
|
|
1251
|
+
if (ts12.isOmittedExpression(element))
|
|
1252
|
+
continue;
|
|
1253
|
+
const name = NodeHandler.handle(element);
|
|
1254
|
+
if (!name || name === "null")
|
|
1255
|
+
continue;
|
|
1256
|
+
ctx.bindingElements[name] = `${paramName}[${i}]`;
|
|
1257
|
+
}
|
|
1258
|
+
return paramName;
|
|
1259
|
+
});
|
|
1260
|
+
NodeHandler.register(ts12.SyntaxKind.BindingElement, (node) => {
|
|
1261
|
+
if (node.initializer)
|
|
1262
|
+
throw "Initializers in BindingElement are not yet supported";
|
|
1263
|
+
if (!ts12.isIdentifier(node.name))
|
|
1264
|
+
throw "Nested binding patterns are not supported";
|
|
1265
|
+
return NodeHandler.handle(node.name);
|
|
1266
|
+
});
|
|
1267
|
+
|
|
1268
|
+
// src/visitors/statements.ts
|
|
1269
|
+
import ts13 from "typescript";
|
|
1270
|
+
NodeHandler.register(ts13.SyntaxKind.ForStatement, (node) => {
|
|
1208
1271
|
if (!node.condition || !node.initializer || !node.incrementor) {
|
|
1209
1272
|
throw "Can't transpile this type of for loop.";
|
|
1210
1273
|
}
|
|
@@ -1214,7 +1277,7 @@ NodeHandler.register(ts12.SyntaxKind.ForStatement, (node) => {
|
|
|
1214
1277
|
const statement = NodeHandler.handle(node.statement);
|
|
1215
1278
|
function hasContinue(n) {
|
|
1216
1279
|
if (n.getChildren().some((child) => {
|
|
1217
|
-
if (
|
|
1280
|
+
if (ts13.isContinueStatement(child))
|
|
1218
1281
|
return true;
|
|
1219
1282
|
return hasContinue(child);
|
|
1220
1283
|
})) {
|
|
@@ -1222,7 +1285,7 @@ NodeHandler.register(ts12.SyntaxKind.ForStatement, (node) => {
|
|
|
1222
1285
|
}
|
|
1223
1286
|
return false;
|
|
1224
1287
|
}
|
|
1225
|
-
const labelIf =
|
|
1288
|
+
const labelIf = ts13.isLabeledStatement(node.parent) ? ` if ${node.parent.label.text}Broke then break` : "";
|
|
1226
1289
|
if (!hasContinue(node)) {
|
|
1227
1290
|
return [
|
|
1228
1291
|
`${initializer}`,
|
|
@@ -1253,8 +1316,8 @@ NodeHandler.register(ts12.SyntaxKind.ForStatement, (node) => {
|
|
|
1253
1316
|
`);
|
|
1254
1317
|
return output;
|
|
1255
1318
|
});
|
|
1256
|
-
NodeHandler.register(
|
|
1257
|
-
if (!
|
|
1319
|
+
NodeHandler.register(ts13.SyntaxKind.ForOfStatement, (node) => {
|
|
1320
|
+
if (!ts13.isVariableDeclarationList(node.initializer)) {
|
|
1258
1321
|
throw `Can't handle this 'for of' statement as '${NodeHandler.handle(node.initializer)}' is not initialized there`;
|
|
1259
1322
|
}
|
|
1260
1323
|
if (node.initializer.declarations.length > 1) {
|
|
@@ -1262,7 +1325,7 @@ NodeHandler.register(ts12.SyntaxKind.ForOfStatement, (node) => {
|
|
|
1262
1325
|
}
|
|
1263
1326
|
const varName = NodeHandler.handle(node.initializer.declarations[0].name);
|
|
1264
1327
|
const objToLoop = NodeHandler.handle(node.expression);
|
|
1265
|
-
const labelIf =
|
|
1328
|
+
const labelIf = ts13.isLabeledStatement(node.parent) ? ` if ${node.parent.label.text}Broke then break` : "";
|
|
1266
1329
|
return [
|
|
1267
1330
|
`for ${varName} in ${objToLoop}`,
|
|
1268
1331
|
`${NodeHandler.handle(node.statement)}`,
|
|
@@ -1271,8 +1334,8 @@ NodeHandler.register(ts12.SyntaxKind.ForOfStatement, (node) => {
|
|
|
1271
1334
|
].join(`
|
|
1272
1335
|
`);
|
|
1273
1336
|
});
|
|
1274
|
-
NodeHandler.register(
|
|
1275
|
-
if (!
|
|
1337
|
+
NodeHandler.register(ts13.SyntaxKind.ForInStatement, (node) => {
|
|
1338
|
+
if (!ts13.isVariableDeclarationList(node.initializer)) {
|
|
1276
1339
|
throw `Can't handle this 'for in' statement as '${NodeHandler.handle(node.initializer)}' is not initialized there`;
|
|
1277
1340
|
}
|
|
1278
1341
|
if (node.initializer.declarations.length > 1) {
|
|
@@ -1280,7 +1343,7 @@ NodeHandler.register(ts12.SyntaxKind.ForInStatement, (node) => {
|
|
|
1280
1343
|
}
|
|
1281
1344
|
const varName = NodeHandler.handle(node.initializer.declarations[0].name);
|
|
1282
1345
|
const objToLoop = NodeHandler.handle(node.expression);
|
|
1283
|
-
const labelIf =
|
|
1346
|
+
const labelIf = ts13.isLabeledStatement(node.parent) ? ` if ${node.parent.label.text}Broke then break` : "";
|
|
1284
1347
|
return [
|
|
1285
1348
|
`for ${varName} in ${objToLoop}.indexes`,
|
|
1286
1349
|
`${NodeHandler.handle(node.statement)}`,
|
|
@@ -1289,19 +1352,19 @@ NodeHandler.register(ts12.SyntaxKind.ForInStatement, (node) => {
|
|
|
1289
1352
|
].join(`
|
|
1290
1353
|
`);
|
|
1291
1354
|
});
|
|
1292
|
-
NodeHandler.register(
|
|
1355
|
+
NodeHandler.register(ts13.SyntaxKind.IfStatement, (node) => {
|
|
1293
1356
|
const condition = NodeHandler.handle(node.expression);
|
|
1294
1357
|
const thenStatement = NodeHandler.handle(node.thenStatement);
|
|
1295
|
-
if (!
|
|
1358
|
+
if (!ts13.isBlock(node.thenStatement) && !ts13.isIfStatement(node.thenStatement) && !ts13.isIfStatement(node.parent)) {
|
|
1296
1359
|
if (!node.elseStatement)
|
|
1297
1360
|
return `if ${condition} then ${thenStatement}`;
|
|
1298
|
-
else if (!
|
|
1361
|
+
else if (!ts13.isBlock(node.elseStatement) && !ts13.isIfStatement(node.elseStatement))
|
|
1299
1362
|
return `if ${condition} then ${thenStatement} else ${NodeHandler.handle(node.elseStatement)}`;
|
|
1300
1363
|
}
|
|
1301
1364
|
let output = `if ${condition} then
|
|
1302
1365
|
${thenStatement.trimStart()}`;
|
|
1303
1366
|
if (node.elseStatement) {
|
|
1304
|
-
if (
|
|
1367
|
+
if (ts13.isIfStatement(node.elseStatement)) {
|
|
1305
1368
|
output += `
|
|
1306
1369
|
else ${NodeHandler.handle(node.elseStatement)}`;
|
|
1307
1370
|
return output;
|
|
@@ -1315,9 +1378,9 @@ else
|
|
|
1315
1378
|
end if`;
|
|
1316
1379
|
return output;
|
|
1317
1380
|
});
|
|
1318
|
-
NodeHandler.register(
|
|
1381
|
+
NodeHandler.register(ts13.SyntaxKind.WhileStatement, (node) => {
|
|
1319
1382
|
const expression = NodeHandler.handle(node.expression);
|
|
1320
|
-
const labelIf =
|
|
1383
|
+
const labelIf = ts13.isLabeledStatement(node.parent) ? ` if ${node.parent.label.text}Broke then break` : "";
|
|
1321
1384
|
return [
|
|
1322
1385
|
`while ${expression}`,
|
|
1323
1386
|
` ${NodeHandler.handle(node.statement).trimStart()}`,
|
|
@@ -1326,9 +1389,9 @@ NodeHandler.register(ts12.SyntaxKind.WhileStatement, (node) => {
|
|
|
1326
1389
|
].join(`
|
|
1327
1390
|
`);
|
|
1328
1391
|
});
|
|
1329
|
-
NodeHandler.register(
|
|
1392
|
+
NodeHandler.register(ts13.SyntaxKind.DoStatement, (node) => {
|
|
1330
1393
|
const expression = NodeHandler.handle(node.expression);
|
|
1331
|
-
const labelIf =
|
|
1394
|
+
const labelIf = ts13.isLabeledStatement(node.parent) ? ` if ${node.parent.label.text}Broke then break` : "";
|
|
1332
1395
|
return [
|
|
1333
1396
|
`did_once = 0`,
|
|
1334
1397
|
`while not did_once or ${expression}`,
|
|
@@ -1339,38 +1402,38 @@ NodeHandler.register(ts12.SyntaxKind.DoStatement, (node) => {
|
|
|
1339
1402
|
].join(`
|
|
1340
1403
|
`);
|
|
1341
1404
|
});
|
|
1342
|
-
NodeHandler.register(
|
|
1405
|
+
NodeHandler.register(ts13.SyntaxKind.ContinueStatement, (_node) => {
|
|
1343
1406
|
return "continue";
|
|
1344
1407
|
});
|
|
1345
|
-
NodeHandler.register(
|
|
1408
|
+
NodeHandler.register(ts13.SyntaxKind.BreakStatement, (node) => {
|
|
1346
1409
|
if (node.label) {
|
|
1347
|
-
if (!
|
|
1410
|
+
if (!ts13.isBlock(node.parent))
|
|
1348
1411
|
throw "A break statement with a label must be in a block";
|
|
1349
1412
|
return `${NodeHandler.handle(node.label)}Broke = 1
|
|
1350
1413
|
break`;
|
|
1351
1414
|
}
|
|
1352
1415
|
return "break";
|
|
1353
1416
|
});
|
|
1354
|
-
NodeHandler.register(
|
|
1417
|
+
NodeHandler.register(ts13.SyntaxKind.ReturnStatement, (node) => {
|
|
1355
1418
|
if (!node.expression) {
|
|
1356
|
-
if (
|
|
1419
|
+
if (ts13.findAncestor(node, (n) => ts13.isConstructorDeclaration(n)) && !ts13.findAncestor(node, (n) => ts13.isFunctionLike(n))) {
|
|
1357
1420
|
return "return self";
|
|
1358
1421
|
}
|
|
1359
1422
|
return "return";
|
|
1360
1423
|
}
|
|
1361
1424
|
return `return ${NodeHandler.handle(node.expression)}`;
|
|
1362
1425
|
});
|
|
1363
|
-
NodeHandler.register(
|
|
1426
|
+
NodeHandler.register(ts13.SyntaxKind.LabeledStatement, (node) => {
|
|
1364
1427
|
return `${NodeHandler.handle(node.label)}Broke = 0
|
|
1365
1428
|
${NodeHandler.handle(node.statement)}`;
|
|
1366
1429
|
});
|
|
1367
1430
|
|
|
1368
1431
|
// src/visitors/variables.ts
|
|
1369
|
-
import
|
|
1432
|
+
import ts14 from "typescript";
|
|
1370
1433
|
function handleVariableDeclaration(node) {
|
|
1371
1434
|
const left = NodeHandler.handle(node.name);
|
|
1372
1435
|
const initializerType = node.initializer ? checker.getTypeAtLocation(node.initializer) : undefined;
|
|
1373
|
-
if (
|
|
1436
|
+
if (ts14.isPropertyDeclaration(node) && initializerType?.flags === ts14.TypeFlags.Object && !node.modifiers?.some((mod) => mod.kind === ts14.SyntaxKind.StaticKeyword) && !ts14.isFunctionLike(node.initializer)) {
|
|
1374
1437
|
console.warn(`You shouldn't initialize '${left}' with an Array or an Object because in GreyScript, every instantiation refers to the same '${left}' variable.
|
|
1375
1438
|
Initialize them in the constructor instead`);
|
|
1376
1439
|
}
|
|
@@ -1380,18 +1443,18 @@ Initialize them in the constructor instead`);
|
|
|
1380
1443
|
}
|
|
1381
1444
|
return `${left} = ${right}`;
|
|
1382
1445
|
}
|
|
1383
|
-
NodeHandler.register(
|
|
1446
|
+
NodeHandler.register(ts14.SyntaxKind.VariableDeclarationList, (node) => {
|
|
1384
1447
|
return node.declarations.map((decl) => handleVariableDeclaration(decl)).join(`
|
|
1385
1448
|
`);
|
|
1386
1449
|
});
|
|
1387
|
-
NodeHandler.register(
|
|
1388
|
-
if (node.modifiers?.some((modifier) => modifier.kind ===
|
|
1450
|
+
NodeHandler.register(ts14.SyntaxKind.VariableStatement, (node) => {
|
|
1451
|
+
if (node.modifiers?.some((modifier) => modifier.kind === ts14.SyntaxKind.DeclareKeyword))
|
|
1389
1452
|
return "";
|
|
1390
1453
|
return NodeHandler.handle(node.declarationList);
|
|
1391
1454
|
});
|
|
1392
|
-
NodeHandler.register(
|
|
1393
|
-
NodeHandler.register(
|
|
1394
|
-
NodeHandler.register(
|
|
1455
|
+
NodeHandler.register(ts14.SyntaxKind.VariableDeclaration, handleVariableDeclaration);
|
|
1456
|
+
NodeHandler.register(ts14.SyntaxKind.PropertyDeclaration, handleVariableDeclaration);
|
|
1457
|
+
NodeHandler.register(ts14.SyntaxKind.EnumDeclaration, (node) => {
|
|
1395
1458
|
const members = [];
|
|
1396
1459
|
function addMember(name, initializer) {
|
|
1397
1460
|
members.push(`${name}: ${initializer}`);
|
|
@@ -1401,7 +1464,7 @@ NodeHandler.register(ts13.SyntaxKind.EnumDeclaration, (node) => {
|
|
|
1401
1464
|
}
|
|
1402
1465
|
node.members.forEach((member, index) => {
|
|
1403
1466
|
let name = NodeHandler.handle(member.name);
|
|
1404
|
-
if (!
|
|
1467
|
+
if (!ts14.isStringLiteral(member.name))
|
|
1405
1468
|
name = `"${name}"`;
|
|
1406
1469
|
if (member.initializer) {
|
|
1407
1470
|
addMember(name, NodeHandler.handle(member.initializer));
|
|
@@ -1731,6 +1794,9 @@ var globalObjects = {
|
|
|
1731
1794
|
"end function",
|
|
1732
1795
|
"Map.values = function",
|
|
1733
1796
|
"\treturn self.data.values",
|
|
1797
|
+
"end function",
|
|
1798
|
+
"Map.size = function",
|
|
1799
|
+
"\treturn self.data.len",
|
|
1734
1800
|
"end function"
|
|
1735
1801
|
].join(`
|
|
1736
1802
|
`),
|
|
@@ -1766,6 +1832,9 @@ var globalObjects = {
|
|
|
1766
1832
|
"end function",
|
|
1767
1833
|
"Set.values = function",
|
|
1768
1834
|
"\treturn self.data.indexes",
|
|
1835
|
+
"end function",
|
|
1836
|
+
"Set.size = function",
|
|
1837
|
+
"\treturn self.data.len",
|
|
1769
1838
|
"end function"
|
|
1770
1839
|
].join(`
|
|
1771
1840
|
`),
|
|
@@ -1880,9 +1949,12 @@ function createAnonFunction(body, params, insertToUtils = true) {
|
|
|
1880
1949
|
const defaultParams = new Array(3).fill(0).map((_, i) => `param${i}`);
|
|
1881
1950
|
const nextName = `func_${anonFunctionsCreated}`;
|
|
1882
1951
|
const paramString = Object.assign(defaultParams, params).join(",");
|
|
1883
|
-
const result =
|
|
1884
|
-
${
|
|
1885
|
-
|
|
1952
|
+
const result = [
|
|
1953
|
+
`${nextName} = function(${paramString})`,
|
|
1954
|
+
...body ? [body] : [],
|
|
1955
|
+
`end function`
|
|
1956
|
+
].join(`
|
|
1957
|
+
`);
|
|
1886
1958
|
anonFunctionsCreated++;
|
|
1887
1959
|
if (insertToUtils)
|
|
1888
1960
|
utilitiesToInsert.set(nextName, result);
|
|
@@ -1896,7 +1968,9 @@ function createContext(currentFileName = "file.ts") {
|
|
|
1896
1968
|
namespaceImports: {},
|
|
1897
1969
|
visitedFiles: new Set,
|
|
1898
1970
|
output: [],
|
|
1899
|
-
extraOutput: new Map
|
|
1971
|
+
extraOutput: new Map,
|
|
1972
|
+
bindingElements: {},
|
|
1973
|
+
parameterProperties: []
|
|
1900
1974
|
};
|
|
1901
1975
|
}
|
|
1902
1976
|
function transpileProgram(entryFileRelativePath) {
|
|
@@ -1909,15 +1983,15 @@ function transpileProgram(entryFileRelativePath) {
|
|
|
1909
1983
|
}
|
|
1910
1984
|
let start = Date.now();
|
|
1911
1985
|
const tsconfigPath = `${findProjectRoot(process.cwd(), "tsconfig.json")}/tsconfig.json`;
|
|
1912
|
-
const res =
|
|
1913
|
-
const parsed =
|
|
1986
|
+
const res = ts15.readConfigFile(tsconfigPath, ts15.sys.readFile);
|
|
1987
|
+
const parsed = ts15.parseJsonConfigFileContent(res.config, ts15.sys, path5.dirname(tsconfigPath));
|
|
1914
1988
|
if (!parsed.options.types)
|
|
1915
1989
|
parsed.options.types = [];
|
|
1916
1990
|
if (!parsed.options.types.includes("@grey-ts/types")) {
|
|
1917
1991
|
parsed.options.types.push("@grey-ts/types");
|
|
1918
1992
|
}
|
|
1919
1993
|
parsed.options.noLib = true;
|
|
1920
|
-
program =
|
|
1994
|
+
program = ts15.createProgram({
|
|
1921
1995
|
rootNames: parsed.fileNames,
|
|
1922
1996
|
options: parsed.options
|
|
1923
1997
|
});
|
|
@@ -1992,7 +2066,8 @@ if (command === "transpile") {
|
|
|
1992
2066
|
const statement = transpiledStatements.shift();
|
|
1993
2067
|
if (content.length + statement.length > 155000 && content.length) {
|
|
1994
2068
|
fileContents.push(content);
|
|
1995
|
-
content =
|
|
2069
|
+
content = `${statement}
|
|
2070
|
+
`;
|
|
1996
2071
|
continue;
|
|
1997
2072
|
}
|
|
1998
2073
|
content += `${statement}
|