@grey-ts/transpiler 1.4.4 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +478 -325
- package/package.json +5 -4
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) {
|
|
@@ -45,13 +45,15 @@ class NodeHandler {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
static addExtraOutput(node, before, after) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
let extra = this.transpileContext.extraOutput.get(node);
|
|
49
|
+
if (!extra) {
|
|
50
|
+
extra = { before: [], after: [] };
|
|
51
|
+
this.transpileContext.extraOutput.set(node, extra);
|
|
52
|
+
}
|
|
51
53
|
if (before)
|
|
52
|
-
extra.before
|
|
54
|
+
extra.before.push(before);
|
|
53
55
|
if (after)
|
|
54
|
-
extra.after
|
|
56
|
+
extra.after.push(after);
|
|
55
57
|
}
|
|
56
58
|
static printLineAndCol(node) {
|
|
57
59
|
const source = node.getSourceFile();
|
|
@@ -167,7 +169,6 @@ var apiNameMap = {
|
|
|
167
169
|
"GreyHack.File.setGroup": "set_group",
|
|
168
170
|
"GreyHack.File.setOwner": "set_owner",
|
|
169
171
|
"GreyHack.activeUser": "active_user",
|
|
170
|
-
"GreyHack.clearScreen": "clear_screen",
|
|
171
172
|
"GreyHack.commandInfo": "command_info",
|
|
172
173
|
"GreyHack.currentDate": "current_date",
|
|
173
174
|
"GreyHack.currentPath": "current_path",
|
|
@@ -258,26 +259,11 @@ var apiNameMap = {
|
|
|
258
259
|
"Object.size": "len",
|
|
259
260
|
"Array.length": "len",
|
|
260
261
|
"Array.shift": "pull",
|
|
261
|
-
"Array.push": "push_many"
|
|
262
|
+
"Array.push": "push_many",
|
|
263
|
+
"Map.size": "data.len",
|
|
264
|
+
"Set.size": "data.len"
|
|
262
265
|
};
|
|
263
266
|
var propertyAccessReplacements = {
|
|
264
|
-
"Math.PI": "pi",
|
|
265
|
-
"Math.abs": "abs",
|
|
266
|
-
"Math.acos": "acos",
|
|
267
|
-
"Math.asin": "asin",
|
|
268
|
-
"Math.atan": "atan",
|
|
269
|
-
"Math.ceil": "ceil",
|
|
270
|
-
"Math.floor": "floor",
|
|
271
|
-
"Math.cos": "cos",
|
|
272
|
-
"Math.sin": "sin",
|
|
273
|
-
"Math.tan": "tan",
|
|
274
|
-
"Math.sqrt": "sqrt",
|
|
275
|
-
"Math.sign": "sign",
|
|
276
|
-
"Math.round": "round",
|
|
277
|
-
"Math.random": "rnd",
|
|
278
|
-
"Math.log": "log",
|
|
279
|
-
"console.log": "print",
|
|
280
|
-
"console.clear": "clear_screen",
|
|
281
267
|
"String.prototype": "string",
|
|
282
268
|
"Number.prototype": "number",
|
|
283
269
|
"Boolean.prototype": "number",
|
|
@@ -303,6 +289,7 @@ var knownOperators = new Set([
|
|
|
303
289
|
"!==",
|
|
304
290
|
"??",
|
|
305
291
|
"??=",
|
|
292
|
+
"||=",
|
|
306
293
|
"in",
|
|
307
294
|
"||",
|
|
308
295
|
"<",
|
|
@@ -312,6 +299,13 @@ var knownOperators = new Set([
|
|
|
312
299
|
"*",
|
|
313
300
|
"/",
|
|
314
301
|
"%",
|
|
302
|
+
"*=",
|
|
303
|
+
"/=",
|
|
304
|
+
"%=",
|
|
305
|
+
"**=",
|
|
306
|
+
"<<=",
|
|
307
|
+
">>=",
|
|
308
|
+
">>>=",
|
|
315
309
|
"~",
|
|
316
310
|
"&",
|
|
317
311
|
"|",
|
|
@@ -327,13 +321,13 @@ function getOperatorToken(node) {
|
|
|
327
321
|
return null;
|
|
328
322
|
if (!knownOperators.has(operatorToken))
|
|
329
323
|
throw `Can't handle operator '${operatorToken}' yet`;
|
|
330
|
-
if (operatorToken
|
|
324
|
+
if (operatorToken === "||")
|
|
331
325
|
operatorToken = "or";
|
|
332
|
-
else if (operatorToken
|
|
326
|
+
else if (operatorToken === "&&")
|
|
333
327
|
operatorToken = "and";
|
|
334
|
-
else if (operatorToken
|
|
328
|
+
else if (operatorToken === "===")
|
|
335
329
|
operatorToken = "==";
|
|
336
|
-
else if (operatorToken
|
|
330
|
+
else if (operatorToken === "!==")
|
|
337
331
|
operatorToken = "!=";
|
|
338
332
|
return operatorToken;
|
|
339
333
|
}
|
|
@@ -355,7 +349,7 @@ function nodeIsFunctionReference(node, type) {
|
|
|
355
349
|
function asRef(value) {
|
|
356
350
|
if (value[0] === "@")
|
|
357
351
|
return value;
|
|
358
|
-
return
|
|
352
|
+
return `@${value}`;
|
|
359
353
|
}
|
|
360
354
|
function getSourceFiles(absPath) {
|
|
361
355
|
if (!fs.existsSync(absPath))
|
|
@@ -380,20 +374,16 @@ function getSourceFiles(absPath) {
|
|
|
380
374
|
return output;
|
|
381
375
|
}
|
|
382
376
|
function replaceIdentifier(original, type, propertyName) {
|
|
383
|
-
let symbol;
|
|
384
377
|
if (type.isUnion()) {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
}
|
|
391
|
-
} else {
|
|
392
|
-
symbol = type.types.find((t) => t.flags !== ts3.TypeFlags.Undefined && t.symbol)?.symbol;
|
|
378
|
+
let result = original;
|
|
379
|
+
for (const t of type.types) {
|
|
380
|
+
result = replaceIdentifier(original, t, propertyName);
|
|
381
|
+
if (result !== original)
|
|
382
|
+
return result;
|
|
393
383
|
}
|
|
394
|
-
|
|
395
|
-
symbol = propertyName ? type.getProperty(propertyName) : type.symbol;
|
|
384
|
+
return result;
|
|
396
385
|
}
|
|
386
|
+
const symbol = propertyName ? type.getProperty(propertyName) : type.symbol;
|
|
397
387
|
if (!symbol)
|
|
398
388
|
return original;
|
|
399
389
|
const symbolFullName = checker.getFullyQualifiedName(symbol);
|
|
@@ -402,7 +392,7 @@ function replaceIdentifier(original, type, propertyName) {
|
|
|
402
392
|
return original;
|
|
403
393
|
const dotIndex = symbolFullName.lastIndexOf(".");
|
|
404
394
|
const strToReplace = dotIndex !== null ? symbolFullName.slice(dotIndex + 1) : symbolFullName;
|
|
405
|
-
if (strToReplace
|
|
395
|
+
if (strToReplace !== original)
|
|
406
396
|
return original;
|
|
407
397
|
return replaceValue;
|
|
408
398
|
}
|
|
@@ -433,7 +423,14 @@ var assignmentOperators = new Set([
|
|
|
433
423
|
"??=",
|
|
434
424
|
"||=",
|
|
435
425
|
"-=",
|
|
436
|
-
"+="
|
|
426
|
+
"+=",
|
|
427
|
+
"*=",
|
|
428
|
+
"/=",
|
|
429
|
+
"%=",
|
|
430
|
+
"**=",
|
|
431
|
+
"<<=",
|
|
432
|
+
">>=",
|
|
433
|
+
">>>="
|
|
437
434
|
]);
|
|
438
435
|
function valueIsBeingAssignedToNode(node) {
|
|
439
436
|
if (ts3.hasOnlyExpressionInitializer(node.parent) && node === node.parent.name)
|
|
@@ -467,21 +464,90 @@ NodeHandler.register(ts4.SyntaxKind.ComputedPropertyName, (node) => {
|
|
|
467
464
|
});
|
|
468
465
|
|
|
469
466
|
// src/visitors/classes.ts
|
|
467
|
+
import ts6 from "typescript";
|
|
468
|
+
|
|
469
|
+
// src/visitors/functions.ts
|
|
470
470
|
import ts5 from "typescript";
|
|
471
|
-
|
|
471
|
+
function handleFunctionBodyAndParams(node, ctx) {
|
|
472
|
+
const oldBindingElements = Object.keys(ctx.bindingElements);
|
|
473
|
+
const params = node.parameters.map((param) => NodeHandler.handle(param));
|
|
474
|
+
const newBindingElements = Object.keys(ctx.bindingElements).filter((b) => !oldBindingElements.includes(b));
|
|
475
|
+
const body = !node.body ? "" : ts5.isBlock(node.body) ? NodeHandler.handle(node.body) : ` return ${NodeHandler.handle(node.body)}`;
|
|
476
|
+
for (const bindingElement of newBindingElements) {
|
|
477
|
+
delete ctx.bindingElements[bindingElement];
|
|
478
|
+
}
|
|
479
|
+
const functionOutput = [
|
|
480
|
+
`function${params.length ? `(${params.join(", ")})` : ""}`,
|
|
481
|
+
...body ? [body] : [],
|
|
482
|
+
`end function`
|
|
483
|
+
].join(`
|
|
484
|
+
`);
|
|
485
|
+
return {
|
|
486
|
+
body,
|
|
487
|
+
params,
|
|
488
|
+
functionOutput
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
NodeHandler.register(ts5.SyntaxKind.Block, (node) => {
|
|
492
|
+
const output = node.statements.map((val) => {
|
|
493
|
+
let statement = NodeHandler.handle(val);
|
|
494
|
+
statement = statement.split(`
|
|
495
|
+
`).filter((s) => !!s).map((line) => ` ${line}`).join(`
|
|
496
|
+
`);
|
|
497
|
+
return statement;
|
|
498
|
+
}).filter((s) => !!s).join(`
|
|
499
|
+
`);
|
|
500
|
+
return output;
|
|
501
|
+
});
|
|
502
|
+
NodeHandler.register(ts5.SyntaxKind.MethodDeclaration, (node, ctx) => {
|
|
503
|
+
const func = handleFunctionBodyAndParams(node, ctx);
|
|
504
|
+
return `${NodeHandler.handle(node.name)} = ${func.functionOutput}`;
|
|
505
|
+
});
|
|
506
|
+
NodeHandler.register(ts5.SyntaxKind.FunctionDeclaration, (node, ctx) => {
|
|
507
|
+
if (!node.body)
|
|
508
|
+
return "";
|
|
472
509
|
if (node.modifiers?.some((m) => m.kind === ts5.SyntaxKind.DeclareKeyword))
|
|
473
510
|
return "";
|
|
511
|
+
const func = handleFunctionBodyAndParams(node, ctx);
|
|
512
|
+
const name = node.name ? node.name.text : "anon";
|
|
513
|
+
return `${name} = ${func.functionOutput}`;
|
|
514
|
+
});
|
|
515
|
+
NodeHandler.register(ts5.SyntaxKind.ArrowFunction, (node, ctx) => {
|
|
516
|
+
const func = handleFunctionBodyAndParams(node, ctx);
|
|
517
|
+
if (ts5.isCallOrNewExpression(node.parent) || ts5.isParenthesizedExpression(node.parent)) {
|
|
518
|
+
const mainNode = ts5.findAncestor(node.parent, (n) => n.parent && (ts5.isBlock(n.parent) || ts5.isSourceFile(n.parent)));
|
|
519
|
+
if (!mainNode) {
|
|
520
|
+
return `@${createAnonFunction(func.body, func.params).name}`;
|
|
521
|
+
}
|
|
522
|
+
const anon = createAnonFunction(func.body, func.params, false);
|
|
523
|
+
NodeHandler.addExtraOutput(mainNode, anon.str, null);
|
|
524
|
+
return `@${anon.name}`;
|
|
525
|
+
}
|
|
526
|
+
if (ts5.hasOnlyExpressionInitializer(node.parent) || ts5.isBinaryExpression(node.parent) || ts5.isReturnStatement(node.parent)) {
|
|
527
|
+
return func.functionOutput;
|
|
528
|
+
}
|
|
529
|
+
const kind = ts5.SyntaxKind[node.parent.kind];
|
|
530
|
+
throw `This kind of arrow function is not yet supported (parent: ${kind} (${node.parent.kind}))`;
|
|
531
|
+
});
|
|
532
|
+
NodeHandler.register(ts5.SyntaxKind.FunctionExpression, (node, ctx) => {
|
|
533
|
+
return handleFunctionBodyAndParams(node, ctx).functionOutput;
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
// src/visitors/classes.ts
|
|
537
|
+
NodeHandler.register(ts6.SyntaxKind.ClassDeclaration, (node) => {
|
|
538
|
+
if (node.modifiers?.some((m) => m.kind === ts6.SyntaxKind.DeclareKeyword))
|
|
539
|
+
return "";
|
|
474
540
|
const name = node.name ? node.name.text : "anon";
|
|
475
|
-
const extensions = node.heritageClauses?.filter((h) => h.token ===
|
|
541
|
+
const extensions = node.heritageClauses?.filter((h) => h.token === ts6.SyntaxKind.ExtendsKeyword);
|
|
476
542
|
let output = `${name} = {}`;
|
|
477
|
-
if (extensions
|
|
543
|
+
if (extensions?.length && extensions[0].types.length)
|
|
478
544
|
output = `${name} = new ${NodeHandler.handle(extensions[0].types[0].expression)}`;
|
|
479
545
|
const declaredNames = new Set;
|
|
480
546
|
let hasConstructor = false;
|
|
481
547
|
for (const member of node.members) {
|
|
482
|
-
if (
|
|
548
|
+
if (ts6.isFunctionLike(member) && "body" in member && !member.body)
|
|
483
549
|
continue;
|
|
484
|
-
if (
|
|
550
|
+
if (ts6.isSemicolonClassElement(member))
|
|
485
551
|
continue;
|
|
486
552
|
if (member.name) {
|
|
487
553
|
const memberName = NodeHandler.handle(member.name);
|
|
@@ -490,78 +556,67 @@ NodeHandler.register(ts5.SyntaxKind.ClassDeclaration, (node) => {
|
|
|
490
556
|
Modifiers such as 'static' are only for TypeScript for now and are not differentiated in the transpiled version from normal declarations for now`;
|
|
491
557
|
declaredNames.add(memberName);
|
|
492
558
|
}
|
|
493
|
-
if (
|
|
559
|
+
if (ts6.isConstructorDeclaration(member))
|
|
494
560
|
hasConstructor = true;
|
|
495
561
|
output += `
|
|
496
562
|
${name}.${NodeHandler.handle(member)}`;
|
|
497
563
|
}
|
|
498
|
-
if (!hasConstructor && !node.modifiers?.some((m) => m.kind ===
|
|
564
|
+
if (!hasConstructor && !node.modifiers?.some((m) => m.kind === ts6.SyntaxKind.AbstractKeyword))
|
|
499
565
|
output += `
|
|
500
566
|
${name}.constructor = function
|
|
501
567
|
return self
|
|
502
568
|
end function`;
|
|
503
569
|
return output;
|
|
504
570
|
});
|
|
505
|
-
NodeHandler.register(
|
|
571
|
+
NodeHandler.register(ts6.SyntaxKind.Constructor, (node, ctx) => {
|
|
506
572
|
if (!node.body)
|
|
507
573
|
return "";
|
|
508
|
-
const
|
|
509
|
-
|
|
510
|
-
const
|
|
511
|
-
if (param.modifiers) {
|
|
512
|
-
const paramName = NodeHandler.handle(param.name);
|
|
513
|
-
const declaration = ` self.${paramName} = ${paramName}`;
|
|
514
|
-
declaredProperties.push(declaration);
|
|
515
|
-
}
|
|
516
|
-
return res;
|
|
517
|
-
}).join(", ");
|
|
518
|
-
let body = NodeHandler.handle(node.body);
|
|
519
|
-
if (declaredProperties.length) {
|
|
520
|
-
const propertiesStr = declaredProperties.join(`
|
|
574
|
+
const func = handleFunctionBodyAndParams(node, ctx);
|
|
575
|
+
if (ctx.parameterProperties.length) {
|
|
576
|
+
const propertiesStr = ctx.parameterProperties.join(`
|
|
521
577
|
`);
|
|
522
|
-
|
|
578
|
+
ctx.parameterProperties.length = 0;
|
|
579
|
+
const lines = func.body.split(`
|
|
523
580
|
`);
|
|
524
581
|
const superIndex = lines.findIndex((line) => line.includes("super.constructor"));
|
|
525
582
|
if (superIndex !== -1) {
|
|
526
|
-
body = `${lines.slice(0, superIndex + 1).join(`
|
|
583
|
+
func.body = `${lines.slice(0, superIndex + 1).join(`
|
|
527
584
|
`)}
|
|
528
585
|
${propertiesStr}
|
|
529
586
|
${lines.slice(superIndex + 1).join(`
|
|
530
587
|
`)}`;
|
|
531
588
|
} else {
|
|
532
|
-
body = `${propertiesStr}
|
|
533
|
-
${body}`;
|
|
589
|
+
func.body = `${propertiesStr}
|
|
590
|
+
${func.body}`;
|
|
534
591
|
}
|
|
535
592
|
}
|
|
536
|
-
return
|
|
537
|
-
${
|
|
538
|
-
|
|
539
|
-
|
|
593
|
+
return [
|
|
594
|
+
`constructor = function${func.params.length ? `(${func.params.join(", ")})` : ""}`,
|
|
595
|
+
...func.body ? [func.body] : [],
|
|
596
|
+
"\treturn self",
|
|
597
|
+
`end function`
|
|
598
|
+
].join(`
|
|
599
|
+
`);
|
|
540
600
|
});
|
|
541
|
-
NodeHandler.register(
|
|
601
|
+
NodeHandler.register(ts6.SyntaxKind.GetAccessor, (node, ctx) => {
|
|
542
602
|
if (!node.body)
|
|
543
603
|
return "";
|
|
544
|
-
const
|
|
545
|
-
return `${NodeHandler.handle(node.name)} =
|
|
546
|
-
${body}
|
|
547
|
-
end function`;
|
|
604
|
+
const func = handleFunctionBodyAndParams(node, ctx);
|
|
605
|
+
return `${NodeHandler.handle(node.name)} = ${func.functionOutput}`;
|
|
548
606
|
});
|
|
549
|
-
NodeHandler.register(
|
|
607
|
+
NodeHandler.register(ts6.SyntaxKind.SetAccessor, (node, ctx) => {
|
|
550
608
|
if (!node.body)
|
|
551
609
|
return "";
|
|
552
|
-
const
|
|
553
|
-
|
|
554
|
-
return `set_${NodeHandler.handle(node.name)} = function(${params.join(", ")})
|
|
555
|
-
${body}
|
|
556
|
-
end function`;
|
|
610
|
+
const func = handleFunctionBodyAndParams(node, ctx);
|
|
611
|
+
return `set_${NodeHandler.handle(node.name)} = ${func.functionOutput}`;
|
|
557
612
|
});
|
|
558
613
|
|
|
559
614
|
// src/visitors/expressions.ts
|
|
560
|
-
import
|
|
615
|
+
import ts8 from "typescript";
|
|
561
616
|
|
|
562
617
|
// src/call_transformers/callTransformer.ts
|
|
563
618
|
import path3 from "node:path";
|
|
564
|
-
import
|
|
619
|
+
import ts7 from "typescript";
|
|
565
620
|
class CallTransformer {
|
|
566
621
|
static handlers = new Map;
|
|
567
622
|
static register(symbolFullName, handler) {
|
|
@@ -569,10 +624,23 @@ class CallTransformer {
|
|
|
569
624
|
throw `Handler for '${symbolFullName}' was already registered`;
|
|
570
625
|
this.handlers.set(symbolFullName, handler);
|
|
571
626
|
}
|
|
572
|
-
static handle(
|
|
627
|
+
static handle(type, functionName, callArgs, node, ctx) {
|
|
628
|
+
let symbolFullName = "";
|
|
629
|
+
if (type.isUnion()) {
|
|
630
|
+
let result = null;
|
|
631
|
+
for (const t of type.types) {
|
|
632
|
+
const res = CallTransformer.handle(t, functionName, callArgs, node, ctx);
|
|
633
|
+
result ??= res;
|
|
634
|
+
}
|
|
635
|
+
return result;
|
|
636
|
+
} else if (type.symbol) {
|
|
637
|
+
symbolFullName = checker.getFullyQualifiedName(type.symbol);
|
|
638
|
+
}
|
|
639
|
+
if (!symbolFullName || symbolFullName.startsWith("__")) {
|
|
640
|
+
const symbol = checker.getSymbolAtLocation(node.expression);
|
|
641
|
+
symbolFullName = symbol ? checker.getFullyQualifiedName(symbol) : "";
|
|
642
|
+
}
|
|
573
643
|
if (symbolFullName in extensionFunctions) {
|
|
574
|
-
if (symbolFullName.startsWith("Math"))
|
|
575
|
-
utilitiesToInsert.set("create_math", "Math = {}");
|
|
576
644
|
utilitiesToInsert.set(symbolFullName, extensionFunctions[symbolFullName]);
|
|
577
645
|
const params = callArgs.length ? `(${callArgs.join(",")})` : "";
|
|
578
646
|
return `${functionName}${params}`;
|
|
@@ -583,19 +651,15 @@ class CallTransformer {
|
|
|
583
651
|
return handler(functionName, callArgs, node, ctx);
|
|
584
652
|
}
|
|
585
653
|
}
|
|
586
|
-
CallTransformer.register("Number.toString", (name) => {
|
|
587
|
-
const number = name.slice(0, name.lastIndexOf("."));
|
|
588
|
-
return `str(${number})`;
|
|
589
|
-
});
|
|
590
654
|
CallTransformer.register("Function.toString", (name) => {
|
|
591
655
|
const func = name.slice(0, name.lastIndexOf("."));
|
|
592
656
|
return `str(@${func})`;
|
|
593
657
|
});
|
|
594
|
-
CallTransformer.register("GreyHack.include", (
|
|
658
|
+
CallTransformer.register("GreyHack.include", (_name, _args, node, ctx) => {
|
|
595
659
|
if (!node.arguments.length)
|
|
596
660
|
return "";
|
|
597
661
|
const fileArg = node.arguments[0];
|
|
598
|
-
if (!
|
|
662
|
+
if (!ts7.isStringLiteralLike(fileArg))
|
|
599
663
|
throw "You can't include variables";
|
|
600
664
|
const absPath = path3.resolve(ctx.currentFolder, fileArg.text);
|
|
601
665
|
const sources = getSourceFiles(absPath);
|
|
@@ -604,20 +668,20 @@ CallTransformer.register("GreyHack.include", (name, args, node, ctx) => {
|
|
|
604
668
|
}
|
|
605
669
|
return "";
|
|
606
670
|
});
|
|
607
|
-
CallTransformer.register("GreyHack.isType", (
|
|
671
|
+
CallTransformer.register("GreyHack.isType", (_name, args) => {
|
|
608
672
|
return callUtilFunction("is_type", args.join(","));
|
|
609
673
|
});
|
|
610
|
-
CallTransformer.register("Boolean", (
|
|
674
|
+
CallTransformer.register("Boolean", (_name, args) => {
|
|
611
675
|
if (!args.length)
|
|
612
676
|
return "0";
|
|
613
677
|
return `(not (not ${args[0]}))`;
|
|
614
678
|
});
|
|
615
|
-
CallTransformer.register("Number", (
|
|
679
|
+
CallTransformer.register("Number", (_name, args) => {
|
|
616
680
|
if (!args.length)
|
|
617
681
|
return "0";
|
|
618
682
|
return `str(${args[0]}).val`;
|
|
619
683
|
});
|
|
620
|
-
CallTransformer.register("String", (
|
|
684
|
+
CallTransformer.register("String", (_name, args) => {
|
|
621
685
|
if (!args.length)
|
|
622
686
|
return "";
|
|
623
687
|
return `str(${args[0]})`;
|
|
@@ -628,7 +692,7 @@ function hasRestParam(params) {
|
|
|
628
692
|
if (!params.length)
|
|
629
693
|
return false;
|
|
630
694
|
const lastParam = params[params.length - 1];
|
|
631
|
-
return !!(lastParam.valueDeclaration &&
|
|
695
|
+
return !!(lastParam.valueDeclaration && ts8.isParameter(lastParam.valueDeclaration) && lastParam.valueDeclaration.dotDotDotToken);
|
|
632
696
|
}
|
|
633
697
|
function handleCallArgs(callNode, ctx) {
|
|
634
698
|
const args = callNode.arguments;
|
|
@@ -652,11 +716,11 @@ function handleCallArgs(callNode, ctx) {
|
|
|
652
716
|
}
|
|
653
717
|
}
|
|
654
718
|
for (const arg of args) {
|
|
655
|
-
if (!
|
|
719
|
+
if (!ts8.isSpreadElement(arg)) {
|
|
656
720
|
pushArgs(false, NodeHandler.handle(arg));
|
|
657
721
|
continue;
|
|
658
722
|
}
|
|
659
|
-
if (
|
|
723
|
+
if (ts8.isArrayLiteralExpression(arg.expression)) {
|
|
660
724
|
const arrayItems = [];
|
|
661
725
|
const outArrs = [];
|
|
662
726
|
handleArrayLiteralExpression(arg.expression, ctx, arrayItems, outArrs);
|
|
@@ -708,38 +772,35 @@ function handleCallArgs(callNode, ctx) {
|
|
|
708
772
|
result.push("[]");
|
|
709
773
|
return result;
|
|
710
774
|
}
|
|
711
|
-
NodeHandler.register(
|
|
775
|
+
NodeHandler.register(ts8.SyntaxKind.CallExpression, (node, ctx) => {
|
|
712
776
|
const args = handleCallArgs(node, ctx);
|
|
713
|
-
|
|
777
|
+
const name = NodeHandler.handle(node.expression);
|
|
714
778
|
const type = checker.getTypeAtLocation(node.expression);
|
|
715
|
-
|
|
716
|
-
if (!symbolFullName || symbolFullName.startsWith("__")) {
|
|
717
|
-
const symbol = checker.getSymbolAtLocation(node.expression);
|
|
718
|
-
symbolFullName = symbol ? checker.getFullyQualifiedName(symbol) : "";
|
|
719
|
-
}
|
|
720
|
-
const transformed = CallTransformer.handle(symbolFullName, name, args, node, ctx);
|
|
779
|
+
const transformed = CallTransformer.handle(type, name, args, node, ctx);
|
|
721
780
|
if (transformed !== null)
|
|
722
781
|
return transformed;
|
|
723
|
-
if (!args.length && !
|
|
782
|
+
if (!args.length && !ts8.isParenthesizedExpression(node.expression))
|
|
724
783
|
return name;
|
|
725
784
|
return `${name}(${args.join(", ")})`;
|
|
726
785
|
});
|
|
727
|
-
NodeHandler.register(
|
|
786
|
+
NodeHandler.register(ts8.SyntaxKind.NewExpression, (node, ctx) => {
|
|
728
787
|
const args = handleCallArgs(node, ctx);
|
|
729
788
|
let output = `(new ${NodeHandler.handle(node.expression)}).constructor`;
|
|
730
789
|
if (args.length)
|
|
731
790
|
output += `(${args.join(",")})`;
|
|
732
791
|
return output;
|
|
733
792
|
});
|
|
734
|
-
function shouldHaveOuterPrefix(node, operator) {
|
|
793
|
+
function shouldHaveOuterPrefix(node, operator, ctx) {
|
|
735
794
|
if (!assignmentOperators.has(operator))
|
|
736
795
|
return false;
|
|
737
|
-
if (!
|
|
796
|
+
if (!ts8.isIdentifier(node.left))
|
|
738
797
|
return false;
|
|
739
|
-
|
|
798
|
+
if (ctx.forceOuterPrefix)
|
|
799
|
+
return true;
|
|
800
|
+
const functionAncestor = ts8.findAncestor(node.parent, (n) => ts8.isFunctionLike(n));
|
|
740
801
|
if (!functionAncestor)
|
|
741
802
|
return false;
|
|
742
|
-
if (!
|
|
803
|
+
if (!ts8.findAncestor(functionAncestor.parent, (n) => ts8.isFunctionLike(n)))
|
|
743
804
|
return false;
|
|
744
805
|
const leftSymbol = checker.getSymbolAtLocation(node.left);
|
|
745
806
|
if (!leftSymbol?.valueDeclaration)
|
|
@@ -749,26 +810,26 @@ function shouldHaveOuterPrefix(node, operator) {
|
|
|
749
810
|
function isAssignmentChain(node, operator) {
|
|
750
811
|
if (!assignmentOperators.has(operator))
|
|
751
812
|
return false;
|
|
752
|
-
if (
|
|
813
|
+
if (ts8.isBinaryExpression(node.right) && assignmentOperators.has(ts8.tokenToString(node.right.operatorToken.kind) || ""))
|
|
753
814
|
return true;
|
|
754
|
-
if (
|
|
815
|
+
if (ts8.hasOnlyExpressionInitializer(node.parent))
|
|
755
816
|
return true;
|
|
756
817
|
return false;
|
|
757
818
|
}
|
|
758
|
-
NodeHandler.register(
|
|
819
|
+
NodeHandler.register(ts8.SyntaxKind.BinaryExpression, (node, ctx) => {
|
|
759
820
|
let operatorToken = getOperatorToken(node.operatorToken) || node.operatorToken.getText();
|
|
760
821
|
if (isAssignmentChain(node, operatorToken))
|
|
761
822
|
throw `Assignment chaining is not supported`;
|
|
762
823
|
let right = NodeHandler.handle(node.right);
|
|
763
824
|
if (nodeIsFunctionReference(node.right))
|
|
764
825
|
right = asRef(right);
|
|
765
|
-
if (
|
|
826
|
+
if (ts8.isPropertyAccessExpression(node.left)) {
|
|
766
827
|
const leftType = checker.getTypeAtLocation(node.left.expression);
|
|
767
828
|
const symbol = leftType.getProperty(node.left.name.text);
|
|
768
|
-
if (symbol?.declarations?.some((decl) =>
|
|
829
|
+
if (symbol?.declarations?.some((decl) => ts8.isSetAccessor(decl))) {
|
|
769
830
|
const objName = NodeHandler.handle(node.left.expression);
|
|
770
831
|
const key = node.left.name.text;
|
|
771
|
-
if (operatorToken !== "=" && symbol.declarations.some((decl) =>
|
|
832
|
+
if (operatorToken !== "=" && symbol.declarations.some((decl) => ts8.isGetAccessor(decl)))
|
|
772
833
|
throw `Can't handle '${operatorToken}' because '${objName}' doesn't have a getter '${key}'`;
|
|
773
834
|
if (operatorToken === "+=" || operatorToken === "-=") {
|
|
774
835
|
right = `${objName}.${key} ${operatorToken[0]} ${right}`;
|
|
@@ -779,11 +840,11 @@ NodeHandler.register(ts7.SyntaxKind.BinaryExpression, (node) => {
|
|
|
779
840
|
}
|
|
780
841
|
}
|
|
781
842
|
let left = NodeHandler.handle(node.left);
|
|
782
|
-
if (shouldHaveOuterPrefix(node, operatorToken))
|
|
783
|
-
left =
|
|
843
|
+
if (shouldHaveOuterPrefix(node, operatorToken, ctx))
|
|
844
|
+
left = `outer.${left}`;
|
|
784
845
|
if (nodeIsFunctionReference(node.left))
|
|
785
846
|
left = asRef(left);
|
|
786
|
-
if (operatorToken === "or" &&
|
|
847
|
+
if (operatorToken === "or" && ts8.hasOnlyExpressionInitializer(node.parent)) {
|
|
787
848
|
return callUtilFunction("or_op", left, right);
|
|
788
849
|
}
|
|
789
850
|
switch (operatorToken) {
|
|
@@ -792,7 +853,15 @@ NodeHandler.register(ts7.SyntaxKind.BinaryExpression, (node) => {
|
|
|
792
853
|
case "??":
|
|
793
854
|
return callUtilFunction("nullish_coalescing_op", left, right);
|
|
794
855
|
case "??=":
|
|
795
|
-
|
|
856
|
+
case "||=": {
|
|
857
|
+
const util = operatorToken === "??=" ? "nullish_coalescing_op" : "or_op";
|
|
858
|
+
ctx.forceSafeAccess = true;
|
|
859
|
+
let leftSafe = NodeHandler.handle(node.left);
|
|
860
|
+
ctx.forceSafeAccess = false;
|
|
861
|
+
if (nodeIsFunctionReference(node.left))
|
|
862
|
+
leftSafe = asRef(leftSafe);
|
|
863
|
+
return `${left} = ${callUtilFunction(util, leftSafe, right)}`;
|
|
864
|
+
}
|
|
796
865
|
case "in":
|
|
797
866
|
return `${right}.hasIndex(${left})`;
|
|
798
867
|
case "&":
|
|
@@ -807,28 +876,37 @@ NodeHandler.register(ts7.SyntaxKind.BinaryExpression, (node) => {
|
|
|
807
876
|
return `bitwise(">>", ${left}, ${right})`;
|
|
808
877
|
case ">>>":
|
|
809
878
|
return `bitwise(">>>", ${left}, ${right})`;
|
|
879
|
+
case "<<=":
|
|
880
|
+
case ">>=":
|
|
881
|
+
case ">>>=":
|
|
882
|
+
return `${left} = bitwise("${operatorToken.slice(0, -1)}", ${left}, ${right})`;
|
|
883
|
+
case "**=":
|
|
884
|
+
return `${left} = ${left} ^ ${right}`;
|
|
810
885
|
case "+=":
|
|
811
886
|
case "-=":
|
|
887
|
+
case "*=":
|
|
888
|
+
case "/=":
|
|
889
|
+
case "%=":
|
|
812
890
|
return `${left} = ${left} ${operatorToken[0]} ${right}`;
|
|
813
891
|
}
|
|
814
892
|
if (operatorToken === "**")
|
|
815
893
|
operatorToken = "^";
|
|
816
894
|
return `${left} ${operatorToken} ${right}`;
|
|
817
895
|
});
|
|
818
|
-
NodeHandler.register(
|
|
896
|
+
NodeHandler.register(ts8.SyntaxKind.ParenthesizedExpression, (node) => {
|
|
819
897
|
return `(${NodeHandler.handle(node.expression)})`;
|
|
820
898
|
});
|
|
821
899
|
function handleUnaryExpression(node) {
|
|
822
900
|
const operand = NodeHandler.handle(node.operand);
|
|
823
|
-
const operator =
|
|
901
|
+
const operator = ts8.tokenToString(node.operator);
|
|
824
902
|
switch (operator) {
|
|
825
903
|
case "++":
|
|
826
904
|
case "--":
|
|
827
|
-
if (
|
|
905
|
+
if (ts8.hasOnlyExpressionInitializer(node.parent) || ts8.isBinaryExpression(node.parent))
|
|
828
906
|
throw `Operator ${operator} is not supported for this kind of expression yet`;
|
|
829
907
|
return `${operand} = ${operand} ${operator[0]} 1`;
|
|
830
908
|
case "!":
|
|
831
|
-
if (
|
|
909
|
+
if (ts8.isPrefixUnaryExpression(node.parent) && ts8.tokenToString(node.parent.operator) === "!") {
|
|
832
910
|
return `(not ${operand})`;
|
|
833
911
|
}
|
|
834
912
|
return `not ${operand}`;
|
|
@@ -842,17 +920,17 @@ function handleUnaryExpression(node) {
|
|
|
842
920
|
throw `Couldn't handle this UnaryExpression: ${node.getText()}`;
|
|
843
921
|
}
|
|
844
922
|
}
|
|
845
|
-
NodeHandler.register(
|
|
846
|
-
NodeHandler.register(
|
|
923
|
+
NodeHandler.register(ts8.SyntaxKind.PrefixUnaryExpression, handleUnaryExpression);
|
|
924
|
+
NodeHandler.register(ts8.SyntaxKind.PostfixUnaryExpression, handleUnaryExpression);
|
|
847
925
|
function handleArrayLiteralExpression(node, ctx, itemStrings, out) {
|
|
848
926
|
itemStrings ??= [];
|
|
849
927
|
out ??= [];
|
|
850
928
|
for (const item of node.elements) {
|
|
851
|
-
if (!
|
|
929
|
+
if (!ts8.isSpreadElement(item)) {
|
|
852
930
|
itemStrings.push(NodeHandler.handle(item));
|
|
853
931
|
continue;
|
|
854
932
|
}
|
|
855
|
-
if (
|
|
933
|
+
if (ts8.isArrayLiteralExpression(item.expression)) {
|
|
856
934
|
handleArrayLiteralExpression(item.expression, ctx, itemStrings, out);
|
|
857
935
|
continue;
|
|
858
936
|
}
|
|
@@ -862,14 +940,14 @@ function handleArrayLiteralExpression(node, ctx, itemStrings, out) {
|
|
|
862
940
|
}
|
|
863
941
|
out.push(NodeHandler.handle(item.expression));
|
|
864
942
|
}
|
|
865
|
-
if ((!out.length || itemStrings.length) && !
|
|
943
|
+
if ((!out.length || itemStrings.length) && !ts8.isSpreadElement(node.parent)) {
|
|
866
944
|
out.push(`[${itemStrings.join(",")}]`);
|
|
867
945
|
itemStrings.length = 0;
|
|
868
946
|
}
|
|
869
947
|
return out.join(" + ");
|
|
870
948
|
}
|
|
871
|
-
NodeHandler.register(
|
|
872
|
-
NodeHandler.register(
|
|
949
|
+
NodeHandler.register(ts8.SyntaxKind.ArrayLiteralExpression, handleArrayLiteralExpression);
|
|
950
|
+
NodeHandler.register(ts8.SyntaxKind.TemplateExpression, (node) => {
|
|
873
951
|
const head = NodeHandler.handle(node.head);
|
|
874
952
|
const strings = [
|
|
875
953
|
...head ? [`"${head}"`] : [],
|
|
@@ -878,51 +956,54 @@ NodeHandler.register(ts7.SyntaxKind.TemplateExpression, (node) => {
|
|
|
878
956
|
const output = strings.join(" + ");
|
|
879
957
|
return output;
|
|
880
958
|
});
|
|
881
|
-
NodeHandler.register(
|
|
959
|
+
NodeHandler.register(ts8.SyntaxKind.TemplateHead, (node) => {
|
|
882
960
|
return transformString(node.text);
|
|
883
961
|
});
|
|
884
|
-
NodeHandler.register(
|
|
962
|
+
NodeHandler.register(ts8.SyntaxKind.TemplateSpan, (node) => {
|
|
885
963
|
let output = NodeHandler.handle(node.expression);
|
|
886
|
-
if (
|
|
964
|
+
if (ts8.isBinaryExpression(node.expression))
|
|
887
965
|
output = `str(${output})`;
|
|
888
966
|
if (node.literal.text)
|
|
889
967
|
output += ` + "${transformString(node.literal.text)}"`;
|
|
890
968
|
return output;
|
|
891
969
|
});
|
|
892
|
-
NodeHandler.register(
|
|
970
|
+
NodeHandler.register(ts8.SyntaxKind.NoSubstitutionTemplateLiteral, (node) => {
|
|
893
971
|
return `"${transformString(node.text)}"`;
|
|
894
972
|
});
|
|
895
|
-
NodeHandler.register(
|
|
896
|
-
if (
|
|
973
|
+
NodeHandler.register(ts8.SyntaxKind.ConditionalExpression, (node) => {
|
|
974
|
+
if (ts8.isCallExpression(node.whenTrue) || ts8.isCallExpression(node.whenFalse)) {
|
|
897
975
|
throw "Call expressions are not supported inside conditional expressions yet";
|
|
898
976
|
}
|
|
977
|
+
if (ts8.isBinaryExpression(node.whenTrue) || ts8.isBinaryExpression(node.whenFalse)) {
|
|
978
|
+
throw "Binary expressions are not supported inside conditional expressions yet";
|
|
979
|
+
}
|
|
899
980
|
const condition = NodeHandler.handle(node.condition);
|
|
900
981
|
const whenTrue = NodeHandler.handle(node.whenTrue);
|
|
901
982
|
const whenFalse = NodeHandler.handle(node.whenFalse);
|
|
902
983
|
return callUtilFunction("conditional_expr", condition, whenTrue, whenFalse);
|
|
903
984
|
});
|
|
904
|
-
NodeHandler.register(
|
|
985
|
+
NodeHandler.register(ts8.SyntaxKind.ExpressionStatement, (node) => {
|
|
905
986
|
return NodeHandler.handle(node.expression);
|
|
906
987
|
});
|
|
907
|
-
NodeHandler.register(
|
|
988
|
+
NodeHandler.register(ts8.SyntaxKind.NonNullExpression, (node) => {
|
|
908
989
|
return NodeHandler.handle(node.expression);
|
|
909
990
|
});
|
|
910
|
-
NodeHandler.register(
|
|
991
|
+
NodeHandler.register(ts8.SyntaxKind.AsExpression, (node) => {
|
|
911
992
|
return NodeHandler.handle(node.expression);
|
|
912
993
|
});
|
|
913
|
-
NodeHandler.register(
|
|
914
|
-
if (
|
|
994
|
+
NodeHandler.register(ts8.SyntaxKind.DeleteExpression, (node) => {
|
|
995
|
+
if (ts8.isPropertyAccessExpression(node.expression)) {
|
|
915
996
|
const pnode = node.expression;
|
|
916
997
|
const left = NodeHandler.handle(pnode.expression);
|
|
917
998
|
const leftType = checker.getTypeAtLocation(pnode.expression);
|
|
918
999
|
const right = replaceIdentifier(NodeHandler.handle(pnode.name), leftType, pnode.name.text);
|
|
919
1000
|
return `${left}.remove("${right}")`;
|
|
920
1001
|
}
|
|
921
|
-
if (
|
|
1002
|
+
if (ts8.isElementAccessExpression(node.expression)) {
|
|
922
1003
|
const pnode = node.expression;
|
|
923
1004
|
const left = NodeHandler.handle(pnode.expression);
|
|
924
1005
|
let right;
|
|
925
|
-
if (
|
|
1006
|
+
if (ts8.isStringLiteral(pnode.argumentExpression)) {
|
|
926
1007
|
const leftType = checker.getTypeAtLocation(pnode.expression);
|
|
927
1008
|
right = `"${replaceIdentifier(pnode.argumentExpression.text, leftType, pnode.argumentExpression.text)}"`;
|
|
928
1009
|
} else {
|
|
@@ -930,62 +1011,7 @@ NodeHandler.register(ts7.SyntaxKind.DeleteExpression, (node) => {
|
|
|
930
1011
|
}
|
|
931
1012
|
return `${left}.remove(${right})`;
|
|
932
1013
|
}
|
|
933
|
-
throw `Cant handle delete expression for ${
|
|
934
|
-
});
|
|
935
|
-
|
|
936
|
-
// src/visitors/functions.ts
|
|
937
|
-
import ts8 from "typescript";
|
|
938
|
-
function transpileFunctionBody(node) {
|
|
939
|
-
const params = node.parameters.map((param) => NodeHandler.handle(param)).join(", ");
|
|
940
|
-
const body = node.body ? NodeHandler.handle(node.body) : "";
|
|
941
|
-
return `function(${params})
|
|
942
|
-
${body}
|
|
943
|
-
end function`;
|
|
944
|
-
}
|
|
945
|
-
NodeHandler.register(ts8.SyntaxKind.Block, (node) => {
|
|
946
|
-
const output = node.statements.map((val) => {
|
|
947
|
-
let statement = NodeHandler.handle(val);
|
|
948
|
-
statement = statement.split(`
|
|
949
|
-
`).filter((s) => !!s).map((line) => "\t" + line).join(`
|
|
950
|
-
`);
|
|
951
|
-
return statement;
|
|
952
|
-
}).filter((s) => !!s).join(`
|
|
953
|
-
`);
|
|
954
|
-
return output;
|
|
955
|
-
});
|
|
956
|
-
NodeHandler.register(ts8.SyntaxKind.MethodDeclaration, (node) => {
|
|
957
|
-
return `${NodeHandler.handle(node.name)} = ${transpileFunctionBody(node)}`;
|
|
958
|
-
});
|
|
959
|
-
NodeHandler.register(ts8.SyntaxKind.FunctionDeclaration, (node) => {
|
|
960
|
-
if (!node.body)
|
|
961
|
-
return "";
|
|
962
|
-
if (node.modifiers?.some((m) => m.kind === ts8.SyntaxKind.DeclareKeyword))
|
|
963
|
-
return "";
|
|
964
|
-
const name = node.name ? node.name.text : "anon";
|
|
965
|
-
return `${name} = ${transpileFunctionBody(node)}`;
|
|
966
|
-
});
|
|
967
|
-
NodeHandler.register(ts8.SyntaxKind.ArrowFunction, (node) => {
|
|
968
|
-
const params = node.parameters.map((param) => NodeHandler.handle(param));
|
|
969
|
-
const body = ts8.isBlock(node.body) ? NodeHandler.handle(node.body) : ` return ${NodeHandler.handle(node.body)}`;
|
|
970
|
-
if (ts8.isCallOrNewExpression(node.parent) || ts8.isParenthesizedExpression(node.parent)) {
|
|
971
|
-
const mainNode = ts8.findAncestor(node.parent, (n) => n.parent && (ts8.isBlock(n.parent) || ts8.isSourceFile(n.parent)));
|
|
972
|
-
if (!mainNode) {
|
|
973
|
-
return "@" + createAnonFunction(body, params).name;
|
|
974
|
-
}
|
|
975
|
-
const anon = createAnonFunction(body, params, false);
|
|
976
|
-
NodeHandler.addExtraOutput(mainNode, anon.str, null);
|
|
977
|
-
return "@" + anon.name;
|
|
978
|
-
}
|
|
979
|
-
if (ts8.hasOnlyExpressionInitializer(node.parent) || ts8.isBinaryExpression(node.parent) || ts8.isReturnStatement(node.parent)) {
|
|
980
|
-
return `function(${params.join(", ")})
|
|
981
|
-
${body}
|
|
982
|
-
end function`;
|
|
983
|
-
}
|
|
984
|
-
const kind = ts8.SyntaxKind[node.parent.kind];
|
|
985
|
-
throw `This kind of arrow function is not yet supported (parent: ${kind} (${node.parent.kind}))`;
|
|
986
|
-
});
|
|
987
|
-
NodeHandler.register(ts8.SyntaxKind.FunctionExpression, (node) => {
|
|
988
|
-
return transpileFunctionBody(node);
|
|
1014
|
+
throw `Cant handle delete expression for ${ts8.SyntaxKind[node.expression.kind]}`;
|
|
989
1015
|
});
|
|
990
1016
|
|
|
991
1017
|
// src/visitors/identifiers.ts
|
|
@@ -995,27 +1021,30 @@ NodeHandler.register(ts9.SyntaxKind.Identifier, (node, ctx) => {
|
|
|
995
1021
|
let name = node.text;
|
|
996
1022
|
if (name === "undefined")
|
|
997
1023
|
return "null";
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
if (name != original)
|
|
1003
|
-
break;
|
|
1004
|
-
}
|
|
1005
|
-
} else {
|
|
1006
|
-
name = replaceIdentifier(node.text, type);
|
|
1024
|
+
name = replaceIdentifier(node.text, type);
|
|
1025
|
+
const symbolFullName = type.symbol ? checker.getFullyQualifiedName(type.symbol) : "";
|
|
1026
|
+
if (symbolFullName in globalObjects) {
|
|
1027
|
+
utilitiesToInsert.set(symbolFullName, globalObjects[symbolFullName]);
|
|
1007
1028
|
}
|
|
1008
|
-
if (ctx.namedImports[ctx.currentFilePath]
|
|
1029
|
+
if (ctx.namedImports[ctx.currentFilePath] && Object.hasOwn(ctx.namedImports[ctx.currentFilePath], name)) {
|
|
1009
1030
|
name = ctx.namedImports[ctx.currentFilePath][name];
|
|
1010
1031
|
}
|
|
1011
|
-
if (
|
|
1032
|
+
if (Object.hasOwn(ctx.bindingElements, name)) {
|
|
1033
|
+
return ctx.bindingElements[name];
|
|
1034
|
+
}
|
|
1035
|
+
if (ts9.isCallOrNewExpression(node.parent) && node !== node.parent.expression) {
|
|
1012
1036
|
if (nodeIsFunctionReference(node, type))
|
|
1013
1037
|
name = asRef(name);
|
|
1014
1038
|
}
|
|
1015
1039
|
return name;
|
|
1016
1040
|
});
|
|
1017
|
-
NodeHandler.register(ts9.SyntaxKind.Parameter, (node) => {
|
|
1041
|
+
NodeHandler.register(ts9.SyntaxKind.Parameter, (node, ctx) => {
|
|
1018
1042
|
const name = NodeHandler.handle(node.name);
|
|
1043
|
+
if (node.modifiers && ts9.isConstructorDeclaration(node.parent)) {
|
|
1044
|
+
const paramName = name;
|
|
1045
|
+
const declaration = ` self.${paramName} = ${paramName}`;
|
|
1046
|
+
ctx.parameterProperties.push(declaration);
|
|
1047
|
+
}
|
|
1019
1048
|
if (!node.initializer)
|
|
1020
1049
|
return name;
|
|
1021
1050
|
const initializer = NodeHandler.handle(node.initializer);
|
|
@@ -1095,37 +1124,38 @@ NodeHandler.register(ts10.SyntaxKind.ImportDeclaration, (node, ctx) => {
|
|
|
1095
1124
|
|
|
1096
1125
|
// src/visitors/objects.ts
|
|
1097
1126
|
import ts11 from "typescript";
|
|
1098
|
-
function shouldGetSafely(node) {
|
|
1127
|
+
function shouldGetSafely(node, ctx) {
|
|
1099
1128
|
if (ts11.isNonNullExpression(node.parent))
|
|
1100
1129
|
return false;
|
|
1130
|
+
const callParent = ts11.findAncestor(node, (n) => n.parent && ts11.isCallExpression(n.parent) && n.parent.expression === n);
|
|
1131
|
+
if (callParent)
|
|
1132
|
+
return false;
|
|
1133
|
+
if (ctx.forceSafeAccess)
|
|
1134
|
+
return true;
|
|
1101
1135
|
if (valueIsBeingAssignedToNode(node))
|
|
1102
1136
|
return false;
|
|
1103
|
-
if (ts11.
|
|
1104
|
-
const rightType = checker.getTypeAtLocation(node.name);
|
|
1105
|
-
if (!rightType.isUnion())
|
|
1106
|
-
return !!node.questionDotToken;
|
|
1107
|
-
const hasUndefined = rightType.types.some((t) => t.flags === ts11.TypeFlags.Undefined);
|
|
1108
|
-
if (!hasUndefined)
|
|
1109
|
-
return false;
|
|
1110
|
-
if (!ts11.isCallExpression(node.parent))
|
|
1111
|
-
return true;
|
|
1112
|
-
if (node.parent.arguments.length)
|
|
1113
|
-
return false;
|
|
1114
|
-
} else {
|
|
1137
|
+
if (ts11.isElementAccessExpression(node)) {
|
|
1115
1138
|
if (ts11.isNumericLiteral(node.argumentExpression) && !node.questionDotToken)
|
|
1116
1139
|
return false;
|
|
1140
|
+
return true;
|
|
1117
1141
|
}
|
|
1142
|
+
const type = checker.getTypeAtLocation(node);
|
|
1143
|
+
if (!type.isUnion())
|
|
1144
|
+
return !!node.questionDotToken;
|
|
1145
|
+
const hasNullish = type.types.some((t) => t.flags === ts11.TypeFlags.Undefined || ts11.TypeFlags.Null);
|
|
1146
|
+
if (!hasNullish)
|
|
1147
|
+
return false;
|
|
1118
1148
|
return true;
|
|
1119
1149
|
}
|
|
1120
1150
|
NodeHandler.register(ts11.SyntaxKind.PropertyAccessExpression, (node, ctx) => {
|
|
1121
1151
|
const left = NodeHandler.handle(node.expression);
|
|
1122
1152
|
let right = NodeHandler.handle(node.name);
|
|
1123
1153
|
right = replaceIdentifier(right, checker.getTypeAtLocation(node.expression), right);
|
|
1124
|
-
const nodeSymbol = checker.getSymbolAtLocation(node);
|
|
1125
1154
|
if (ctx.namespaceImports[ctx.currentFilePath]?.has(left))
|
|
1126
1155
|
return right;
|
|
1127
|
-
if (shouldGetSafely(node))
|
|
1156
|
+
if (shouldGetSafely(node, ctx))
|
|
1128
1157
|
return callUtilFunction("get_property", left, `"${right}"`);
|
|
1158
|
+
const nodeSymbol = checker.getSymbolAtLocation(node);
|
|
1129
1159
|
let output = `${left}.${right}`;
|
|
1130
1160
|
output = replacePropertyAccess(output, nodeSymbol);
|
|
1131
1161
|
if (nodeIsFunctionReference(node))
|
|
@@ -1141,7 +1171,7 @@ NodeHandler.register(ts11.SyntaxKind.ElementAccessExpression, (node, ctx) => {
|
|
|
1141
1171
|
} else {
|
|
1142
1172
|
right = NodeHandler.handle(node.argumentExpression);
|
|
1143
1173
|
}
|
|
1144
|
-
if (shouldGetSafely(node)) {
|
|
1174
|
+
if (shouldGetSafely(node, ctx)) {
|
|
1145
1175
|
return callUtilFunction("get_property", left, `${right}`);
|
|
1146
1176
|
}
|
|
1147
1177
|
return `${left}[${right}]`;
|
|
@@ -1158,7 +1188,7 @@ function handleObjectLiteralExpression(node, ctx, currObj, outObjects, funcs) {
|
|
|
1158
1188
|
function pushObj() {
|
|
1159
1189
|
if (!currObj?.length)
|
|
1160
1190
|
return "";
|
|
1161
|
-
const res = currObj.filter((s) => s
|
|
1191
|
+
const res = currObj.filter((s) => s !== "").join(",");
|
|
1162
1192
|
if (res) {
|
|
1163
1193
|
outObjects?.push(`{ ${res} }`);
|
|
1164
1194
|
}
|
|
@@ -1204,16 +1234,42 @@ function handleObjectLiteralExpression(node, ctx, currObj, outObjects, funcs) {
|
|
|
1204
1234
|
throw "You can't have method declarations inside an object that is not being assigned to a variable";
|
|
1205
1235
|
}
|
|
1206
1236
|
output += `
|
|
1207
|
-
|
|
1208
|
-
`)
|
|
1237
|
+
${funcs.map((func) => `${objectName}.${func}`).join(`
|
|
1238
|
+
`)}`;
|
|
1209
1239
|
}
|
|
1210
1240
|
return output;
|
|
1211
1241
|
}
|
|
1212
1242
|
NodeHandler.register(ts11.SyntaxKind.ObjectLiteralExpression, handleObjectLiteralExpression);
|
|
1213
1243
|
|
|
1214
|
-
// src/visitors/
|
|
1244
|
+
// src/visitors/patterns.ts
|
|
1215
1245
|
import ts12 from "typescript";
|
|
1216
|
-
NodeHandler.register(ts12.SyntaxKind.
|
|
1246
|
+
NodeHandler.register(ts12.SyntaxKind.ArrayBindingPattern, (node, ctx) => {
|
|
1247
|
+
if (!ts12.isParameter(node.parent))
|
|
1248
|
+
throw `This kind of ArrayBindingPattern is not yet supported (parent: ${ts12.SyntaxKind[node.parent.kind]})`;
|
|
1249
|
+
const index = Object.entries(ctx.bindingElements).length;
|
|
1250
|
+
const paramName = `arr${index || ""}`;
|
|
1251
|
+
for (let i = 0;i < node.elements.length; i++) {
|
|
1252
|
+
const element = node.elements[i];
|
|
1253
|
+
if (ts12.isOmittedExpression(element))
|
|
1254
|
+
continue;
|
|
1255
|
+
const name = NodeHandler.handle(element);
|
|
1256
|
+
if (!name || name === "null")
|
|
1257
|
+
continue;
|
|
1258
|
+
ctx.bindingElements[name] = `${paramName}[${i}]`;
|
|
1259
|
+
}
|
|
1260
|
+
return paramName;
|
|
1261
|
+
});
|
|
1262
|
+
NodeHandler.register(ts12.SyntaxKind.BindingElement, (node) => {
|
|
1263
|
+
if (node.initializer)
|
|
1264
|
+
throw "Initializers in BindingElement are not yet supported";
|
|
1265
|
+
if (!ts12.isIdentifier(node.name))
|
|
1266
|
+
throw "Nested binding patterns are not supported";
|
|
1267
|
+
return NodeHandler.handle(node.name);
|
|
1268
|
+
});
|
|
1269
|
+
|
|
1270
|
+
// src/visitors/statements.ts
|
|
1271
|
+
import ts13 from "typescript";
|
|
1272
|
+
NodeHandler.register(ts13.SyntaxKind.ForStatement, (node) => {
|
|
1217
1273
|
if (!node.condition || !node.initializer || !node.incrementor) {
|
|
1218
1274
|
throw "Can't transpile this type of for loop.";
|
|
1219
1275
|
}
|
|
@@ -1223,7 +1279,7 @@ NodeHandler.register(ts12.SyntaxKind.ForStatement, (node) => {
|
|
|
1223
1279
|
const statement = NodeHandler.handle(node.statement);
|
|
1224
1280
|
function hasContinue(n) {
|
|
1225
1281
|
if (n.getChildren().some((child) => {
|
|
1226
|
-
if (
|
|
1282
|
+
if (ts13.isContinueStatement(child))
|
|
1227
1283
|
return true;
|
|
1228
1284
|
return hasContinue(child);
|
|
1229
1285
|
})) {
|
|
@@ -1231,7 +1287,7 @@ NodeHandler.register(ts12.SyntaxKind.ForStatement, (node) => {
|
|
|
1231
1287
|
}
|
|
1232
1288
|
return false;
|
|
1233
1289
|
}
|
|
1234
|
-
const labelIf =
|
|
1290
|
+
const labelIf = ts13.isLabeledStatement(node.parent) ? ` if ${node.parent.label.text}Broke then break` : "";
|
|
1235
1291
|
if (!hasContinue(node)) {
|
|
1236
1292
|
return [
|
|
1237
1293
|
`${initializer}`,
|
|
@@ -1243,7 +1299,7 @@ NodeHandler.register(ts12.SyntaxKind.ForStatement, (node) => {
|
|
|
1243
1299
|
].join(`
|
|
1244
1300
|
`);
|
|
1245
1301
|
}
|
|
1246
|
-
const incrementedStateVarName =
|
|
1302
|
+
const incrementedStateVarName = `state_${(Date.now() * Math.random()).toFixed(0).slice(0, 6)}`;
|
|
1247
1303
|
const output = [
|
|
1248
1304
|
`${incrementedStateVarName} = 1`,
|
|
1249
1305
|
`${initializer}`,
|
|
@@ -1262,8 +1318,8 @@ NodeHandler.register(ts12.SyntaxKind.ForStatement, (node) => {
|
|
|
1262
1318
|
`);
|
|
1263
1319
|
return output;
|
|
1264
1320
|
});
|
|
1265
|
-
NodeHandler.register(
|
|
1266
|
-
if (!
|
|
1321
|
+
NodeHandler.register(ts13.SyntaxKind.ForOfStatement, (node) => {
|
|
1322
|
+
if (!ts13.isVariableDeclarationList(node.initializer)) {
|
|
1267
1323
|
throw `Can't handle this 'for of' statement as '${NodeHandler.handle(node.initializer)}' is not initialized there`;
|
|
1268
1324
|
}
|
|
1269
1325
|
if (node.initializer.declarations.length > 1) {
|
|
@@ -1271,7 +1327,7 @@ NodeHandler.register(ts12.SyntaxKind.ForOfStatement, (node) => {
|
|
|
1271
1327
|
}
|
|
1272
1328
|
const varName = NodeHandler.handle(node.initializer.declarations[0].name);
|
|
1273
1329
|
const objToLoop = NodeHandler.handle(node.expression);
|
|
1274
|
-
const labelIf =
|
|
1330
|
+
const labelIf = ts13.isLabeledStatement(node.parent) ? ` if ${node.parent.label.text}Broke then break` : "";
|
|
1275
1331
|
return [
|
|
1276
1332
|
`for ${varName} in ${objToLoop}`,
|
|
1277
1333
|
`${NodeHandler.handle(node.statement)}`,
|
|
@@ -1280,8 +1336,8 @@ NodeHandler.register(ts12.SyntaxKind.ForOfStatement, (node) => {
|
|
|
1280
1336
|
].join(`
|
|
1281
1337
|
`);
|
|
1282
1338
|
});
|
|
1283
|
-
NodeHandler.register(
|
|
1284
|
-
if (!
|
|
1339
|
+
NodeHandler.register(ts13.SyntaxKind.ForInStatement, (node) => {
|
|
1340
|
+
if (!ts13.isVariableDeclarationList(node.initializer)) {
|
|
1285
1341
|
throw `Can't handle this 'for in' statement as '${NodeHandler.handle(node.initializer)}' is not initialized there`;
|
|
1286
1342
|
}
|
|
1287
1343
|
if (node.initializer.declarations.length > 1) {
|
|
@@ -1289,7 +1345,7 @@ NodeHandler.register(ts12.SyntaxKind.ForInStatement, (node) => {
|
|
|
1289
1345
|
}
|
|
1290
1346
|
const varName = NodeHandler.handle(node.initializer.declarations[0].name);
|
|
1291
1347
|
const objToLoop = NodeHandler.handle(node.expression);
|
|
1292
|
-
const labelIf =
|
|
1348
|
+
const labelIf = ts13.isLabeledStatement(node.parent) ? ` if ${node.parent.label.text}Broke then break` : "";
|
|
1293
1349
|
return [
|
|
1294
1350
|
`for ${varName} in ${objToLoop}.indexes`,
|
|
1295
1351
|
`${NodeHandler.handle(node.statement)}`,
|
|
@@ -1298,19 +1354,19 @@ NodeHandler.register(ts12.SyntaxKind.ForInStatement, (node) => {
|
|
|
1298
1354
|
].join(`
|
|
1299
1355
|
`);
|
|
1300
1356
|
});
|
|
1301
|
-
NodeHandler.register(
|
|
1357
|
+
NodeHandler.register(ts13.SyntaxKind.IfStatement, (node) => {
|
|
1302
1358
|
const condition = NodeHandler.handle(node.expression);
|
|
1303
1359
|
const thenStatement = NodeHandler.handle(node.thenStatement);
|
|
1304
|
-
if (!
|
|
1360
|
+
if (!ts13.isBlock(node.thenStatement) && !ts13.isIfStatement(node.thenStatement) && !ts13.isIfStatement(node.parent)) {
|
|
1305
1361
|
if (!node.elseStatement)
|
|
1306
1362
|
return `if ${condition} then ${thenStatement}`;
|
|
1307
|
-
else if (!
|
|
1363
|
+
else if (!ts13.isBlock(node.elseStatement) && !ts13.isIfStatement(node.elseStatement))
|
|
1308
1364
|
return `if ${condition} then ${thenStatement} else ${NodeHandler.handle(node.elseStatement)}`;
|
|
1309
1365
|
}
|
|
1310
1366
|
let output = `if ${condition} then
|
|
1311
1367
|
${thenStatement.trimStart()}`;
|
|
1312
1368
|
if (node.elseStatement) {
|
|
1313
|
-
if (
|
|
1369
|
+
if (ts13.isIfStatement(node.elseStatement)) {
|
|
1314
1370
|
output += `
|
|
1315
1371
|
else ${NodeHandler.handle(node.elseStatement)}`;
|
|
1316
1372
|
return output;
|
|
@@ -1324,9 +1380,9 @@ else
|
|
|
1324
1380
|
end if`;
|
|
1325
1381
|
return output;
|
|
1326
1382
|
});
|
|
1327
|
-
NodeHandler.register(
|
|
1383
|
+
NodeHandler.register(ts13.SyntaxKind.WhileStatement, (node) => {
|
|
1328
1384
|
const expression = NodeHandler.handle(node.expression);
|
|
1329
|
-
const labelIf =
|
|
1385
|
+
const labelIf = ts13.isLabeledStatement(node.parent) ? ` if ${node.parent.label.text}Broke then break` : "";
|
|
1330
1386
|
return [
|
|
1331
1387
|
`while ${expression}`,
|
|
1332
1388
|
` ${NodeHandler.handle(node.statement).trimStart()}`,
|
|
@@ -1335,9 +1391,9 @@ NodeHandler.register(ts12.SyntaxKind.WhileStatement, (node, ctx) => {
|
|
|
1335
1391
|
].join(`
|
|
1336
1392
|
`);
|
|
1337
1393
|
});
|
|
1338
|
-
NodeHandler.register(
|
|
1394
|
+
NodeHandler.register(ts13.SyntaxKind.DoStatement, (node) => {
|
|
1339
1395
|
const expression = NodeHandler.handle(node.expression);
|
|
1340
|
-
const labelIf =
|
|
1396
|
+
const labelIf = ts13.isLabeledStatement(node.parent) ? ` if ${node.parent.label.text}Broke then break` : "";
|
|
1341
1397
|
return [
|
|
1342
1398
|
`did_once = 0`,
|
|
1343
1399
|
`while not did_once or ${expression}`,
|
|
@@ -1348,69 +1404,69 @@ NodeHandler.register(ts12.SyntaxKind.DoStatement, (node, ctx) => {
|
|
|
1348
1404
|
].join(`
|
|
1349
1405
|
`);
|
|
1350
1406
|
});
|
|
1351
|
-
NodeHandler.register(
|
|
1407
|
+
NodeHandler.register(ts13.SyntaxKind.ContinueStatement, (_node) => {
|
|
1352
1408
|
return "continue";
|
|
1353
1409
|
});
|
|
1354
|
-
NodeHandler.register(
|
|
1410
|
+
NodeHandler.register(ts13.SyntaxKind.BreakStatement, (node) => {
|
|
1355
1411
|
if (node.label) {
|
|
1356
|
-
if (!
|
|
1412
|
+
if (!ts13.isBlock(node.parent))
|
|
1357
1413
|
throw "A break statement with a label must be in a block";
|
|
1358
1414
|
return `${NodeHandler.handle(node.label)}Broke = 1
|
|
1359
1415
|
break`;
|
|
1360
1416
|
}
|
|
1361
1417
|
return "break";
|
|
1362
1418
|
});
|
|
1363
|
-
NodeHandler.register(
|
|
1419
|
+
NodeHandler.register(ts13.SyntaxKind.ReturnStatement, (node) => {
|
|
1364
1420
|
if (!node.expression) {
|
|
1365
|
-
if (
|
|
1421
|
+
if (ts13.findAncestor(node, (n) => ts13.isConstructorDeclaration(n)) && !ts13.findAncestor(node, (n) => ts13.isFunctionLike(n))) {
|
|
1366
1422
|
return "return self";
|
|
1367
1423
|
}
|
|
1368
1424
|
return "return";
|
|
1369
1425
|
}
|
|
1370
1426
|
return `return ${NodeHandler.handle(node.expression)}`;
|
|
1371
1427
|
});
|
|
1372
|
-
NodeHandler.register(
|
|
1428
|
+
NodeHandler.register(ts13.SyntaxKind.LabeledStatement, (node) => {
|
|
1373
1429
|
return `${NodeHandler.handle(node.label)}Broke = 0
|
|
1374
1430
|
${NodeHandler.handle(node.statement)}`;
|
|
1375
1431
|
});
|
|
1376
1432
|
|
|
1377
1433
|
// src/visitors/variables.ts
|
|
1378
|
-
import
|
|
1379
|
-
function handleVariableDeclaration(node
|
|
1434
|
+
import ts14 from "typescript";
|
|
1435
|
+
function handleVariableDeclaration(node) {
|
|
1380
1436
|
const left = NodeHandler.handle(node.name);
|
|
1381
1437
|
const initializerType = node.initializer ? checker.getTypeAtLocation(node.initializer) : undefined;
|
|
1382
|
-
if (
|
|
1438
|
+
if (ts14.isPropertyDeclaration(node) && initializerType?.flags === ts14.TypeFlags.Object && !node.modifiers?.some((mod) => mod.kind === ts14.SyntaxKind.StaticKeyword) && !ts14.isFunctionLike(node.initializer)) {
|
|
1383
1439
|
console.warn(`You shouldn't initialize '${left}' with an Array or an Object because in GreyScript, every instantiation refers to the same '${left}' variable.
|
|
1384
1440
|
Initialize them in the constructor instead`);
|
|
1385
1441
|
}
|
|
1386
1442
|
let right = node.initializer ? NodeHandler.handle(node.initializer) || "null" : "null";
|
|
1387
|
-
if (right
|
|
1443
|
+
if (right !== "null" && nodeIsFunctionReference(node.initializer, initializerType)) {
|
|
1388
1444
|
right = asRef(right);
|
|
1389
1445
|
}
|
|
1390
1446
|
return `${left} = ${right}`;
|
|
1391
1447
|
}
|
|
1392
|
-
NodeHandler.register(
|
|
1393
|
-
return node.declarations.map((decl) => handleVariableDeclaration(decl
|
|
1448
|
+
NodeHandler.register(ts14.SyntaxKind.VariableDeclarationList, (node) => {
|
|
1449
|
+
return node.declarations.map((decl) => handleVariableDeclaration(decl)).join(`
|
|
1394
1450
|
`);
|
|
1395
1451
|
});
|
|
1396
|
-
NodeHandler.register(
|
|
1397
|
-
if (node.modifiers?.some((modifier) => modifier.kind ===
|
|
1452
|
+
NodeHandler.register(ts14.SyntaxKind.VariableStatement, (node) => {
|
|
1453
|
+
if (node.modifiers?.some((modifier) => modifier.kind === ts14.SyntaxKind.DeclareKeyword))
|
|
1398
1454
|
return "";
|
|
1399
1455
|
return NodeHandler.handle(node.declarationList);
|
|
1400
1456
|
});
|
|
1401
|
-
NodeHandler.register(
|
|
1402
|
-
NodeHandler.register(
|
|
1403
|
-
NodeHandler.register(
|
|
1457
|
+
NodeHandler.register(ts14.SyntaxKind.VariableDeclaration, handleVariableDeclaration);
|
|
1458
|
+
NodeHandler.register(ts14.SyntaxKind.PropertyDeclaration, handleVariableDeclaration);
|
|
1459
|
+
NodeHandler.register(ts14.SyntaxKind.EnumDeclaration, (node) => {
|
|
1404
1460
|
const members = [];
|
|
1405
1461
|
function addMember(name, initializer) {
|
|
1406
1462
|
members.push(`${name}: ${initializer}`);
|
|
1407
|
-
if (isNaN(+initializer))
|
|
1463
|
+
if (Number.isNaN(+initializer))
|
|
1408
1464
|
return;
|
|
1409
1465
|
members.push(`${initializer}: ${name}`);
|
|
1410
1466
|
}
|
|
1411
1467
|
node.members.forEach((member, index) => {
|
|
1412
1468
|
let name = NodeHandler.handle(member.name);
|
|
1413
|
-
if (!
|
|
1469
|
+
if (!ts14.isStringLiteral(member.name))
|
|
1414
1470
|
name = `"${name}"`;
|
|
1415
1471
|
if (member.initializer) {
|
|
1416
1472
|
addMember(name, NodeHandler.handle(member.initializer));
|
|
@@ -1426,51 +1482,42 @@ NodeHandler.register(ts13.SyntaxKind.EnumDeclaration, (node) => {
|
|
|
1426
1482
|
return `${node.name.text} = { ${members.join(", ")} }`;
|
|
1427
1483
|
});
|
|
1428
1484
|
|
|
1429
|
-
// src/call_transformers/array.ts
|
|
1430
|
-
CallTransformer.register("Array.slice", (name, args) => {
|
|
1431
|
-
return name.slice(0, name.lastIndexOf(".")) + `[${args[0] ?? ""}:${args[1] ?? ""}]`;
|
|
1432
|
-
});
|
|
1433
|
-
CallTransformer.register("Array.toString", (name) => {
|
|
1434
|
-
const arrayName = name.slice(0, name.lastIndexOf("."));
|
|
1435
|
-
return `str(${arrayName})`;
|
|
1436
|
-
});
|
|
1437
|
-
|
|
1438
1485
|
// src/call_transformers/object.ts
|
|
1439
|
-
CallTransformer.register("ObjectConstructor.hasOwn", (
|
|
1486
|
+
CallTransformer.register("ObjectConstructor.hasOwn", (_name, args) => {
|
|
1440
1487
|
if (args.length < 2)
|
|
1441
1488
|
throw "Invalid argument count";
|
|
1442
1489
|
return `${args[0]}.hasIndex(${args[1]})`;
|
|
1443
1490
|
});
|
|
1444
|
-
CallTransformer.register("ObjectConstructor.assign", (
|
|
1491
|
+
CallTransformer.register("ObjectConstructor.assign", (_name, args) => {
|
|
1445
1492
|
if (args.length < 2)
|
|
1446
1493
|
throw "Invalid argument count";
|
|
1447
1494
|
return callUtilFunction("assign_objects", args.join(","));
|
|
1448
1495
|
});
|
|
1449
|
-
CallTransformer.register("ObjectConstructor.keys", (
|
|
1496
|
+
CallTransformer.register("ObjectConstructor.keys", (_name, args) => {
|
|
1450
1497
|
return `${args[0]}.indexes`;
|
|
1451
1498
|
});
|
|
1452
|
-
CallTransformer.register("ObjectConstructor.values", (
|
|
1499
|
+
CallTransformer.register("ObjectConstructor.values", (_name, args) => {
|
|
1453
1500
|
return `${args[0]}.values`;
|
|
1454
1501
|
});
|
|
1455
|
-
CallTransformer.register("ObjectConstructor.sum", (
|
|
1502
|
+
CallTransformer.register("ObjectConstructor.sum", (_name, args) => {
|
|
1456
1503
|
return `${args[0]}.sum`;
|
|
1457
1504
|
});
|
|
1458
|
-
CallTransformer.register("ObjectConstructor.shuffle", (
|
|
1505
|
+
CallTransformer.register("ObjectConstructor.shuffle", (_name, args) => {
|
|
1459
1506
|
return `${args[0]}.shuffle`;
|
|
1460
1507
|
});
|
|
1461
|
-
CallTransformer.register("ObjectConstructor.replace", (
|
|
1508
|
+
CallTransformer.register("ObjectConstructor.replace", (_name, args) => {
|
|
1462
1509
|
return `${args[0]}.replace(${args.slice(1).join(",")})`;
|
|
1463
1510
|
});
|
|
1464
|
-
CallTransformer.register("ObjectConstructor.remove", (
|
|
1511
|
+
CallTransformer.register("ObjectConstructor.remove", (_name, args) => {
|
|
1465
1512
|
return `${args[0]}.remove(${args[1]})`;
|
|
1466
1513
|
});
|
|
1467
|
-
CallTransformer.register("ObjectConstructor.shift", (
|
|
1514
|
+
CallTransformer.register("ObjectConstructor.shift", (_name, args) => {
|
|
1468
1515
|
return `${args[0]}.pull`;
|
|
1469
1516
|
});
|
|
1470
|
-
CallTransformer.register("ObjectConstructor.size", (
|
|
1517
|
+
CallTransformer.register("ObjectConstructor.size", (_name, args) => {
|
|
1471
1518
|
return `${args[0]}.len`;
|
|
1472
1519
|
});
|
|
1473
|
-
CallTransformer.register("ObjectConstructor.indexOf", (
|
|
1520
|
+
CallTransformer.register("ObjectConstructor.indexOf", (_name, args) => {
|
|
1474
1521
|
return `${args[0]}.indexOf(${args[1]})`;
|
|
1475
1522
|
});
|
|
1476
1523
|
CallTransformer.register("Object.toString", (name) => {
|
|
@@ -1478,14 +1525,6 @@ CallTransformer.register("Object.toString", (name) => {
|
|
|
1478
1525
|
return `str(${objectName})`;
|
|
1479
1526
|
});
|
|
1480
1527
|
|
|
1481
|
-
// src/call_transformers/string.ts
|
|
1482
|
-
CallTransformer.register("String.slice", (name, args) => {
|
|
1483
|
-
return name.slice(0, name.lastIndexOf(".")) + `[${args[0] ?? ""}:${args[1] ?? ""}]`;
|
|
1484
|
-
});
|
|
1485
|
-
CallTransformer.register("String.toString", (name) => {
|
|
1486
|
-
return name.slice(0, name.lastIndexOf("."));
|
|
1487
|
-
});
|
|
1488
|
-
|
|
1489
1528
|
// src/transpiler.ts
|
|
1490
1529
|
var program;
|
|
1491
1530
|
var checker;
|
|
@@ -1628,6 +1667,12 @@ var extensionFunctions = {
|
|
|
1628
1667
|
"end function"
|
|
1629
1668
|
].join(`
|
|
1630
1669
|
`),
|
|
1670
|
+
"Array.toString": `list.toString = function
|
|
1671
|
+
return str(self)
|
|
1672
|
+
end function`,
|
|
1673
|
+
"Array.slice": `list.slice = function(a, b)
|
|
1674
|
+
return self[a:b]
|
|
1675
|
+
end function`,
|
|
1631
1676
|
"String.startsWith": [
|
|
1632
1677
|
"string.startsWith = function(search, pos = 0)",
|
|
1633
1678
|
"\tif pos < 0 then pos = 0",
|
|
@@ -1670,6 +1715,12 @@ var extensionFunctions = {
|
|
|
1670
1715
|
"end function"
|
|
1671
1716
|
].join(`
|
|
1672
1717
|
`),
|
|
1718
|
+
"String.toString": `string.toString = function
|
|
1719
|
+
return str(self)
|
|
1720
|
+
end function`,
|
|
1721
|
+
"String.slice": `string.slice = function(a, b)
|
|
1722
|
+
return self[a:b]
|
|
1723
|
+
end function`,
|
|
1673
1724
|
"Number.toFixed": [
|
|
1674
1725
|
"number.toFixed = function(digits = 0)",
|
|
1675
1726
|
"\tdigits = floor(digits)",
|
|
@@ -1691,23 +1742,120 @@ var extensionFunctions = {
|
|
|
1691
1742
|
"end function"
|
|
1692
1743
|
].join(`
|
|
1693
1744
|
`),
|
|
1694
|
-
"
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1745
|
+
"Number.toString": `number.toString = function
|
|
1746
|
+
return str(self)
|
|
1747
|
+
end function`,
|
|
1748
|
+
"Function.toString": `funcRef.toString = function
|
|
1749
|
+
return str(@self)
|
|
1750
|
+
end function`
|
|
1751
|
+
};
|
|
1752
|
+
var globalObjects = {
|
|
1753
|
+
MapConstructor: [
|
|
1754
|
+
"Map = {}",
|
|
1755
|
+
"Map.constructor = function(entries)",
|
|
1756
|
+
"\tself.data = {}",
|
|
1757
|
+
"\tif not entries then return self",
|
|
1758
|
+
"\tfor entry in entries",
|
|
1759
|
+
"\t\tself.data[entry[0]] = entry[1]",
|
|
1699
1760
|
"\tend for",
|
|
1700
|
-
"\treturn
|
|
1761
|
+
"\treturn self",
|
|
1762
|
+
"end function",
|
|
1763
|
+
"Map.clear = function",
|
|
1764
|
+
"\tfor key in self.data.indexes",
|
|
1765
|
+
"\t\tself.data.remove(@key)",
|
|
1766
|
+
"\tend for",
|
|
1767
|
+
"end function",
|
|
1768
|
+
"Map.delete = function(key)",
|
|
1769
|
+
"\treturn self.data.remove(key)",
|
|
1770
|
+
"end function",
|
|
1771
|
+
"Map.forEach = function(callback)",
|
|
1772
|
+
"\tfor item in self.data",
|
|
1773
|
+
"\t\tcallback(@item.value, @item.key, self)",
|
|
1774
|
+
"\tend for",
|
|
1775
|
+
"end function",
|
|
1776
|
+
"Map.get = function(key)",
|
|
1777
|
+
"\tif not self.data.hasIndex(@key) then retun null",
|
|
1778
|
+
"\treturn self.data[@key]",
|
|
1779
|
+
"end function",
|
|
1780
|
+
"Map.has = function(key)",
|
|
1781
|
+
"\treturn self.data.hasIndex(@key)",
|
|
1782
|
+
"end function",
|
|
1783
|
+
"Map.set = function(key, value)",
|
|
1784
|
+
"\tself.data[@key] = @value",
|
|
1785
|
+
"\treturn self",
|
|
1786
|
+
"end function",
|
|
1787
|
+
"Map.entries = function",
|
|
1788
|
+
"\tentries = []",
|
|
1789
|
+
"\tfor item in self.data",
|
|
1790
|
+
"\t\tentries.push([@item.key, @item.value])",
|
|
1791
|
+
"\tend for",
|
|
1792
|
+
"\treturn entries",
|
|
1793
|
+
"end function",
|
|
1794
|
+
"Map.keys = function",
|
|
1795
|
+
"\treturn self.data.indexes",
|
|
1796
|
+
"end function",
|
|
1797
|
+
"Map.values = function",
|
|
1798
|
+
"\treturn self.data.values",
|
|
1701
1799
|
"end function"
|
|
1702
1800
|
].join(`
|
|
1703
1801
|
`),
|
|
1704
|
-
|
|
1802
|
+
SetConstructor: [
|
|
1803
|
+
"Set = {}",
|
|
1804
|
+
"Set.constructor = function(values)",
|
|
1805
|
+
"\tself.data = {}",
|
|
1806
|
+
"\tif not values then return self",
|
|
1807
|
+
"\tfor v in values",
|
|
1808
|
+
"\t\tself.data[@v] = 1",
|
|
1809
|
+
"\tend for",
|
|
1810
|
+
"\treturn self",
|
|
1811
|
+
"end function",
|
|
1812
|
+
"Set.add = function(value)",
|
|
1813
|
+
"\tself.data[@value] = 1",
|
|
1814
|
+
"\treturn self",
|
|
1815
|
+
"end function",
|
|
1816
|
+
"Set.clear = function",
|
|
1817
|
+
"\tfor key in self.data.indexes",
|
|
1818
|
+
"\t\tself.data.remove(@key)",
|
|
1819
|
+
"\tend for",
|
|
1820
|
+
"end function",
|
|
1821
|
+
"Set.delete = function(key)",
|
|
1822
|
+
"\treturn self.data.remove(key)",
|
|
1823
|
+
"end function",
|
|
1824
|
+
"Set.forEach = function(callback)",
|
|
1825
|
+
"\tfor key in self.data.indexes",
|
|
1826
|
+
"\t\tcallback(@key, self)",
|
|
1827
|
+
"\tend for",
|
|
1828
|
+
"end function",
|
|
1829
|
+
"Set.has = function(key)",
|
|
1830
|
+
"\treturn self.data.hasIndex(@key)",
|
|
1831
|
+
"end function",
|
|
1832
|
+
"Set.values = function",
|
|
1833
|
+
"\treturn self.data.indexes",
|
|
1834
|
+
"end function"
|
|
1835
|
+
].join(`
|
|
1836
|
+
`),
|
|
1837
|
+
Math: [
|
|
1838
|
+
'Math = { "PI": @pi, "abs": @abs, "acos": @acos, "asin": @asin, "atan": @atan, "ceil": @ceil, "floor": @floor, "cos": @cos, "sin": @sin, "tan": @tan, "sqrt": @sqrt, "sign": @sign, "round": @round, "random": @rnd, "log": @log }',
|
|
1705
1839
|
"Math.max = function(numbers)",
|
|
1706
1840
|
"\tcurr_max = null",
|
|
1707
1841
|
"\tfor num in numbers",
|
|
1708
1842
|
"\t\tif curr_max == null or num > curr_max then curr_max = num",
|
|
1709
1843
|
"\tend for",
|
|
1710
1844
|
"\treturn curr_max",
|
|
1845
|
+
"end function",
|
|
1846
|
+
"Math.min = function(numbers)",
|
|
1847
|
+
"\tcurr_min = null",
|
|
1848
|
+
"\tfor num in numbers",
|
|
1849
|
+
"\t\tif curr_min == null or num < curr_min then curr_min = num",
|
|
1850
|
+
"\tend for",
|
|
1851
|
+
"\treturn curr_min",
|
|
1852
|
+
"end function"
|
|
1853
|
+
].join(`
|
|
1854
|
+
`),
|
|
1855
|
+
Console: [
|
|
1856
|
+
'console = { "clear": @clear_screen }',
|
|
1857
|
+
"console.log = function(data)",
|
|
1858
|
+
'\tprint(data.join(", "))',
|
|
1711
1859
|
"end function"
|
|
1712
1860
|
].join(`
|
|
1713
1861
|
`)
|
|
@@ -1777,19 +1925,19 @@ var utilFunctions = {
|
|
|
1777
1925
|
].join(`
|
|
1778
1926
|
`),
|
|
1779
1927
|
nullish_coalescing_op: `nullish_coalescing_op = function(left, right)
|
|
1780
|
-
if left == null then return @right
|
|
1928
|
+
if @left == null then return @right
|
|
1781
1929
|
return @left
|
|
1782
1930
|
end function`,
|
|
1783
1931
|
or_op: `or_op = function(left, right)
|
|
1784
|
-
if not left then return @right
|
|
1932
|
+
if not @left then return @right
|
|
1785
1933
|
return @left
|
|
1786
1934
|
end function`,
|
|
1787
1935
|
is_type: `is_type = function(value, type)
|
|
1788
|
-
return typeof(value) == type
|
|
1936
|
+
return typeof(@value) == type
|
|
1789
1937
|
end function`,
|
|
1790
1938
|
conditional_expr: `conditional_expr = function(cond, when_true, when_false)
|
|
1791
|
-
if cond then return when_true
|
|
1792
|
-
return when_false
|
|
1939
|
+
if cond then return @when_true
|
|
1940
|
+
return @when_false
|
|
1793
1941
|
end function`
|
|
1794
1942
|
};
|
|
1795
1943
|
var anonFunctionsCreated = 0;
|
|
@@ -1797,9 +1945,12 @@ function createAnonFunction(body, params, insertToUtils = true) {
|
|
|
1797
1945
|
const defaultParams = new Array(3).fill(0).map((_, i) => `param${i}`);
|
|
1798
1946
|
const nextName = `func_${anonFunctionsCreated}`;
|
|
1799
1947
|
const paramString = Object.assign(defaultParams, params).join(",");
|
|
1800
|
-
const result =
|
|
1801
|
-
${
|
|
1802
|
-
|
|
1948
|
+
const result = [
|
|
1949
|
+
`${nextName} = function(${paramString})`,
|
|
1950
|
+
...body ? [body] : [],
|
|
1951
|
+
`end function`
|
|
1952
|
+
].join(`
|
|
1953
|
+
`);
|
|
1803
1954
|
anonFunctionsCreated++;
|
|
1804
1955
|
if (insertToUtils)
|
|
1805
1956
|
utilitiesToInsert.set(nextName, result);
|
|
@@ -1813,7 +1964,9 @@ function createContext(currentFileName = "file.ts") {
|
|
|
1813
1964
|
namespaceImports: {},
|
|
1814
1965
|
visitedFiles: new Set,
|
|
1815
1966
|
output: [],
|
|
1816
|
-
extraOutput: new Map
|
|
1967
|
+
extraOutput: new Map,
|
|
1968
|
+
bindingElements: {},
|
|
1969
|
+
parameterProperties: []
|
|
1817
1970
|
};
|
|
1818
1971
|
}
|
|
1819
1972
|
function transpileProgram(entryFileRelativePath) {
|
|
@@ -1825,16 +1978,16 @@ function transpileProgram(entryFileRelativePath) {
|
|
|
1825
1978
|
process.exit(1);
|
|
1826
1979
|
}
|
|
1827
1980
|
let start = Date.now();
|
|
1828
|
-
const tsconfigPath = findProjectRoot(process.cwd(), "tsconfig.json")
|
|
1829
|
-
const res =
|
|
1830
|
-
const parsed =
|
|
1981
|
+
const tsconfigPath = `${findProjectRoot(process.cwd(), "tsconfig.json")}/tsconfig.json`;
|
|
1982
|
+
const res = ts15.readConfigFile(tsconfigPath, ts15.sys.readFile);
|
|
1983
|
+
const parsed = ts15.parseJsonConfigFileContent(res.config, ts15.sys, path5.dirname(tsconfigPath));
|
|
1831
1984
|
if (!parsed.options.types)
|
|
1832
1985
|
parsed.options.types = [];
|
|
1833
1986
|
if (!parsed.options.types.includes("@grey-ts/types")) {
|
|
1834
1987
|
parsed.options.types.push("@grey-ts/types");
|
|
1835
1988
|
}
|
|
1836
1989
|
parsed.options.noLib = true;
|
|
1837
|
-
program =
|
|
1990
|
+
program = ts15.createProgram({
|
|
1838
1991
|
rootNames: parsed.fileNames,
|
|
1839
1992
|
options: parsed.options
|
|
1840
1993
|
});
|
|
@@ -1912,7 +2065,7 @@ if (command === "transpile") {
|
|
|
1912
2065
|
content = "";
|
|
1913
2066
|
continue;
|
|
1914
2067
|
}
|
|
1915
|
-
content += statement
|
|
2068
|
+
content += `${statement}
|
|
1916
2069
|
`;
|
|
1917
2070
|
}
|
|
1918
2071
|
if (content.length)
|