@grey-ts/transpiler 0.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.
Files changed (4) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +21 -0
  3. package/dist/index.js +1572 -0
  4. package/package.json +44 -0
package/dist/index.js ADDED
@@ -0,0 +1,1572 @@
1
+ #!/usr/bin/env -S node --no-warnings --no-deprecation
2
+
3
+ // src/index.ts
4
+ import * as fs3 from "node:fs";
5
+ import path5 from "node:path";
6
+
7
+ // src/transpiler.ts
8
+ import * as fs2 from "node:fs";
9
+ import * as path2 from "node:path";
10
+ import ts3 from "typescript";
11
+
12
+ // src/parser.ts
13
+ import ts from "typescript";
14
+ function parseCode(fileName, code) {
15
+ return ts.createSourceFile(fileName, code, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
16
+ }
17
+ var parser_default = parseCode;
18
+
19
+ // src/utils.ts
20
+ import fs from "node:fs";
21
+ import path from "node:path";
22
+ import ts2 from "typescript";
23
+
24
+ // src/replaceKeywords.ts
25
+ var apiNameMap = {
26
+ "GreyHack.AptClient.addRepo": "add_repo",
27
+ "GreyHack.AptClient.checkUpgrade": "check_upgrade",
28
+ "GreyHack.AptClient.delRepo": "del_repo",
29
+ "GreyHack.BlockChain.amountMined": "amount_mined",
30
+ "GreyHack.BlockChain.coinPrice": "coin_price",
31
+ "GreyHack.BlockChain.createWallet": "create_wallet",
32
+ "GreyHack.BlockChain.deleteCoin": "delete_coin",
33
+ "GreyHack.BlockChain.getCoin": "get_coin",
34
+ "GreyHack.BlockChain.getCoinName": "get_coin_name",
35
+ "GreyHack.BlockChain.loginWallet": "login_wallet",
36
+ "GreyHack.BlockChain.showHistory": "show_history",
37
+ "GreyHack.Coin.createSubWallet": "create_subwallet",
38
+ "GreyHack.Coin.getAddress": "get_address",
39
+ "GreyHack.Coin.getCycleMining": "get_cycle_mining",
40
+ "GreyHack.Coin.getMinedCoins": "get_mined_coins",
41
+ "GreyHack.Coin.getReward": "get_reward",
42
+ "GreyHack.Coin.getSubwallet": "get_subwallet",
43
+ "GreyHack.Coin.getSubwallets": "get_subwallets",
44
+ "GreyHack.Coin.resetPassword": "reset_password",
45
+ "GreyHack.Coin.setAddress": "set_address",
46
+ "GreyHack.Coin.setCycleMining": "set_cycle_mining",
47
+ "GreyHack.Coin.setReward": "set_reward",
48
+ "GreyHack.BaseComputer.file": "File",
49
+ "GreyHack.Computer.activeNetCard": "active_net_card",
50
+ "GreyHack.Computer.changePassword": "change_password",
51
+ "GreyHack.Computer.closeProgram": "close_program",
52
+ "GreyHack.Computer.connectEthernet": "connect_ethernet",
53
+ "GreyHack.Computer.connectWifi": "connect_wifi",
54
+ "GreyHack.BaseComputer.createFolder": "create_folder",
55
+ "GreyHack.Computer.createGroup": "create_group",
56
+ "GreyHack.Computer.createUser": "create_user",
57
+ "GreyHack.Computer.deleteGroup": "delete_group",
58
+ "GreyHack.Computer.deleteUser": "delete_user",
59
+ "GreyHack.BaseComputer.getName": "get_name",
60
+ "GreyHack.Computer.getPorts": "get_ports",
61
+ "GreyHack.Computer.isNetworkActive": "is_network_active",
62
+ "GreyHack.Computer.localIp": "local_ip",
63
+ "GreyHack.Computer.networkDevices": "network_devices",
64
+ "GreyHack.Computer.networkGateway": "network_gateway",
65
+ "GreyHack.Computer.publicIp": "public_ip",
66
+ "GreyHack.Computer.showProcs": "show_procs",
67
+ "GreyHack.Computer.wifiNetworks": "wifi_networks",
68
+ "GreyHack.Crypto.isEncrypted": "is_encrypted",
69
+ "GreyHack.Crypto.smtpUserList": "smtp_user_list",
70
+ "GreyHack.Ctfevent.getCreatorName": "get_creator_name",
71
+ "GreyHack.Ctfevent.getDescription": "get_description",
72
+ "GreyHack.Ctfevent.getMailContent": "get_mail_content",
73
+ "GreyHack.Ctfevent.getTemplate": "get_template",
74
+ "GreyHack.Ctfevent.playerSuccess": "player_success",
75
+ "GreyHack.DebugLibrary.applyPatch": "apply_patch",
76
+ "GreyHack.DebugLibrary.unitTesting": "unit_testing",
77
+ "GreyHack.File.allowImport": "allow_import",
78
+ "GreyHack.File.getContent": "get_content",
79
+ "GreyHack.File.getFiles": "get_files",
80
+ "GreyHack.File.getFolders": "get_folders",
81
+ "GreyHack.FtpFile.getFiles": "get_files",
82
+ "GreyHack.FtpFile.getFolders": "get_folders",
83
+ "GreyHack.BaseFile.hasPermission": "has_permission",
84
+ "GreyHack.BaseFile.isBinary": "is_binary",
85
+ "GreyHack.BaseFile.isFolder": "is_folder",
86
+ "GreyHack.BaseFile.isSymlink": "is_symlink",
87
+ "GreyHack.File.setContent": "set_content",
88
+ "GreyHack.File.setGroup": "set_group",
89
+ "GreyHack.File.setOwner": "set_owner",
90
+ "GreyHack.activeUser": "active_user",
91
+ "GreyHack.clearScreen": "clear_screen",
92
+ "GreyHack.commandInfo": "command_info",
93
+ "GreyHack.currentDate": "current_date",
94
+ "GreyHack.currentPath": "current_path",
95
+ "GreyHack.formatColumns": "format_columns",
96
+ "GreyHack.getAbsPath": "get_abs_path",
97
+ "GreyHack.getCtf": "get_ctf",
98
+ "GreyHack.getCustomObject": "get_custom_object",
99
+ "GreyHack.getRouter": "get_router",
100
+ "GreyHack.getShell": "get_shell",
101
+ "GreyHack.getSwitch": "get_switch",
102
+ "GreyHack.homeDir": "home_dir",
103
+ "GreyHack.importCode": "import_code",
104
+ "GreyHack.includeLib": "include_lib",
105
+ "GreyHack.isLanIp": "is_lan_ip",
106
+ "GreyHack.isValidIp": "is_valid_ip",
107
+ "GreyHack.launchPath": "launch_path",
108
+ "GreyHack.mailLogin": "mail_login",
109
+ "GreyHack.parentPath": "parent_path",
110
+ "GreyHack.programPath": "program_path",
111
+ "GreyHack.resetCtfPassword": "reset_ctf_password",
112
+ "GreyHack.getType": "typeof",
113
+ "GreyHack.isType": "is_type",
114
+ "GreyHack.userBankNumber": "user_bank_number",
115
+ "GreyHack.userInput": "user_input",
116
+ "GreyHack.userMailAddress": "user_mail_address",
117
+ "GreyHack.MetaLib.debugTools": "debug_tools",
118
+ "GreyHack.MetaLib.isPatched": "is_patched",
119
+ "GreyHack.MetaLib.libName": "lib_name",
120
+ "GreyHack.Metaxploit.netUse": "net_use",
121
+ "GreyHack.Metaxploit.rshellClient": "rshell_client",
122
+ "GreyHack.Metaxploit.rshellServer": "rshell_server",
123
+ "GreyHack.Metaxploit.scanAddress": "scan_address",
124
+ "GreyHack.NetSession.dumpLib": "dump_lib",
125
+ "GreyHack.NetSession.floodConnection": "flood_connection",
126
+ "GreyHack.NetSession.getNumConnGateway": "get_num_conn_gateway",
127
+ "GreyHack.NetSession.getNumPortforward": "get_num_portforward",
128
+ "GreyHack.NetSession.getNumUsers": "get_num_users",
129
+ "GreyHack.NetSession.isAnyActiveUser": "is_any_active_user",
130
+ "GreyHack.NetSession.isRootActiveUser": "is_root_active_user",
131
+ "GreyHack.Port.getLanIp": "get_lan_ip",
132
+ "GreyHack.Port.isClosed": "is_closed",
133
+ "GreyHack.Port.portNumber": "port_number",
134
+ "GreyHack.Router.bssidName": "bssid_name",
135
+ "GreyHack.Router.devicePorts": "device_ports",
136
+ "GreyHack.Router.devicesLanIp": "devices_lan_ip",
137
+ "GreyHack.Router.essidName": "essid_name",
138
+ "GreyHack.Router.firewallRules": "firewall_rules",
139
+ "GreyHack.Router.kernelVersion": "kernel_version",
140
+ "GreyHack.Router.localIp": "local_ip",
141
+ "GreyHack.Router.pingPort": "ping_port",
142
+ "GreyHack.Router.portInfo": "port_info",
143
+ "GreyHack.Router.publicIp": "public_ip",
144
+ "GreyHack.Router.usedPorts": "used_ports",
145
+ "GreyHack.Service.installService": "install_service",
146
+ "GreyHack.Service.startService": "start_service",
147
+ "GreyHack.Service.stopService": "stop_service",
148
+ "GreyHack.Shell.connectService": "connect_service",
149
+ "GreyHack.Shell.hostComputer": "host_computer",
150
+ "GreyHack.Shell.startTerminal": "start_terminal",
151
+ "GreyHack.SmartAppliance.overrideSettings": "override_settings",
152
+ "GreyHack.SmartAppliance.setAlarm": "set_alarm",
153
+ "GreyHack.SubWallet.checkPassword": "check_password",
154
+ "GreyHack.SubWallet.getBalance": "get_balance",
155
+ "GreyHack.SubWallet.getInfo": "get_info",
156
+ "GreyHack.SubWallet.getUser": "get_user",
157
+ "GreyHack.SubWallet.lastTransaction": "last_transaction",
158
+ "GreyHack.SubWallet.setInfo": "set_info",
159
+ "GreyHack.SubWallet.walletUsername": "wallet_username",
160
+ "GreyHack.TrafficNet.cameraLinkSystem": "camera_link_system",
161
+ "GreyHack.TrafficNet.getCredentialsInfo": "get_credentials_info",
162
+ "GreyHack.TrafficNet.locateVehicle": "locate_vehicle",
163
+ "GreyHack.Wallet.buyCoin": "buy_coin",
164
+ "GreyHack.Wallet.cancelPendingTrade": "cancel_pending_trade",
165
+ "GreyHack.Wallet.getBalance": "get_balance",
166
+ "GreyHack.Wallet.getGlobalOffers": "get_global_offers",
167
+ "GreyHack.Wallet.getPendingTrade": "get_pending_trade",
168
+ "GreyHack.Wallet.getPin": "get_pin",
169
+ "GreyHack.Wallet.listCoins": "list_coins",
170
+ "GreyHack.Wallet.listGlobalCoins": "list_global_coins",
171
+ "GreyHack.Wallet.resetPassword": "reset_password",
172
+ "GreyHack.Wallet.sellCoin": "sell_coin",
173
+ "GreyHack.Wallet.showNodes": "show_nodes",
174
+ "String.isMatch": "is_match",
175
+ "String.toInt": "to_int",
176
+ "String.length": "len",
177
+ "Object.size": "len",
178
+ "Array.length": "len"
179
+ };
180
+ var propertyAccessReplacements = {
181
+ "Math.PI": "pi",
182
+ "Math.abs": "abs",
183
+ "Math.acos": "acos",
184
+ "Math.asin": "asin",
185
+ "Math.atan": "atan",
186
+ "Math.ceil": "ceil",
187
+ "Math.floor": "floor",
188
+ "Math.cos": "cos",
189
+ "Math.sin": "sin",
190
+ "Math.tan": "tan",
191
+ "Math.sqrt": "sqrt",
192
+ "Math.sign": "sign",
193
+ "Math.round": "round",
194
+ "Math.random": "rnd",
195
+ "Math.log": "log",
196
+ "String.prototype": "string",
197
+ "Number.prototype": "number",
198
+ "Object.prototype": "map",
199
+ "Array.prototype": "list",
200
+ "Function.prototype": "funcRef"
201
+ };
202
+
203
+ // src/utils.ts
204
+ var knownOperators = new Set([
205
+ "=",
206
+ "+",
207
+ "+=",
208
+ "-",
209
+ "-=",
210
+ "++",
211
+ "--",
212
+ "**",
213
+ "&&",
214
+ "==",
215
+ "===",
216
+ "!=",
217
+ "!==",
218
+ "??",
219
+ "??=",
220
+ "in",
221
+ "||",
222
+ "<",
223
+ "<=",
224
+ ">",
225
+ ">=",
226
+ "*",
227
+ "/",
228
+ "%",
229
+ "~",
230
+ "&",
231
+ "|",
232
+ "^",
233
+ "<<",
234
+ ">>",
235
+ ">>>",
236
+ "instanceof"
237
+ ]);
238
+ function getOperatorToken(node) {
239
+ let operatorToken = ts2.tokenToString(node.kind);
240
+ if (!operatorToken)
241
+ return null;
242
+ if (!knownOperators.has(operatorToken))
243
+ throw `Can't handle operator '${operatorToken}' yet`;
244
+ if (operatorToken == "||")
245
+ operatorToken = "or";
246
+ else if (operatorToken == "&&")
247
+ operatorToken = "and";
248
+ else if (operatorToken == "===")
249
+ operatorToken = "==";
250
+ else if (operatorToken == "!==")
251
+ operatorToken = "!=";
252
+ return operatorToken;
253
+ }
254
+ function transformString(value) {
255
+ value = value.replaceAll('"', '""').replaceAll(`
256
+ `, ` \\n`);
257
+ return value;
258
+ }
259
+ function nodeIsFunctionReference(node, type) {
260
+ if (ts2.isCallOrNewExpression(node) || ts2.isCallOrNewExpression(node.parent) && node === node.parent.expression)
261
+ return false;
262
+ if (ts2.isFunctionLike(node))
263
+ return false;
264
+ type ??= checker.getTypeAtLocation(node);
265
+ if (!type.getCallSignatures().length)
266
+ return false;
267
+ return true;
268
+ }
269
+ function asRef(value) {
270
+ if (value[0] === "@")
271
+ return value;
272
+ return "@" + value;
273
+ }
274
+ function getSourceFiles(absPath) {
275
+ if (!fs.existsSync(absPath))
276
+ throw new Error(`File ${absPath} doesn't exist`);
277
+ const output = [];
278
+ const filePaths = [absPath];
279
+ while (filePaths.length) {
280
+ const file = filePaths.shift();
281
+ const stat = fs.statSync(file);
282
+ if (stat.isDirectory()) {
283
+ filePaths.push(...fs.readdirSync(file).map((name) => path.join(file, name)));
284
+ continue;
285
+ }
286
+ const existing = program.getSourceFile(file);
287
+ if (existing) {
288
+ output.push(existing);
289
+ continue;
290
+ }
291
+ const source = parser_default(file, fs.readFileSync(file, { encoding: "utf-8" }));
292
+ output.push(source);
293
+ }
294
+ return output;
295
+ }
296
+ function replaceIdentifier(original, type, propertyName) {
297
+ let symbol;
298
+ if (type.isUnion()) {
299
+ if (propertyName) {
300
+ for (const t of type.types) {
301
+ symbol = t.getProperty(propertyName);
302
+ if (symbol)
303
+ break;
304
+ }
305
+ } else {
306
+ symbol = type.types.find((t) => t.flags !== ts2.TypeFlags.Undefined && t.symbol)?.symbol;
307
+ }
308
+ } else {
309
+ symbol = propertyName ? type.getProperty(propertyName) : type.symbol;
310
+ }
311
+ if (!symbol)
312
+ return original;
313
+ const symbolFullName = checker.getFullyQualifiedName(symbol);
314
+ const replaceValue = apiNameMap[symbolFullName];
315
+ if (!replaceValue)
316
+ return original;
317
+ const dotIndex = symbolFullName.lastIndexOf(".");
318
+ const strToReplace = dotIndex !== null ? symbolFullName.slice(dotIndex + 1) : symbolFullName;
319
+ if (strToReplace != original)
320
+ return original;
321
+ return replaceValue;
322
+ }
323
+ function replacePropertyAccess(original, symbol) {
324
+ if (!symbol)
325
+ return original;
326
+ const symbolFullName = checker.getFullyQualifiedName(symbol);
327
+ const replaceValue = propertyAccessReplacements[symbolFullName];
328
+ if (!replaceValue || original !== symbolFullName)
329
+ return original;
330
+ return replaceValue;
331
+ }
332
+ function findProjectRoot(dir, fileToSearch = "package.json") {
333
+ while (!fs.existsSync(path.join(dir, fileToSearch))) {
334
+ const parent = path.dirname(dir);
335
+ if (parent === dir)
336
+ throw new Error(`No ${fileToSearch} found`);
337
+ dir = parent;
338
+ }
339
+ return dir;
340
+ }
341
+ function callUtilFunction(functionName, ...params) {
342
+ calledUtilFunctions.add(functionName);
343
+ return `${functionName}(${params.join(", ")})`;
344
+ }
345
+
346
+ // src/transpiler.ts
347
+ class NodeHandler {
348
+ static handlers = new Map;
349
+ static transpileContext;
350
+ static register(kind, handler) {
351
+ if (this.handlers.has(kind))
352
+ throw `${ts3.SyntaxKind[kind]} (${kind}) is already registered`;
353
+ this.handlers.set(kind, handler);
354
+ }
355
+ static handle(node) {
356
+ const handler = this.handlers.get(node.kind);
357
+ if (!handler) {
358
+ console.log(`Unsupported syntax ${ts3.SyntaxKind[node.kind]} (kind ${node.kind}) was not transpiled: ${node.getText()}`);
359
+ this.printLineAndCol(node);
360
+ return "null";
361
+ }
362
+ try {
363
+ const result = handler(node, this.transpileContext);
364
+ return result;
365
+ } catch (error) {
366
+ console.error(error);
367
+ this.printLineAndCol(node);
368
+ return "null";
369
+ }
370
+ }
371
+ static printLineAndCol(node) {
372
+ const source = node.getSourceFile();
373
+ const lineAndChar = source.getLineAndCharacterOfPosition(node.pos);
374
+ console.log(`At ${source.fileName}: line ${lineAndChar.line + 1}, col ${lineAndChar.character + 1}`);
375
+ }
376
+ }
377
+ NodeHandler.register(ts3.SyntaxKind.TypeAliasDeclaration, () => "");
378
+ NodeHandler.register(ts3.SyntaxKind.InterfaceDeclaration, () => "");
379
+ NodeHandler.register(ts3.SyntaxKind.EndOfFileToken, () => "");
380
+ NodeHandler.register(ts3.SyntaxKind.EmptyStatement, () => "");
381
+ var program;
382
+ var checker;
383
+ var anonFunctions = new Map;
384
+ var calledUtilFunctions = new Set;
385
+ var utilFunctions2 = {
386
+ get_property: [
387
+ "get_property = function(obj, key)",
388
+ "\tif not obj then return null",
389
+ "\tif obj.hasIndex(key) then return obj[key]",
390
+ "\tisaobj = obj",
391
+ '\twhile isaobj.hasIndex("__isa")',
392
+ '\t\tisaobj = obj["__isa"]',
393
+ "\t\tif isaobj.hasIndex(key) then",
394
+ "\t\t\tval = obj[key]",
395
+ "\t\t\treturn val",
396
+ "\t\tend if",
397
+ "\tend while",
398
+ "\treturn null",
399
+ "end function"
400
+ ].join(`
401
+ `),
402
+ assign_objects: [
403
+ "assign_objects = function(target, source1, source2, source3)",
404
+ "\tassign_to_list = function(target, source)",
405
+ "\t\tif source isa list then",
406
+ "\t\t\tfor i in range(0, source.len - 1, 1)",
407
+ "\t\t\t\tif target.len <= i then target.push(null)",
408
+ "\t\t\t\ttarget[i] = source[i]",
409
+ "\t\t\tend for",
410
+ "\t\telse if source isa map then",
411
+ "\t\t\tfor item in source",
412
+ "\t\t\t\tkey = str(item.key).to_int",
413
+ "\t\t\t\tif key isa number then target[key] = item.value",
414
+ "\t\t\tend for",
415
+ "\t\tend if",
416
+ "\t\treturn target",
417
+ "\tend function",
418
+ "\tcounter = 0",
419
+ "\tassign_object = function(target, source)",
420
+ "\t\tif target isa list then return assign_to_list(target, source)",
421
+ "\t\tif source isa list then",
422
+ "\t\t\tfor i in range(0, source.len - 1, 1)",
423
+ "\t\t\t\ttarget[str(i)] = source[i]",
424
+ "\t\t\tend for",
425
+ "\t\telse if source isa map then",
426
+ "\t\t\tfor item in source",
427
+ "\t\t\t\ttarget[item.key] = item.value",
428
+ "\t\t\tend for",
429
+ "\t\telse",
430
+ "\t\t\ttarget[str(outer.counter)] = source",
431
+ "\t\t\touter.counter = outer.counter + 1",
432
+ "\t\tend if",
433
+ "\tend function",
434
+ "\tif source1 isa list then",
435
+ "\t\tif target isa list then return assign_to_list(target, source1)",
436
+ "\t\tfor source in source1",
437
+ "\t\t\tassign_object(target, source)",
438
+ "\t\tend for",
439
+ "\t\treturn target",
440
+ "\tend if",
441
+ "\tif source1 then assign_object(target, source1)",
442
+ "\tif source2 then assign_object(target, source2)",
443
+ "\tif source3 then assign_object(target, source3)",
444
+ "\treturn target",
445
+ "end function"
446
+ ].join(`
447
+ `),
448
+ array_map: [
449
+ "array_map = function(array, callback)",
450
+ "\tindex = 0",
451
+ "\tout = []",
452
+ "\tfor item in array",
453
+ "\t\tout.push(callback(item, index, array))",
454
+ "\t\tindex = index + 1",
455
+ "\tend for",
456
+ "\treturn out",
457
+ "end function"
458
+ ].join(`
459
+ `),
460
+ array_filter: [
461
+ "array_filter = function(array, predicate)",
462
+ "\tindex = 0",
463
+ "\tout = []",
464
+ "\tfor item in array",
465
+ "\t\tif predicate(item, index, array) then out.push(item)",
466
+ "\t\tindex = index + 1",
467
+ "\tend for",
468
+ "\treturn out",
469
+ "end function"
470
+ ].join(`
471
+ `),
472
+ array_find: [
473
+ "array_find = function(array, predicate)",
474
+ "\tindex = 0",
475
+ "\tfor item in array",
476
+ "\t\tif predicate(item, index, array) then return item",
477
+ "\t\tindex = index + 1",
478
+ "\tend for",
479
+ "\treturn null",
480
+ "end function"
481
+ ].join(`
482
+ `),
483
+ array_some: [
484
+ "array_some = function(array, predicate)",
485
+ "\tindex = 0",
486
+ "\tfor item in array",
487
+ "\t\tif predicate(item, index, array) then return 1",
488
+ "\t\tindex = index + 1",
489
+ "\tend for",
490
+ "\treturn 0",
491
+ "end function"
492
+ ].join(`
493
+ `),
494
+ array_every: [
495
+ "array_every = function(array, predicate)",
496
+ "\tindex = 0",
497
+ "\tfor item in array",
498
+ "\t\tif not predicate(item, index, array) then return 0",
499
+ "\t\tindex = index + 1",
500
+ "\tend for",
501
+ "\treturn 1",
502
+ "end function"
503
+ ].join(`
504
+ `),
505
+ array_concat: [
506
+ "array_concat = function(target, items)",
507
+ "\tout = target[0:]",
508
+ "\tfor item in items",
509
+ "\t\tif item isa list then out = out + item else out.push(item)",
510
+ "\tend for",
511
+ "\treturn out",
512
+ "end function"
513
+ ].join(`
514
+ `),
515
+ math_min: [
516
+ "math_min = function(numbers)",
517
+ "\tcurr_min = null",
518
+ "\tfor num in numbers",
519
+ "\t\tif curr_min == null or num < curr_min then curr_min = num",
520
+ "\tend for",
521
+ "\treturn curr_min",
522
+ "end function"
523
+ ].join(`
524
+ `),
525
+ math_max: [
526
+ "math_max = function(numbers)",
527
+ "\tcurr_max = null",
528
+ "\tfor num in numbers",
529
+ "\t\tif curr_max == null or num > curr_max then curr_max = num",
530
+ "\tend for",
531
+ "\treturn curr_max",
532
+ "end function"
533
+ ].join(`
534
+ `),
535
+ nullish_coalescing_op: `nullish_coalescing_op = function(left, right)
536
+ if left == null then return @right
537
+ return @left
538
+ end function`,
539
+ or_op: `or_op = function(left, right)
540
+ if not left then return @right
541
+ return @left
542
+ end function`,
543
+ is_type: `is_type = function(value, type)
544
+ if typeof(value) == type then return 1
545
+ return 0
546
+ end function`,
547
+ conditional_expr: `conditional_expr = function(cond, when_true, when_false)
548
+ if cond then return when_true
549
+ return when_false
550
+ end function`
551
+ };
552
+ function createAnonFunction(body, params) {
553
+ const defaultParams = new Array(3).fill(0).map((_, i) => `param${i}`);
554
+ const nextName = `func_${anonFunctions.size}`;
555
+ const paramString = Object.assign(defaultParams, params).join(",");
556
+ const result = `${nextName} = function(${paramString})
557
+ ${body}
558
+ end function`;
559
+ anonFunctions.set(nextName, result);
560
+ return { name: nextName, str: result };
561
+ }
562
+ function transpileProgram(entryFileRelativePath) {
563
+ const ctx = {
564
+ currentFolder: "",
565
+ currentFilePath: path2.resolve(process.cwd(), entryFileRelativePath),
566
+ namedImports: {},
567
+ namespaceImports: {},
568
+ visitedFiles: {},
569
+ output: []
570
+ };
571
+ NodeHandler.transpileContext = ctx;
572
+ ctx.currentFolder = path2.dirname(ctx.currentFilePath);
573
+ if (!fs2.existsSync(ctx.currentFilePath)) {
574
+ console.error(`Error: file '${ctx.currentFilePath}' doesn't exist`);
575
+ process.exit(1);
576
+ }
577
+ let start = Date.now();
578
+ const tsconfigPath = findProjectRoot(process.cwd(), "tsconfig.json") + "/tsconfig.json";
579
+ const res = ts3.readConfigFile(tsconfigPath, ts3.sys.readFile);
580
+ const parsed = ts3.parseJsonConfigFileContent(res.config, ts3.sys, path2.dirname(tsconfigPath));
581
+ if (!parsed.options.types)
582
+ parsed.options.types = [];
583
+ if (!parsed.options.types.includes("@grey-ts/types")) {
584
+ parsed.options.types.push("@grey-ts/types");
585
+ }
586
+ parsed.options.noLib = true;
587
+ program = ts3.createProgram({
588
+ rootNames: parsed.fileNames,
589
+ options: parsed.options
590
+ });
591
+ console.log(`Program creation took ${Date.now() - start} ms`);
592
+ start = Date.now();
593
+ checker = program.getTypeChecker();
594
+ const entry = program.getSourceFile(ctx.currentFilePath);
595
+ if (!entry) {
596
+ console.error(`Error: failed to find '${ctx.currentFilePath}' from the included sources`);
597
+ process.exit(1);
598
+ }
599
+ transpileSourceFile(entry, ctx);
600
+ if (anonFunctions.size) {
601
+ for (const declaration of anonFunctions.values())
602
+ ctx.output.unshift(declaration);
603
+ anonFunctions.clear();
604
+ }
605
+ if (calledUtilFunctions.size) {
606
+ for (const call of calledUtilFunctions.keys())
607
+ ctx.output.unshift(utilFunctions2[call]);
608
+ calledUtilFunctions.clear();
609
+ }
610
+ console.log(`Transpiling took ${Date.now() - start} ms`);
611
+ return ctx.output.join(`
612
+ `);
613
+ }
614
+ function transpileSourceFile(sourceFile, ctx, returnResult) {
615
+ if (ctx.visitedFiles[sourceFile.fileName])
616
+ return "";
617
+ ctx.visitedFiles[sourceFile.fileName] = true;
618
+ if (sourceFile.isDeclarationFile)
619
+ return "";
620
+ if (program.isSourceFileDefaultLibrary(sourceFile) || program.isSourceFileFromExternalLibrary(sourceFile))
621
+ return "";
622
+ const prevFile = ctx.currentFilePath;
623
+ ctx.currentFilePath = sourceFile.fileName;
624
+ ctx.currentFolder = path2.dirname(sourceFile.fileName);
625
+ ctx.namedImports[sourceFile.fileName] = {};
626
+ ctx.namespaceImports[sourceFile.fileName] = new Set;
627
+ const output = [];
628
+ sourceFile.forEachChild((node) => {
629
+ const result = NodeHandler.handle(node);
630
+ if (!result)
631
+ return;
632
+ if (!returnResult)
633
+ ctx.output.push(result);
634
+ else
635
+ output.push(result);
636
+ });
637
+ ctx.currentFilePath = prevFile;
638
+ ctx.currentFolder = path2.dirname(prevFile);
639
+ return output.join(`
640
+ `);
641
+ }
642
+
643
+ // src/visitors/assignments.ts
644
+ import ts4 from "typescript";
645
+ NodeHandler.register(ts4.SyntaxKind.PropertyAssignment, (node) => {
646
+ let right = NodeHandler.handle(node.initializer);
647
+ if (nodeIsFunctionReference(node.initializer))
648
+ right = asRef(right);
649
+ if (ts4.isNumericLiteral(node.name) || ts4.isStringLiteral(node.name) || ts4.isComputedPropertyName(node.name))
650
+ return `${NodeHandler.handle(node.name)}: ${right}`;
651
+ return `"${NodeHandler.handle(node.name)}": ${right}`;
652
+ });
653
+ NodeHandler.register(ts4.SyntaxKind.ShorthandPropertyAssignment, (node) => {
654
+ const name = NodeHandler.handle(node.name);
655
+ return `"${name}": ${nodeIsFunctionReference(node.name) ? asRef(name) : name}`;
656
+ });
657
+ NodeHandler.register(ts4.SyntaxKind.ComputedPropertyName, (node) => {
658
+ return NodeHandler.handle(node.expression);
659
+ });
660
+
661
+ // src/visitors/classes.ts
662
+ import ts5 from "typescript";
663
+ NodeHandler.register(ts5.SyntaxKind.ClassDeclaration, (node) => {
664
+ if (node.modifiers?.some((m) => m.kind === ts5.SyntaxKind.DeclareKeyword))
665
+ return "";
666
+ const name = node.name ? node.name.text : "anon";
667
+ const extensions = node.heritageClauses?.filter((h) => h.token === ts5.SyntaxKind.ExtendsKeyword);
668
+ let output = `${name} = {}`;
669
+ if (extensions && extensions.length && extensions[0].types.length)
670
+ output = `${name} = new ${NodeHandler.handle(extensions[0].types[0].expression)}`;
671
+ for (const member of node.members) {
672
+ if (ts5.isMethodDeclaration(member) || ts5.isConstructorDeclaration(member)) {
673
+ if (!member.body)
674
+ continue;
675
+ output += `
676
+ ${name}.${NodeHandler.handle(member)}`;
677
+ } else if (ts5.isPropertyDeclaration(member)) {
678
+ output += `
679
+ ${name}.${NodeHandler.handle(member)}`;
680
+ } else {
681
+ output += `
682
+ ${name}.${NodeHandler.handle(member)}`;
683
+ }
684
+ }
685
+ return output;
686
+ });
687
+ NodeHandler.register(ts5.SyntaxKind.Constructor, (node) => {
688
+ if (!node.body)
689
+ return "";
690
+ const params = node.parameters.map((param) => NodeHandler.handle(param)).join(", ");
691
+ const body = NodeHandler.handle(node.body);
692
+ return `constructor = function(${params})
693
+ ${body}
694
+ return self
695
+ end function`;
696
+ });
697
+ NodeHandler.register(ts5.SyntaxKind.GetAccessor, (node) => {
698
+ if (!node.body)
699
+ return "";
700
+ const body = NodeHandler.handle(node.body);
701
+ return `${NodeHandler.handle(node.name)} = function
702
+ ${body}
703
+ end function`;
704
+ });
705
+ NodeHandler.register(ts5.SyntaxKind.SetAccessor, (node) => {
706
+ if (!node.body)
707
+ return "";
708
+ const body = NodeHandler.handle(node.body);
709
+ const params = node.parameters.map((param) => NodeHandler.handle(param));
710
+ return `${NodeHandler.handle(node.name)} = function(${params.join(", ")})
711
+ ${body}
712
+ end function`;
713
+ });
714
+
715
+ // src/visitors/expressions.ts
716
+ import ts7 from "typescript";
717
+
718
+ // src/callTransformer.ts
719
+ import path3 from "node:path";
720
+ import ts6 from "typescript";
721
+ class CallTransformer {
722
+ static handlers = new Map;
723
+ static register(symbolFullName, handler) {
724
+ if (this.handlers.has(symbolFullName))
725
+ throw `Handler for '${symbolFullName}' was already registered`;
726
+ this.handlers.set(symbolFullName, handler);
727
+ }
728
+ static handle(symbolFullName, functionName, callArgs, node, ctx) {
729
+ const handler = this.handlers.get(symbolFullName);
730
+ if (!handler)
731
+ return null;
732
+ return handler(functionName, callArgs, node, ctx);
733
+ }
734
+ }
735
+ CallTransformer.register("Array.concat", (name, args) => {
736
+ const dotI = name.lastIndexOf(".");
737
+ const arrayName = name.slice(0, dotI);
738
+ return callUtilFunction("array_concat", arrayName, args.join(","));
739
+ });
740
+ CallTransformer.register("Array.map", (name, args) => {
741
+ if (!args.length)
742
+ throw "Invalid argument count";
743
+ return callUtilFunction("array_map", name.slice(0, name.lastIndexOf(".")), args[0]);
744
+ });
745
+ CallTransformer.register("Array.filter", (name, args) => {
746
+ if (!args.length)
747
+ throw "Invalid argument count";
748
+ return callUtilFunction("array_filter", name.slice(0, name.lastIndexOf(".")), args[0]);
749
+ });
750
+ CallTransformer.register("Array.find", (name, args) => {
751
+ if (!args.length)
752
+ throw "Invalid argument count";
753
+ return callUtilFunction("array_find", name.slice(0, name.lastIndexOf(".")), args[0]);
754
+ });
755
+ CallTransformer.register("Array.some", (name, args) => {
756
+ if (!args.length)
757
+ throw "Invalid argument count";
758
+ return callUtilFunction("array_some", name.slice(0, name.lastIndexOf(".")), args[0]);
759
+ });
760
+ CallTransformer.register("Array.every", (name, args) => {
761
+ if (!args.length)
762
+ throw "Invalid argument count";
763
+ return callUtilFunction("array_every", name.slice(0, name.lastIndexOf(".")), args[0]);
764
+ });
765
+ CallTransformer.register("Math.min", (name, args) => {
766
+ return callUtilFunction("math_min", `${args.join(",")}`);
767
+ });
768
+ CallTransformer.register("Math.max", (name, args) => {
769
+ return callUtilFunction("math_max", `${args.join(",")}`);
770
+ });
771
+ CallTransformer.register("ObjectConstructor.hasOwn", (name, args) => {
772
+ if (args.length < 2)
773
+ throw "Invalid argument count";
774
+ return `${args[0]}.hasIndex(${args[1]})`;
775
+ });
776
+ CallTransformer.register("ObjectConstructor.assign", (name, args) => {
777
+ if (args.length < 2)
778
+ throw "Invalid argument count";
779
+ return callUtilFunction("assign_objects", args.join(","));
780
+ });
781
+ CallTransformer.register("ObjectConstructor.keys", (name, args) => {
782
+ return `${args[0]}.indexes`;
783
+ });
784
+ CallTransformer.register("GreyHack.include", (name, args, node, ctx) => {
785
+ if (!node.arguments.length)
786
+ return "";
787
+ const fileArg = node.arguments[0];
788
+ if (!ts6.isStringLiteralLike(fileArg))
789
+ throw "You can't include variables";
790
+ const absPath = path3.resolve(ctx.currentFolder, fileArg.text);
791
+ const sources = getSourceFiles(absPath);
792
+ for (const source of sources) {
793
+ transpileSourceFile(source, ctx);
794
+ }
795
+ return "";
796
+ });
797
+
798
+ // src/visitors/expressions.ts
799
+ function hasRestParam(params) {
800
+ if (!params.length)
801
+ return false;
802
+ const lastParam = params[params.length - 1];
803
+ return !!(lastParam.valueDeclaration && ts7.isParameter(lastParam.valueDeclaration) && lastParam.valueDeclaration.dotDotDotToken);
804
+ }
805
+ function handleCallArgs(callNode, ctx) {
806
+ const args = callNode.arguments;
807
+ if (!args)
808
+ return [];
809
+ const result = [];
810
+ const restItems = [];
811
+ const restArrays = [];
812
+ const params = checker.getResolvedSignature(callNode)?.parameters || [];
813
+ const hasRestParameter = hasRestParam(params);
814
+ const nonRestParamCount = params.length - Number(hasRestParameter);
815
+ let remainingRequired = nonRestParamCount;
816
+ function pushArgs(...items) {
817
+ for (const item of items) {
818
+ if (remainingRequired > 0) {
819
+ result.push(item);
820
+ remainingRequired--;
821
+ continue;
822
+ }
823
+ restItems.push(item);
824
+ }
825
+ }
826
+ for (const arg of args) {
827
+ if (!ts7.isSpreadElement(arg)) {
828
+ pushArgs(NodeHandler.handle(arg));
829
+ continue;
830
+ }
831
+ if (ts7.isArrayLiteralExpression(arg.expression)) {
832
+ const arrayItems = [];
833
+ const outArrs = [];
834
+ handleArrayLiteralExpression(arg.expression, ctx, arrayItems, outArrs);
835
+ if (outArrs.length > 1)
836
+ throw "The transpiler can't handle it yet if there are nested spread elements as parameters";
837
+ pushArgs(...arrayItems);
838
+ continue;
839
+ }
840
+ const arrayName = NodeHandler.handle(arg.expression);
841
+ if (remainingRequired > 0) {
842
+ for (let i = 0;i < remainingRequired; i++) {
843
+ result.push(`${arrayName}[${i}]`);
844
+ }
845
+ if (hasRestParameter)
846
+ restArrays.push(`${arrayName}[${remainingRequired}:]`);
847
+ remainingRequired = 0;
848
+ continue;
849
+ }
850
+ if (restItems.length) {
851
+ restArrays.push(`[${restItems.join(",")}]`);
852
+ restItems.length = 0;
853
+ }
854
+ restArrays.push(arrayName);
855
+ }
856
+ if (restItems.length) {
857
+ if (remainingRequired > 0 || !hasRestParameter) {
858
+ result.push(...restItems);
859
+ } else {
860
+ const processedItems = [];
861
+ for (const item of restItems) {
862
+ if (item[0] !== "[") {
863
+ processedItems.push(item);
864
+ continue;
865
+ }
866
+ if (processedItems.length) {
867
+ restArrays.push(`[${processedItems.join(",")}]`);
868
+ processedItems.length = 0;
869
+ }
870
+ restArrays.push(item);
871
+ }
872
+ if (processedItems.length)
873
+ restArrays.push(`[${processedItems.join(",")}]`);
874
+ }
875
+ }
876
+ if (restArrays.length) {
877
+ result.push(restArrays.join(" + "));
878
+ }
879
+ return result;
880
+ }
881
+ NodeHandler.register(ts7.SyntaxKind.CallExpression, (node, ctx) => {
882
+ const args = handleCallArgs(node, ctx);
883
+ let name = NodeHandler.handle(node.expression);
884
+ const type = checker.getTypeAtLocation(node.expression);
885
+ let symbolFullName = type.symbol ? checker.getFullyQualifiedName(type.symbol) : "";
886
+ if (!symbolFullName || symbolFullName.startsWith("__")) {
887
+ const symbol = checker.getSymbolAtLocation(node.expression);
888
+ symbolFullName = symbol ? checker.getFullyQualifiedName(symbol) : "";
889
+ }
890
+ const transformed = CallTransformer.handle(symbolFullName, name, args, node, ctx);
891
+ if (transformed !== null)
892
+ return transformed;
893
+ if (name === "is_type" && !calledUtilFunctions.has("is_type")) {
894
+ calledUtilFunctions.add("is_type");
895
+ }
896
+ if (!args.length)
897
+ return name;
898
+ return `${name}(${args.join(", ")})`;
899
+ });
900
+ NodeHandler.register(ts7.SyntaxKind.NewExpression, (node, ctx) => {
901
+ const args = handleCallArgs(node, ctx);
902
+ let output = `(new ${NodeHandler.handle(node.expression)}).constructor`;
903
+ if (args.length)
904
+ output += `(${args.join(",")})`;
905
+ return output;
906
+ });
907
+ NodeHandler.register(ts7.SyntaxKind.BinaryExpression, (node) => {
908
+ let operatorToken = getOperatorToken(node.operatorToken) || node.operatorToken.getText();
909
+ if (operatorToken === "=" && ts7.isBinaryExpression(node.right) && node.right.operatorToken.kind === ts7.SyntaxKind.EqualsToken) {
910
+ throw "Assignment chaining is not supported";
911
+ }
912
+ let right = NodeHandler.handle(node.right);
913
+ if (nodeIsFunctionReference(node.right))
914
+ right = asRef(right);
915
+ if (ts7.isPropertyAccessExpression(node.left)) {
916
+ const leftType = checker.getTypeAtLocation(node.left.expression);
917
+ const symbol = leftType.getProperty(node.left.name.text);
918
+ if (symbol?.declarations && ts7.isSetAccessor(symbol.declarations[0])) {
919
+ if (operatorToken != "=") {
920
+ throw "Set accessor can only work with = operator for now.";
921
+ }
922
+ return `${NodeHandler.handle(node.left.expression)}.${node.left.name.text}(${right})`;
923
+ }
924
+ }
925
+ let left = NodeHandler.handle(node.left);
926
+ if (nodeIsFunctionReference(node.left))
927
+ left = asRef(left);
928
+ if (operatorToken === "or" && (ts7.isVariableDeclaration(node.parent) || ts7.isPropertyAssignment(node.parent))) {
929
+ return callUtilFunction("or_op", left, right);
930
+ }
931
+ if (operatorToken === "instanceof") {
932
+ const rightSymbol = checker.getSymbolAtLocation(node.right);
933
+ const classIdMember = rightSymbol?.members?.get(ts7.escapeLeadingUnderscores("classID"));
934
+ if (!classIdMember) {
935
+ throw `Can't handle this 'instanceof' operator because '${right}' doesn't have a 'classID' member, which is needed in GreyScript to check a type`;
936
+ }
937
+ const declaration = classIdMember.valueDeclaration;
938
+ if (!declaration || !("initializer" in declaration) || !declaration.initializer) {
939
+ throw `The 'classID' property of '${right}' isn't initialized`;
940
+ }
941
+ return `${left}.classID == typeof(${right})`;
942
+ }
943
+ if (operatorToken === "??") {
944
+ return callUtilFunction("nullish_coalescing_op", left, right);
945
+ } else if (operatorToken === "??=") {
946
+ return `${left} = ${callUtilFunction("nullish_coalescing_op", left, right)}`;
947
+ } else if (operatorToken === "in") {
948
+ return `${right}.hasIndex(${left})`;
949
+ } else if (operatorToken === "&") {
950
+ return `bitwise("&", ${left}, ${right})`;
951
+ } else if (operatorToken === "|") {
952
+ return `bitwise("|", ${left}, ${right})`;
953
+ } else if (operatorToken === "^") {
954
+ return `bitwise("^", ${left}, ${right})`;
955
+ } else if (operatorToken === "<<") {
956
+ return `bitwise("<<", ${left}, ${right})`;
957
+ } else if (operatorToken === ">>") {
958
+ return `bitwise(">>", ${left}, ${right})`;
959
+ } else if (operatorToken === ">>>") {
960
+ return `bitwise(">>>", ${left}, ${right})`;
961
+ }
962
+ if (operatorToken == "+=" || operatorToken == "-=")
963
+ return `${left} = ${left} ${operatorToken[0]} ${right}`;
964
+ if (operatorToken === "**")
965
+ operatorToken = "^";
966
+ return `${left} ${operatorToken} ${right}`;
967
+ });
968
+ NodeHandler.register(ts7.SyntaxKind.ParenthesizedExpression, (node) => {
969
+ return `(${NodeHandler.handle(node.expression)})`;
970
+ });
971
+ function handleUnaryExpression(node) {
972
+ const operand = NodeHandler.handle(node.operand);
973
+ const operator = ts7.tokenToString(node.operator);
974
+ if (operator === "++")
975
+ return `${operand} = ${operand} + 1`;
976
+ if (operator === "--")
977
+ return `${operand} = ${operand} - 1`;
978
+ if (operator === "!") {
979
+ if (ts7.isPrefixUnaryExpression(node.parent) && ts7.tokenToString(node.parent.operator) === "!") {
980
+ return `(not ${operand})`;
981
+ }
982
+ return `not ${operand}`;
983
+ }
984
+ if (operator === "-")
985
+ return `-${operand}`;
986
+ if (operator === "+")
987
+ return `${operand}.val()`;
988
+ if (operator === "~")
989
+ return `bitwise("~", ${operand})`;
990
+ throw `Couldn't handle this UnaryExpression: ${node.getText()}`;
991
+ }
992
+ NodeHandler.register(ts7.SyntaxKind.PrefixUnaryExpression, handleUnaryExpression);
993
+ NodeHandler.register(ts7.SyntaxKind.PostfixUnaryExpression, handleUnaryExpression);
994
+ function handleArrayLiteralExpression(node, ctx, itemStrings, out) {
995
+ itemStrings ??= [];
996
+ out ??= [];
997
+ for (const item of node.elements) {
998
+ if (!ts7.isSpreadElement(item)) {
999
+ itemStrings.push(NodeHandler.handle(item));
1000
+ continue;
1001
+ }
1002
+ if (ts7.isArrayLiteralExpression(item.expression)) {
1003
+ handleArrayLiteralExpression(item.expression, ctx, itemStrings, out);
1004
+ continue;
1005
+ }
1006
+ if (itemStrings.length) {
1007
+ out.push(`[${itemStrings.join(",")}]`);
1008
+ itemStrings.length = 0;
1009
+ }
1010
+ out.push(NodeHandler.handle(item.expression));
1011
+ }
1012
+ if ((!out.length || itemStrings.length) && !ts7.isSpreadElement(node.parent)) {
1013
+ out.push(`[${itemStrings.join(",")}]`);
1014
+ itemStrings.length = 0;
1015
+ }
1016
+ return out.join(" + ");
1017
+ }
1018
+ NodeHandler.register(ts7.SyntaxKind.ArrayLiteralExpression, handleArrayLiteralExpression);
1019
+ NodeHandler.register(ts7.SyntaxKind.TemplateExpression, (node) => {
1020
+ const head = NodeHandler.handle(node.head);
1021
+ const strings = [
1022
+ ...head ? [`"${head}"`] : [],
1023
+ ...node.templateSpans.map((span) => NodeHandler.handle(span))
1024
+ ];
1025
+ const output = strings.join(" + ");
1026
+ return output;
1027
+ });
1028
+ NodeHandler.register(ts7.SyntaxKind.TemplateHead, (node) => {
1029
+ return transformString(node.text);
1030
+ });
1031
+ NodeHandler.register(ts7.SyntaxKind.TemplateSpan, (node) => {
1032
+ let output = NodeHandler.handle(node.expression);
1033
+ if (ts7.isBinaryExpression(node.expression))
1034
+ output = `str(${output})`;
1035
+ if (node.literal.text)
1036
+ output += ` + "${transformString(node.literal.text)}"`;
1037
+ return output;
1038
+ });
1039
+ NodeHandler.register(ts7.SyntaxKind.NoSubstitutionTemplateLiteral, (node) => {
1040
+ return `"${transformString(node.text)}"`;
1041
+ });
1042
+ NodeHandler.register(ts7.SyntaxKind.ConditionalExpression, (node) => {
1043
+ if (ts7.isCallExpression(node.whenTrue) || ts7.isCallExpression(node.whenFalse)) {
1044
+ throw "Call expressions are not supported inside conditional expressions yet";
1045
+ }
1046
+ const condition = NodeHandler.handle(node.condition);
1047
+ const whenTrue = NodeHandler.handle(node.whenTrue);
1048
+ const whenFalse = NodeHandler.handle(node.whenFalse);
1049
+ return callUtilFunction("conditional_expr", condition, whenTrue, whenFalse);
1050
+ });
1051
+ NodeHandler.register(ts7.SyntaxKind.ExpressionStatement, (node) => {
1052
+ return NodeHandler.handle(node.expression);
1053
+ });
1054
+ NodeHandler.register(ts7.SyntaxKind.NonNullExpression, (node) => {
1055
+ return NodeHandler.handle(node.expression);
1056
+ });
1057
+ NodeHandler.register(ts7.SyntaxKind.AsExpression, (node) => {
1058
+ return NodeHandler.handle(node.expression);
1059
+ });
1060
+ NodeHandler.register(ts7.SyntaxKind.DeleteExpression, (node) => {
1061
+ if (!ts7.isPropertyAccessExpression(node.expression))
1062
+ throw `Cant handle delete expression for ${ts7.SyntaxKind[node.expression.kind]}`;
1063
+ const pnode = node.expression;
1064
+ const left = NodeHandler.handle(pnode.expression);
1065
+ const leftType = checker.getTypeAtLocation(pnode.expression);
1066
+ const right = replaceIdentifier(NodeHandler.handle(pnode.name), leftType, pnode.name.text);
1067
+ return `${left}.remove(${right})`;
1068
+ });
1069
+
1070
+ // src/visitors/functions.ts
1071
+ import ts8 from "typescript";
1072
+ function transpileFunctionBody(node) {
1073
+ const params = node.parameters.map((param) => NodeHandler.handle(param)).join(", ");
1074
+ const body = node.body ? NodeHandler.handle(node.body) : "";
1075
+ return `function(${params})
1076
+ ${body}
1077
+ end function`;
1078
+ }
1079
+ NodeHandler.register(ts8.SyntaxKind.Block, (node) => {
1080
+ const output = node.statements.map((val) => {
1081
+ let statement = NodeHandler.handle(val);
1082
+ statement = statement.split(`
1083
+ `).map((line) => "\t" + line).join(`
1084
+ `);
1085
+ return statement;
1086
+ }).join(`
1087
+ `);
1088
+ return output;
1089
+ });
1090
+ NodeHandler.register(ts8.SyntaxKind.MethodDeclaration, (node) => {
1091
+ return `${NodeHandler.handle(node.name)} = ${transpileFunctionBody(node)}`;
1092
+ });
1093
+ NodeHandler.register(ts8.SyntaxKind.FunctionDeclaration, (node) => {
1094
+ if (!node.body)
1095
+ return "";
1096
+ if (node.modifiers?.some((m) => m.kind === ts8.SyntaxKind.DeclareKeyword))
1097
+ return "";
1098
+ const name = node.name ? node.name.text : "anon";
1099
+ return `${name} = ${transpileFunctionBody(node)}`;
1100
+ });
1101
+ NodeHandler.register(ts8.SyntaxKind.ArrowFunction, (node) => {
1102
+ const params = node.parameters.map((param) => NodeHandler.handle(param));
1103
+ const body = ts8.isBlock(node.body) ? NodeHandler.handle(node.body) : ` return ${NodeHandler.handle(node.body)}`;
1104
+ if (ts8.isCallOrNewExpression(node.parent) || ts8.isParenthesizedExpression(node.parent)) {
1105
+ return "@" + createAnonFunction(body, params).name;
1106
+ }
1107
+ if (ts8.isPropertyAssignment(node.parent) || ts8.isVariableDeclaration(node.parent) || ts8.isBinaryExpression(node.parent) || ts8.isReturnStatement(node.parent)) {
1108
+ return `function(${params.join(", ")})
1109
+ ${body}
1110
+ end function`;
1111
+ }
1112
+ const kind = ts8.SyntaxKind[node.parent.kind];
1113
+ throw `This kind of arrow function is not yet supported (parent: ${kind} (${node.parent.kind}))`;
1114
+ });
1115
+ NodeHandler.register(ts8.SyntaxKind.FunctionExpression, (node) => {
1116
+ return transpileFunctionBody(node);
1117
+ });
1118
+
1119
+ // src/visitors/identifiers.ts
1120
+ import ts9 from "typescript";
1121
+ NodeHandler.register(ts9.SyntaxKind.Identifier, (node, ctx) => {
1122
+ const type = checker.getTypeAtLocation(node);
1123
+ let name = node.text;
1124
+ if (name === "undefined")
1125
+ return "null";
1126
+ if (type.isUnion()) {
1127
+ const original = node.text;
1128
+ for (const t of type.types) {
1129
+ name = replaceIdentifier(node.text, t);
1130
+ if (name != original)
1131
+ break;
1132
+ }
1133
+ } else {
1134
+ name = replaceIdentifier(node.text, type);
1135
+ }
1136
+ if (ctx.namedImports[ctx.currentFilePath]?.[name]) {
1137
+ name = ctx.namedImports[ctx.currentFilePath][name];
1138
+ }
1139
+ if (ts9.isCallOrNewExpression(node.parent) && node != node.parent.expression) {
1140
+ if (nodeIsFunctionReference(node, type))
1141
+ name = asRef(name);
1142
+ }
1143
+ return name;
1144
+ });
1145
+ NodeHandler.register(ts9.SyntaxKind.Parameter, (node) => {
1146
+ const name = NodeHandler.handle(node.name);
1147
+ if (!node.initializer)
1148
+ return name;
1149
+ return `${name} = ${NodeHandler.handle(node.initializer)}`;
1150
+ });
1151
+ NodeHandler.register(ts9.SyntaxKind.NumericLiteral, (node) => node.text);
1152
+ NodeHandler.register(ts9.SyntaxKind.StringLiteral, (node) => `"${transformString(node.text)}"`);
1153
+ NodeHandler.register(ts9.SyntaxKind.ThisKeyword, () => "self");
1154
+ NodeHandler.register(ts9.SyntaxKind.NullKeyword, () => "null");
1155
+ NodeHandler.register(ts9.SyntaxKind.UndefinedKeyword, () => "null");
1156
+ NodeHandler.register(ts9.SyntaxKind.FalseKeyword, () => "0");
1157
+ NodeHandler.register(ts9.SyntaxKind.TrueKeyword, () => "1");
1158
+ NodeHandler.register(ts9.SyntaxKind.SuperKeyword, (node) => {
1159
+ if (ts9.isPropertyAccessExpression(node.parent))
1160
+ return "super";
1161
+ return "super.constructor";
1162
+ });
1163
+ NodeHandler.register(ts9.SyntaxKind.RegularExpressionLiteral, (node) => {
1164
+ const start = node.text.indexOf("/") + 1;
1165
+ const end = node.text.lastIndexOf("/");
1166
+ const flags = node.text.slice(end + 1);
1167
+ if (flags)
1168
+ throw "Regex flags are not supported yet";
1169
+ return `"${node.text.slice(start, end)}"`;
1170
+ });
1171
+
1172
+ // src/visitors/imports.ts
1173
+ import path4 from "node:path";
1174
+ import ts10 from "typescript";
1175
+ function importFile(filePath, ctx, returnResult) {
1176
+ let srcPath = path4.resolve(ctx.currentFolder, filePath);
1177
+ if (!path4.extname(srcPath))
1178
+ srcPath += ".ts";
1179
+ const source = program.getSourceFile(srcPath);
1180
+ if (!source) {
1181
+ console.error(`Failed to find source ${srcPath}`);
1182
+ return "";
1183
+ }
1184
+ return transpileSourceFile(source, ctx, returnResult);
1185
+ }
1186
+ NodeHandler.register(ts10.SyntaxKind.ImportDeclaration, (node, ctx) => {
1187
+ if (!node.importClause) {
1188
+ const moduleName = node.moduleSpecifier.text;
1189
+ const transpiledFile = importFile(moduleName, ctx, true);
1190
+ if (!transpiledFile)
1191
+ return "";
1192
+ const rndName = "func_" + (Date.now() * Math.random()).toString().slice(0, 6);
1193
+ return [
1194
+ `${rndName} = function`,
1195
+ transpiledFile.split(`
1196
+ `).map((line) => "\t" + line).join(`
1197
+ `),
1198
+ "end function",
1199
+ `${rndName}()`
1200
+ ].join(`
1201
+ `);
1202
+ }
1203
+ if (node.importClause.phaseModifier)
1204
+ return "";
1205
+ if (node.importClause.name)
1206
+ throw `Can't import default exports yet (imported as ${node.importClause.name.text})`;
1207
+ const bindings = node.importClause.namedBindings;
1208
+ if (bindings) {
1209
+ if (ts10.isNamespaceImport(bindings)) {
1210
+ ctx.namespaceImports[ctx.currentFilePath]?.add(bindings.name.text);
1211
+ } else {
1212
+ bindings.elements.forEach((el) => {
1213
+ if (!el.propertyName || el.isTypeOnly)
1214
+ return;
1215
+ ctx.namedImports[ctx.currentFilePath][el.name.text] = el.propertyName.text;
1216
+ });
1217
+ }
1218
+ }
1219
+ const moduleSpecifier = node.moduleSpecifier.text;
1220
+ return importFile(moduleSpecifier, ctx);
1221
+ });
1222
+
1223
+ // src/visitors/objects.ts
1224
+ import ts11 from "typescript";
1225
+ var assignmentOperators = new Set([
1226
+ "=",
1227
+ "??=",
1228
+ "||=",
1229
+ "-=",
1230
+ "+="
1231
+ ]);
1232
+ function valueIsBeingAssignedToNode(node) {
1233
+ const assignAncestor = ts11.findAncestor(node, (ancestor) => {
1234
+ if (ancestor.parent && ts11.isBinaryExpression(ancestor.parent) && ancestor === ancestor.parent.left) {
1235
+ const token = ts11.tokenToString(ancestor.parent.operatorToken.kind) || ancestor.parent.operatorToken.getText();
1236
+ return assignmentOperators.has(token);
1237
+ }
1238
+ return false;
1239
+ });
1240
+ return !!assignAncestor;
1241
+ }
1242
+ NodeHandler.register(ts11.SyntaxKind.PropertyAccessExpression, (node, ctx) => {
1243
+ const left = NodeHandler.handle(node.expression);
1244
+ let right = NodeHandler.handle(node.name);
1245
+ right = replaceIdentifier(right, checker.getTypeAtLocation(node.expression), right);
1246
+ const nodeSymbol = checker.getSymbolAtLocation(node);
1247
+ if (ctx.namespaceImports[ctx.currentFilePath]?.has(left))
1248
+ return right;
1249
+ let getSafely = !!node.questionDotToken && !ts11.isNonNullExpression(node.parent);
1250
+ const rightType = checker.getTypeAtLocation(node.name);
1251
+ if (rightType.isUnion()) {
1252
+ const hasUndefined = rightType.types.some((t) => t.flags === ts11.TypeFlags.Undefined);
1253
+ if (hasUndefined)
1254
+ getSafely = true;
1255
+ }
1256
+ if (!valueIsBeingAssignedToNode(node) && getSafely)
1257
+ return callUtilFunction("get_property", left, `"${right}"`);
1258
+ let output = `${left}.${right}`;
1259
+ output = replacePropertyAccess(output, nodeSymbol);
1260
+ if (nodeIsFunctionReference(node))
1261
+ output = asRef(output);
1262
+ return output;
1263
+ });
1264
+ NodeHandler.register(ts11.SyntaxKind.ElementAccessExpression, (node, ctx) => {
1265
+ const left = NodeHandler.handle(node.expression);
1266
+ let right;
1267
+ if (ts11.isStringLiteral(node.argumentExpression)) {
1268
+ const leftType = checker.getTypeAtLocation(node.expression);
1269
+ right = `"${replaceIdentifier(node.argumentExpression.text, leftType, node.argumentExpression.text)}"`;
1270
+ } else {
1271
+ right = NodeHandler.handle(node.argumentExpression);
1272
+ }
1273
+ const asd = ts11.findAncestor(node, (ancestor) => {
1274
+ if (ancestor.parent && ts11.isBinaryExpression(ancestor.parent) && ancestor === ancestor.parent.left) {
1275
+ const token = ts11.tokenToString(ancestor.parent.operatorToken.kind) || ancestor.parent.operatorToken.getText();
1276
+ return assignmentOperators.has(token);
1277
+ }
1278
+ return false;
1279
+ });
1280
+ if (!asd && !ts11.isNumericLiteral(node.argumentExpression)) {
1281
+ return callUtilFunction("get_property", left, `${right}`);
1282
+ }
1283
+ return `${left}[${right}]`;
1284
+ });
1285
+ function handleObjectLiteralExpression(node, ctx, currObj, outObjects, funcs) {
1286
+ currObj ??= [];
1287
+ outObjects ??= [];
1288
+ funcs ??= [];
1289
+ const objectName = ts11.isVariableDeclaration(node.parent) ? NodeHandler.handle(node.parent.name) : ts11.isBinaryExpression(node.parent) && node === node.parent.right ? NodeHandler.handle(node.parent.left) : "";
1290
+ function pushObj() {
1291
+ if (!currObj?.length)
1292
+ return "";
1293
+ const res = currObj.filter((s) => s != "").join(",");
1294
+ if (res) {
1295
+ outObjects?.push(`{ ${res} }`);
1296
+ }
1297
+ currObj.length = 0;
1298
+ return res;
1299
+ }
1300
+ for (const item of node.properties) {
1301
+ if (ts11.isFunctionLike(item)) {
1302
+ if (!objectName)
1303
+ throw "You can't have method declarations inside an object that is not being assigned to a variable";
1304
+ funcs.push(`${objectName}.${NodeHandler.handle(item)}`);
1305
+ continue;
1306
+ }
1307
+ if (ts11.isPropertyAssignment(item) && ts11.isFunctionLike(item.initializer)) {
1308
+ if (!objectName)
1309
+ throw "You can't have method declarations inside an object that is not being assigned to a variable";
1310
+ funcs.push(`${objectName}.${NodeHandler.handle(item.name)} = ${NodeHandler.handle(item.initializer)}`);
1311
+ continue;
1312
+ }
1313
+ if (ts11.isSpreadAssignment(item)) {
1314
+ if (ts11.isObjectLiteralExpression(item.expression)) {
1315
+ handleObjectLiteralExpression(item.expression, ctx, currObj, outObjects);
1316
+ continue;
1317
+ }
1318
+ if (ts11.isIdentifier(item.expression)) {
1319
+ pushObj();
1320
+ outObjects.push(NodeHandler.handle(item.expression));
1321
+ continue;
1322
+ }
1323
+ if (ts11.isArrayLiteralExpression(item.expression)) {
1324
+ pushObj();
1325
+ outObjects.push(NodeHandler.handle(item.expression));
1326
+ continue;
1327
+ }
1328
+ }
1329
+ currObj.push(NodeHandler.handle(item));
1330
+ }
1331
+ pushObj();
1332
+ if (!outObjects.length)
1333
+ outObjects.push("{}");
1334
+ let output = outObjects[0];
1335
+ if (outObjects.length > 1) {
1336
+ output = callUtilFunction("assign_objects", output, `[${outObjects.slice(1).join(",")}]`);
1337
+ }
1338
+ if (funcs.length) {
1339
+ output += `
1340
+ ` + funcs.join(`
1341
+ `);
1342
+ }
1343
+ return output;
1344
+ }
1345
+ NodeHandler.register(ts11.SyntaxKind.ObjectLiteralExpression, handleObjectLiteralExpression);
1346
+
1347
+ // src/visitors/statements.ts
1348
+ import ts12 from "typescript";
1349
+ NodeHandler.register(ts12.SyntaxKind.ForStatement, (node) => {
1350
+ if (!node.condition || !node.initializer || !node.incrementor) {
1351
+ throw "Can't transpile this type of for loop.";
1352
+ }
1353
+ const initializer = NodeHandler.handle(node.initializer);
1354
+ const condition = NodeHandler.handle(node.condition);
1355
+ const incrementor = NodeHandler.handle(node.incrementor);
1356
+ const statement = NodeHandler.handle(node.statement);
1357
+ function hasContinue(n) {
1358
+ if (n.getChildren().some((child) => {
1359
+ if (ts12.isContinueStatement(child))
1360
+ return true;
1361
+ return hasContinue(child);
1362
+ })) {
1363
+ return true;
1364
+ }
1365
+ return false;
1366
+ }
1367
+ if (!hasContinue(node)) {
1368
+ return [
1369
+ `${initializer}`,
1370
+ `while ${condition}`,
1371
+ ` ${statement.trimStart()}`,
1372
+ ` ${incrementor}`,
1373
+ `end while`
1374
+ ].join(`
1375
+ `);
1376
+ }
1377
+ const incrementedStateVarName = "state_" + (Date.now() * Math.random()).toFixed(0).slice(0, 6);
1378
+ const output = [
1379
+ `${incrementedStateVarName} = 1`,
1380
+ `${initializer}`,
1381
+ `while ${condition}`,
1382
+ ` if not ${incrementedStateVarName} then`,
1383
+ ` ${incrementor}`,
1384
+ ` if not ${condition} then break`,
1385
+ ` end if`,
1386
+ ` ${incrementedStateVarName} = 0`,
1387
+ ` ${statement.trimStart()}`,
1388
+ ` ${incrementor}`,
1389
+ ` ${incrementedStateVarName} = 1`,
1390
+ `end while`
1391
+ ].join(`
1392
+ `);
1393
+ return output;
1394
+ });
1395
+ NodeHandler.register(ts12.SyntaxKind.ForOfStatement, (node) => {
1396
+ if (!ts12.isVariableDeclarationList(node.initializer)) {
1397
+ throw `Can't handle this 'for of' statement as '${NodeHandler.handle(node.initializer)}' is not initialized there`;
1398
+ }
1399
+ if (node.initializer.declarations.length > 1) {
1400
+ throw "Can't have more than 1 variable declarations in a 'for of' statement";
1401
+ }
1402
+ const varName = NodeHandler.handle(node.initializer.declarations[0].name);
1403
+ const objToLoop = NodeHandler.handle(node.expression);
1404
+ return `for ${varName} in ${objToLoop}
1405
+ ${NodeHandler.handle(node.statement)}
1406
+ end for`;
1407
+ });
1408
+ NodeHandler.register(ts12.SyntaxKind.ForInStatement, (node) => {
1409
+ if (!ts12.isVariableDeclarationList(node.initializer)) {
1410
+ throw `Can't handle this 'for in' statement as '${NodeHandler.handle(node.initializer)}' is not initialized there`;
1411
+ }
1412
+ if (node.initializer.declarations.length > 1) {
1413
+ throw "Can't have more than 1 variable declarations in a 'for in' statement";
1414
+ }
1415
+ const varName = NodeHandler.handle(node.initializer.declarations[0].name);
1416
+ const objToLoop = NodeHandler.handle(node.expression);
1417
+ return `for ${varName} in ${objToLoop}.indexes
1418
+ ${NodeHandler.handle(node.statement)}
1419
+ end for`;
1420
+ });
1421
+ NodeHandler.register(ts12.SyntaxKind.IfStatement, (node) => {
1422
+ const condition = NodeHandler.handle(node.expression);
1423
+ const thenStatement = NodeHandler.handle(node.thenStatement);
1424
+ if (!ts12.isBlock(node.thenStatement) && !ts12.isIfStatement(node.thenStatement) && !ts12.isIfStatement(node.parent)) {
1425
+ if (!node.elseStatement)
1426
+ return `if ${condition} then ${thenStatement}`;
1427
+ else if (!ts12.isBlock(node.elseStatement) && !ts12.isIfStatement(node.elseStatement))
1428
+ return `if ${condition} then ${thenStatement} else ${NodeHandler.handle(node.elseStatement)}`;
1429
+ }
1430
+ let output = `if ${condition} then
1431
+ ${thenStatement.trimStart()}`;
1432
+ if (node.elseStatement) {
1433
+ if (ts12.isIfStatement(node.elseStatement)) {
1434
+ output += `
1435
+ else ${NodeHandler.handle(node.elseStatement)}`;
1436
+ return output;
1437
+ } else {
1438
+ output += `
1439
+ else
1440
+ ${NodeHandler.handle(node.elseStatement).trimStart()}`;
1441
+ }
1442
+ }
1443
+ output += `
1444
+ end if`;
1445
+ return output;
1446
+ });
1447
+ NodeHandler.register(ts12.SyntaxKind.WhileStatement, (node, ctx) => {
1448
+ const expression = NodeHandler.handle(node.expression);
1449
+ return [
1450
+ `while ${expression}`,
1451
+ ` ${NodeHandler.handle(node.statement).trimStart()}`,
1452
+ `end while`
1453
+ ].join(`
1454
+ `);
1455
+ });
1456
+ NodeHandler.register(ts12.SyntaxKind.DoStatement, (node, ctx) => {
1457
+ const expression = NodeHandler.handle(node.expression);
1458
+ return [
1459
+ `did_once = 0`,
1460
+ `while not did_once or ${expression}`,
1461
+ ` did_once = 1`,
1462
+ ` ${NodeHandler.handle(node.statement).trimStart()}`,
1463
+ `end while`
1464
+ ].join(`
1465
+ `);
1466
+ });
1467
+ NodeHandler.register(ts12.SyntaxKind.ContinueStatement, (node) => {
1468
+ return "continue";
1469
+ });
1470
+ NodeHandler.register(ts12.SyntaxKind.BreakStatement, (node) => {
1471
+ return "break";
1472
+ });
1473
+ NodeHandler.register(ts12.SyntaxKind.ReturnStatement, (node) => {
1474
+ if (!node.expression) {
1475
+ if (ts12.findAncestor(node, (n) => ts12.isConstructorDeclaration(n)) && !ts12.findAncestor(node, (n) => ts12.isFunctionLike(n))) {
1476
+ return "return self";
1477
+ }
1478
+ return "return";
1479
+ }
1480
+ return `return ${NodeHandler.handle(node.expression)}`;
1481
+ });
1482
+
1483
+ // src/visitors/variables.ts
1484
+ import ts13 from "typescript";
1485
+ function handleVariableDeclaration(node, ctx) {
1486
+ const left = NodeHandler.handle(node.name);
1487
+ const initializerType = node.initializer ? checker.getTypeAtLocation(node.initializer) : undefined;
1488
+ if (ts13.isPropertyDeclaration(node) && initializerType?.flags === ts13.TypeFlags.Object) {
1489
+ console.warn(`You shouldn't initialize '${left}' with an Array or an Object because in GreyScript, every instantiation refers to the same '${left}' variable.
1490
+ Initialize them in the constructor instead`);
1491
+ }
1492
+ let right = node.initializer ? NodeHandler.handle(node.initializer) || "null" : "null";
1493
+ if (right != "null" && nodeIsFunctionReference(node.initializer, initializerType)) {
1494
+ right = asRef(right);
1495
+ }
1496
+ return `${left} = ${right}`;
1497
+ }
1498
+ NodeHandler.register(ts13.SyntaxKind.VariableDeclarationList, (node, ctx) => {
1499
+ return node.declarations.map((decl) => handleVariableDeclaration(decl, ctx)).join(`
1500
+ `);
1501
+ });
1502
+ NodeHandler.register(ts13.SyntaxKind.VariableStatement, (node, ctx) => {
1503
+ if (node.modifiers?.some((modifier) => modifier.kind === ts13.SyntaxKind.DeclareKeyword))
1504
+ return "";
1505
+ return NodeHandler.handle(node.declarationList);
1506
+ });
1507
+ NodeHandler.register(ts13.SyntaxKind.VariableDeclaration, handleVariableDeclaration);
1508
+ NodeHandler.register(ts13.SyntaxKind.PropertyDeclaration, handleVariableDeclaration);
1509
+ NodeHandler.register(ts13.SyntaxKind.EnumDeclaration, (node) => {
1510
+ const members = node.members.map((member, index) => {
1511
+ const name = NodeHandler.handle(member.name);
1512
+ if (member.initializer) {
1513
+ return `${name}: ${NodeHandler.handle(member.initializer)}`;
1514
+ }
1515
+ const type = checker.getTypeAtLocation(member);
1516
+ if ("value" in type) {
1517
+ return `${name}: ${type.value}`;
1518
+ }
1519
+ return `${name}: ${index}`;
1520
+ });
1521
+ return `${node.name.text} = { ${members.join(", ")} }`;
1522
+ });
1523
+
1524
+ // src/index.ts
1525
+ var noMoreFlags = false;
1526
+ var command = "";
1527
+ var flags = [];
1528
+ var args = [];
1529
+ for (let i = 2;i < process.argv.length; i++) {
1530
+ const arg = process.argv[i];
1531
+ if (arg === "--") {
1532
+ noMoreFlags = true;
1533
+ continue;
1534
+ }
1535
+ if (!command) {
1536
+ command = arg;
1537
+ continue;
1538
+ }
1539
+ if (arg.startsWith("-") && !noMoreFlags)
1540
+ flags.push(arg);
1541
+ else
1542
+ args.push(arg);
1543
+ }
1544
+ var root = findProjectRoot(process.cwd());
1545
+ if (!command) {
1546
+ console.error("No command specified.");
1547
+ process.exit(2);
1548
+ }
1549
+ if (command === "transpile") {
1550
+ if (!args.length) {
1551
+ console.error("No entry file specified.");
1552
+ process.exit(2);
1553
+ }
1554
+ const entryFile = args[0];
1555
+ const output = transpileProgram(entryFile);
1556
+ if (flags.includes("--print") || flags.includes("-p")) {
1557
+ console.log(output);
1558
+ process.exit(0);
1559
+ }
1560
+ const outDirPath = `${root}/out`;
1561
+ if (!fs3.existsSync(outDirPath))
1562
+ fs3.mkdirSync(outDirPath);
1563
+ const outFileName = args.length > 1 ? args[1] : `${path5.basename(entryFile).replace(".ts", ".src")}`;
1564
+ const outFilePath = path5.join(outDirPath, outFileName);
1565
+ fs3.writeFileSync(outFilePath, output);
1566
+ } else {
1567
+ console.log(`Invalid command: ${command}`);
1568
+ process.exit(127);
1569
+ }
1570
+ export {
1571
+ transpileProgram
1572
+ };