@xnoxs/flux-lang 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/README.md +1089 -0
  3. package/bin/flux.js +1397 -0
  4. package/dist/flux.cjs.js +6664 -0
  5. package/dist/flux.esm.js +6674 -0
  6. package/dist/flux.min.js +263 -0
  7. package/index.d.ts +202 -0
  8. package/index.js +26 -0
  9. package/package.json +77 -0
  10. package/scripts/build.js +76 -0
  11. package/src/bundler.js +216 -0
  12. package/src/checker.js +322 -0
  13. package/src/codegen.js +785 -0
  14. package/src/css-preprocessor.js +399 -0
  15. package/src/formatter.js +140 -0
  16. package/src/jsx.js +480 -0
  17. package/src/lexer.js +518 -0
  18. package/src/linter.js +758 -0
  19. package/src/mangler.js +280 -0
  20. package/src/parser.js +1671 -0
  21. package/src/self/bundler.flux +167 -0
  22. package/src/self/bundler.js +187 -0
  23. package/src/self/checker.flux +249 -0
  24. package/src/self/checker.js +338 -0
  25. package/src/self/codegen.flux +555 -0
  26. package/src/self/codegen.js +784 -0
  27. package/src/self/css-preprocessor.flux +373 -0
  28. package/src/self/css-preprocessor.js +387 -0
  29. package/src/self/formatter.flux +93 -0
  30. package/src/self/formatter.js +114 -0
  31. package/src/self/jsx.flux +430 -0
  32. package/src/self/jsx.js +396 -0
  33. package/src/self/lexer.flux +529 -0
  34. package/src/self/lexer.js +709 -0
  35. package/src/self/lexer.stage2.js +700 -0
  36. package/src/self/linter.flux +515 -0
  37. package/src/self/linter.js +804 -0
  38. package/src/self/mangler.flux +253 -0
  39. package/src/self/mangler.js +348 -0
  40. package/src/self/parser.flux +1146 -0
  41. package/src/self/parser.js +1571 -0
  42. package/src/self/sourcemap.flux +66 -0
  43. package/src/self/sourcemap.js +72 -0
  44. package/src/self/stdlib.flux +356 -0
  45. package/src/self/stdlib.js +396 -0
  46. package/src/self/test-runner.flux +201 -0
  47. package/src/self/test-runner.js +132 -0
  48. package/src/self/transpiler.flux +123 -0
  49. package/src/self/transpiler.js +83 -0
  50. package/src/self/type-checker.flux +821 -0
  51. package/src/self/type-checker.js +1106 -0
  52. package/src/sourcemap.js +82 -0
  53. package/src/stdlib.js +436 -0
  54. package/src/test-runner.js +239 -0
  55. package/src/transpiler.js +172 -0
  56. package/src/type-checker.js +1206 -0
@@ -0,0 +1,804 @@
1
+ // ── Flux stdlib ──
2
+
3
+ function sort(arr, fn) { return arr.slice().sort(fn); }
4
+ // ── end stdlib ──
5
+
6
+ // Generated by Flux Transpiler v3.1.0
7
+ "use strict";
8
+
9
+ const { lexerize } = require("./lexer");
10
+ const { makeParser } = require("./parser");
11
+ const BUILTIN_NAMES = new Set(["self", "this", "arguments", "exports", "module", "require", "__dirname", "__filename", "process", "console", "Math", "JSON", "Object", "Array", "String", "Number", "Boolean", "Promise", "Error", "Symbol", "Map", "Set", "WeakMap", "WeakSet", "Proxy", "Reflect", "undefined", "null", "true", "false", "NaN", "Infinity", "parseInt", "parseFloat", "isNaN", "isFinite", "setTimeout", "clearTimeout", "setInterval", "clearInterval", "fetch", "globalThis", "print", "truncate", "range", "sum", "first", "last", "zip", "flatten", "groupBy", "unique", "sortBy", "chunk"]);
12
+ function isIgnoredName(name) {
13
+ if (BUILTIN_NAMES.has(name)) {
14
+ return true;
15
+ }
16
+ if (name.startsWith("_")) {
17
+ return true;
18
+ }
19
+ return false;
20
+ }
21
+ class LintIssue {
22
+ constructor(rule, severity, message, hint, line, col) {
23
+ this.rule = rule;
24
+ this.severity = severity;
25
+ this.message = message;
26
+ this.hint = hint;
27
+ this.line = line;
28
+ this.col = col;
29
+ }
30
+
31
+ }
32
+
33
+ module.exports.LintIssue = LintIssue;
34
+ class LintScope {
35
+ constructor(parent, kind, vars) {
36
+ this.parent = parent;
37
+ this.kind = kind;
38
+ this.vars = vars;
39
+ }
40
+
41
+ define(name, kind, loc) {
42
+ const shadowOf = (this.lookupOwn(name) ?? this.lookupParent(name));
43
+ const entry = { name, kind, loc, used: false, shadowOf };
44
+ this.vars.set(name, entry);
45
+ return entry;
46
+ }
47
+
48
+ lookupOwn(name) {
49
+ return (this.vars.get(name) ?? null);
50
+ }
51
+
52
+ lookupParent(name) {
53
+ let s = this.parent;
54
+ while (s) {
55
+ if (s.vars.has(name)) {
56
+ return s.vars.get(name);
57
+ }
58
+ s = s.parent;
59
+ }
60
+ return null;
61
+ }
62
+
63
+ lookup(name) {
64
+ return (this.lookupOwn(name) ?? this.lookupParent(name));
65
+ }
66
+
67
+ markUsed(name) {
68
+ const entry = this.lookup(name);
69
+ if (entry) {
70
+ entry.used = true;
71
+ }
72
+ }
73
+
74
+ ownEntries() {
75
+ return [...this.vars.values()];
76
+ }
77
+
78
+ }
79
+
80
+ module.exports.LintScope = LintScope;
81
+ function makeLintScope(parent, kind) {
82
+ return new LintScope(parent, kind, new Map());
83
+ }
84
+ function makeLintIssue(rule, severity, message, hint, loc) {
85
+ const li = new LintIssue(rule, severity, message, null, null, null);
86
+ li.hint = (hint ?? null);
87
+ li.line = (loc ? loc.line : null);
88
+ li.col = (loc ? loc.col : null);
89
+ return li;
90
+ }
91
+ class Linter {
92
+ constructor(issues) {
93
+ this.issues = issues;
94
+ }
95
+
96
+ issue(rule, severity, message, hint, loc) {
97
+ this.issues.push(makeLintIssue(rule, severity, message, hint, loc));
98
+ }
99
+
100
+ lint(ast) {
101
+ this.issues = [];
102
+ const scope = makeLintScope(null, "module");
103
+ this.walkStmts(ast.body, scope, { inFn: false });
104
+ return this.issues;
105
+ }
106
+
107
+ isTerminator(node) {
108
+ if (!node) {
109
+ return false;
110
+ }
111
+ if (((node.type == "ReturnStmt") || (node.type == "ThrowStmt"))) {
112
+ return true;
113
+ }
114
+ if (((node.type == "BreakStmt") || (node.type == "ContinueStmt"))) {
115
+ return true;
116
+ }
117
+ return false;
118
+ }
119
+
120
+ terminatorName(node) {
121
+ if ((node.type == "ReturnStmt")) {
122
+ return "return";
123
+ }
124
+ if ((node.type == "ThrowStmt")) {
125
+ return "throw";
126
+ }
127
+ if ((node.type == "BreakStmt")) {
128
+ return "break";
129
+ }
130
+ if ((node.type == "ContinueStmt")) {
131
+ return "continue";
132
+ }
133
+ return "terminator";
134
+ }
135
+
136
+ checkUnused(scope) {
137
+ for (const entry of scope.ownEntries()) {
138
+ if (entry.used) {
139
+ continue;
140
+ }
141
+ if (isIgnoredName(entry.name)) {
142
+ continue;
143
+ }
144
+ if (entry._exported) {
145
+ continue;
146
+ }
147
+ this.issue("unused-var", "warn", (("'" + entry.name) + "' is declared but never used"), (("Prefix with '_' (e.g. '_" + entry.name) + "') to silence this warning, or remove the declaration"), entry.loc);
148
+ }
149
+ }
150
+
151
+ walkStmts(stmts, scope, ctx) {
152
+ if ((!stmts || (stmts.length == 0))) {
153
+ return;
154
+ }
155
+ let i = 0;
156
+ while ((i < stmts.length)) {
157
+ const node = stmts[i];
158
+ if (((i > 0) && this.isTerminator(stmts[(i - 1)]))) {
159
+ if ((node && node.loc)) {
160
+ this.issue("unreachable", "error", (("Unreachable code after '" + this.terminatorName(stmts[(i - 1)])) + "'"), "Remove or move the unreachable statement", node.loc);
161
+ break;
162
+ }
163
+ }
164
+ this.walkStmt(node, scope, ctx);
165
+ i = (i + 1);
166
+ }
167
+ this.checkUnused(scope);
168
+ }
169
+
170
+ walkStmt(node, scope, ctx) {
171
+ if (!node) {
172
+ return;
173
+ }
174
+ if ((node.type == "VarDecl")) {
175
+ if (node.init) {
176
+ this.walkExpr(node.init, scope, ctx);
177
+ }
178
+ scope.define(node.name, node.kind, node.loc);
179
+ return;
180
+ }
181
+ if ((node.type == "DestructureDecl")) {
182
+ if (node.init) {
183
+ this.walkExpr(node.init, scope, ctx);
184
+ }
185
+ if ((node.patternType == "object")) {
186
+ for (const p of node.pattern) {
187
+ scope.define((p.alias ?? p.name), node.kind, node.loc);
188
+ }
189
+ }
190
+ else {
191
+ for (const p of node.pattern) {
192
+ if (p) {
193
+ scope.define(p.name, node.kind, node.loc);
194
+ }
195
+ }
196
+ }
197
+ return;
198
+ }
199
+ if ((node.type == "FnDecl")) {
200
+ if (node.name) {
201
+ const entry = scope.define(node.name, "val", node.loc);
202
+ entry.used = true;
203
+ }
204
+ const inner = makeLintScope(scope, "fn");
205
+ for (const p of node.params) {
206
+ const pe = inner.define(p.name, "val", node.loc);
207
+ pe.used = true;
208
+ }
209
+ if (node.inline) {
210
+ this.walkExpr(node.body, inner, { ...ctx, inFn: true });
211
+ }
212
+ else {
213
+ this.walkStmts(node.body, inner, { ...ctx, inFn: true });
214
+ }
215
+ return;
216
+ }
217
+ if ((node.type == "ClassDecl")) {
218
+ const ce = scope.define(node.name, "val", node.loc);
219
+ ce.used = true;
220
+ const cls = makeLintScope(scope, "class");
221
+ for (const f of (node.fields ?? [])) {
222
+ const fe = cls.define(f.name, "var", node.loc);
223
+ fe.used = true;
224
+ }
225
+ for (const m of (node.methods ?? [])) {
226
+ this.walkStmt(m, cls, ctx);
227
+ }
228
+ return;
229
+ }
230
+ if ((node.type == "TypeDecl")) {
231
+ for (const v of node.variants) {
232
+ const ve = scope.define(v.name, "val", node.loc);
233
+ ve.used = true;
234
+ }
235
+ return;
236
+ }
237
+ if (((node.type == "InterfaceDecl") || (node.type == "EnumDecl"))) {
238
+ const ie = scope.define(node.name, "val", node.loc);
239
+ ie.used = true;
240
+ return;
241
+ }
242
+ if ((node.type == "IfStmt")) {
243
+ this.walkExpr(node.cond, scope, ctx);
244
+ const thenScope = makeLintScope(scope, "block");
245
+ this.walkStmts(node.then, thenScope, ctx);
246
+ for (const ei of (node.elseifs ?? [])) {
247
+ this.walkExpr(ei.cond, scope, ctx);
248
+ const eis = makeLintScope(scope, "block");
249
+ this.walkStmts(ei.body, eis, ctx);
250
+ }
251
+ if (node.else_) {
252
+ const elseScope = makeLintScope(scope, "block");
253
+ this.walkStmts(node.else_, elseScope, ctx);
254
+ }
255
+ return;
256
+ }
257
+ if ((node.type == "ForInStmt")) {
258
+ this.walkExpr(node.iter, scope, ctx);
259
+ const forScope = makeLintScope(scope, "block");
260
+ const loopVar = forScope.define(node.var, "val", node.loc);
261
+ loopVar.used = true;
262
+ this.walkStmts(node.body, forScope, { ...ctx, inLoop: true });
263
+ return;
264
+ }
265
+ if ((node.type == "WhileStmt")) {
266
+ this.walkExpr(node.cond, scope, ctx);
267
+ const ws = makeLintScope(scope, "block");
268
+ this.walkStmts(node.body, ws, { ...ctx, inLoop: true });
269
+ return;
270
+ }
271
+ if ((node.type == "DoWhileStmt")) {
272
+ const ds = makeLintScope(scope, "block");
273
+ this.walkStmts(node.body, ds, { ...ctx, inLoop: true });
274
+ this.walkExpr(node.cond, scope, ctx);
275
+ return;
276
+ }
277
+ if ((node.type == "MatchStmt")) {
278
+ this.walkExpr(node.subject, scope, ctx);
279
+ for (const arm of node.arms) {
280
+ const armScope = makeLintScope(scope, "block");
281
+ if ((arm.pattern && (arm.pattern.type == "VariantPat"))) {
282
+ for (const b of arm.pattern.bindings) {
283
+ const be = armScope.define(b, "val", node.loc);
284
+ be.used = true;
285
+ }
286
+ }
287
+ if (arm.guard) {
288
+ this.walkExpr(arm.guard, armScope, ctx);
289
+ }
290
+ if (arm.inline) {
291
+ let expr = ((arm.body && arm.body[0]) ? arm.body[0] : null);
292
+ if (((arm.body && arm.body[0]) && arm.body[0].expr)) {
293
+ expr = arm.body[0].expr;
294
+ }
295
+ if (expr) {
296
+ this.walkExpr(expr, armScope, ctx);
297
+ }
298
+ }
299
+ else {
300
+ this.walkStmts((arm.body ?? []), armScope, ctx);
301
+ }
302
+ }
303
+ return;
304
+ }
305
+ if ((node.type == "ReturnStmt")) {
306
+ if (node.value) {
307
+ this.walkExpr(node.value, scope, ctx);
308
+ }
309
+ return;
310
+ }
311
+ if ((node.type == "ThrowStmt")) {
312
+ this.walkExpr(node.value, scope, ctx);
313
+ return;
314
+ }
315
+ if ((node.type == "TryCatchStmt")) {
316
+ const tryS = makeLintScope(scope, "block");
317
+ this.walkStmts(node.tryBody, tryS, ctx);
318
+ if (node.catchBody) {
319
+ const catchS = makeLintScope(scope, "block");
320
+ if (node.catchParam) {
321
+ const ce2 = catchS.define(node.catchParam, "val", node.loc);
322
+ ce2.used = true;
323
+ }
324
+ this.walkStmts(node.catchBody, catchS, ctx);
325
+ }
326
+ if (node.finallyBody) {
327
+ const finS = makeLintScope(scope, "block");
328
+ this.walkStmts(node.finallyBody, finS, ctx);
329
+ }
330
+ return;
331
+ }
332
+ if ((node.type == "ImportDecl")) {
333
+ if (node.defaultName) {
334
+ const ie2 = scope.define(node.defaultName, "val", node.loc);
335
+ ie2.used = true;
336
+ }
337
+ if (node.namespaceName) {
338
+ const ne = scope.define(node.namespaceName, "val", node.loc);
339
+ ne.used = true;
340
+ }
341
+ for (const n of (node.names ?? [])) {
342
+ const nm = ((typeof n == "string") ? n : n.alias);
343
+ const ie3 = scope.define(nm, "val", node.loc);
344
+ ie3.used = true;
345
+ }
346
+ return;
347
+ }
348
+ if ((node.type == "ExportDecl")) {
349
+ let inner2 = node.decl;
350
+ if (node.isDefault) {
351
+ inner2 = { type: "ExprStmt", expr: node.decl };
352
+ }
353
+ this.walkStmt(inner2, scope, ctx);
354
+ if ((node.decl && node.decl.name)) {
355
+ const ee = scope.lookup(node.decl.name);
356
+ if (ee) {
357
+ ee.used = true;
358
+ }
359
+ ee._exported = true;
360
+ }
361
+ return;
362
+ }
363
+ if ((node.type == "ExprStmt")) {
364
+ this.walkExpr(node.expr, scope, ctx);
365
+ }
366
+ }
367
+
368
+ walkExpr(node, scope, ctx) {
369
+ if (!node) {
370
+ return;
371
+ }
372
+ if ((node.type == "Identifier")) {
373
+ scope.markUsed(node.name);
374
+ return;
375
+ }
376
+ if ((node.type == "AssignExpr")) {
377
+ this.walkExpr(node.target, scope, ctx);
378
+ this.walkExpr(node.value, scope, ctx);
379
+ return;
380
+ }
381
+ if ((node.type == "UpdateExpr")) {
382
+ this.walkExpr(node.operand, scope, ctx);
383
+ return;
384
+ }
385
+ if (((node.type == "BinaryExpr") || (node.type == "PipeExpr"))) {
386
+ this.walkExpr(node.left, scope, ctx);
387
+ this.walkExpr(node.right, scope, ctx);
388
+ return;
389
+ }
390
+ if ((((node.type == "UnaryExpr") || (node.type == "AwaitExpr")) || (node.type == "TypeofExpr"))) {
391
+ this.walkExpr(node.operand, scope, ctx);
392
+ return;
393
+ }
394
+ if ((node.type == "TernaryExpr")) {
395
+ this.walkExpr(node.cond, scope, ctx);
396
+ this.walkExpr(node.then, scope, ctx);
397
+ this.walkExpr(node.else_, scope, ctx);
398
+ return;
399
+ }
400
+ if (((node.type == "CallExpr") || (node.type == "OptCallExpr"))) {
401
+ this.walkExpr(node.callee, scope, ctx);
402
+ for (const a of (node.args ?? [])) {
403
+ this.walkExpr(a, scope, ctx);
404
+ }
405
+ return;
406
+ }
407
+ if (((node.type == "MemberExpr") || (node.type == "OptMemberExpr"))) {
408
+ this.walkExpr(node.obj, scope, ctx);
409
+ return;
410
+ }
411
+ if (((node.type == "IndexExpr") || (node.type == "OptIndexExpr"))) {
412
+ this.walkExpr(node.obj, scope, ctx);
413
+ this.walkExpr(node.idx, scope, ctx);
414
+ return;
415
+ }
416
+ if ((node.type == "NewExpr")) {
417
+ if (node.callee) {
418
+ this.walkExpr(node.callee, scope, ctx);
419
+ }
420
+ for (const a of (node.args ?? [])) {
421
+ this.walkExpr(a, scope, ctx);
422
+ }
423
+ return;
424
+ }
425
+ if ((node.type == "ArrayExpr")) {
426
+ for (const itm of (node.items ?? [])) {
427
+ if (itm) {
428
+ this.walkExpr(itm, scope, ctx);
429
+ }
430
+ }
431
+ return;
432
+ }
433
+ if ((node.type == "ObjectExpr")) {
434
+ for (const pair of (node.pairs ?? [])) {
435
+ if (pair.value) {
436
+ this.walkExpr(pair.value, scope, ctx);
437
+ }
438
+ }
439
+ return;
440
+ }
441
+ if ((node.type == "SpreadExpr")) {
442
+ this.walkExpr(node.expr, scope, ctx);
443
+ return;
444
+ }
445
+ if ((node.type == "LambdaExpr")) {
446
+ const lInner = makeLintScope(scope, "fn");
447
+ for (const p of (node.params ?? [])) {
448
+ const pe = lInner.define(p.name, "val", null);
449
+ pe.used = true;
450
+ }
451
+ this.walkExpr(node.body, lInner, { ...ctx, inFn: true });
452
+ return;
453
+ }
454
+ if ((node.type == "FnDecl")) {
455
+ if (node.name) {
456
+ const fentry = scope.define(node.name, "val", node.loc);
457
+ fentry.used = true;
458
+ }
459
+ const fInner = makeLintScope(scope, "fn");
460
+ for (const p of (node.params ?? [])) {
461
+ const pe2 = fInner.define(p.name, "val", null);
462
+ pe2.used = true;
463
+ }
464
+ if (node.inline) {
465
+ this.walkExpr(node.body, fInner, { ...ctx, inFn: true });
466
+ }
467
+ else {
468
+ this.walkStmts(node.body, fInner, { ...ctx, inFn: true });
469
+ }
470
+ return;
471
+ }
472
+ if ((node.type == "TemplateLit")) {
473
+ this.walkTemplateParts((node.parts ?? []), scope, ctx);
474
+ return;
475
+ }
476
+ if ((((((node.type == "CastExpr") || (node.type == "AsConstExpr")) || (node.type == "SatisfiesExpr")) || (node.type == "IsExpr")) || (node.type == "NonNullExpr"))) {
477
+ this.walkExpr(node.expr, scope, ctx);
478
+ return;
479
+ }
480
+ if ((node.type == "RangeExpr")) {
481
+ this.walkExpr(node.start, scope, ctx);
482
+ this.walkExpr(node.end, scope, ctx);
483
+ }
484
+ }
485
+
486
+ walkTemplateParts(parts, scope, ctx) {
487
+ for (const p of parts) {
488
+ if ((!p || (p.type != "expr"))) {
489
+ continue;
490
+ }
491
+ try {
492
+ const tokens = lexerize(p.value).tokenize();
493
+ const expr = makeParser(tokens).parseExpr();
494
+ this.walkExpr(expr, scope, ctx);
495
+ }
496
+ catch (err3) {
497
+ const re = /\b([a-zA-Z_][a-zA-Z0-9_]*)\b/g;
498
+ let m = re.exec(p.value);
499
+ while (m) {
500
+ scope.markUsed(m[1]);
501
+ m = re.exec(p.value);
502
+ }
503
+ }
504
+ }
505
+ }
506
+
507
+ }
508
+
509
+ module.exports.Linter = Linter;
510
+ class ShadowChecker {
511
+ constructor(issues) {
512
+ this.issues = issues;
513
+ }
514
+
515
+ check(ast) {
516
+ this.issues = [];
517
+ this.scWalkStmts(ast.body, makeLintScope(null, "module"));
518
+ return this.issues;
519
+ }
520
+
521
+ scWarn(name, inner, _outer) {
522
+ this.issues.push(makeLintIssue("shadow-val", "warn", (("'" + name) + "' shadows an outer declaration"), (("Rename one of the '" + name) + "' variables to avoid confusion"), inner));
523
+ }
524
+
525
+ scDefine(scope, name, loc) {
526
+ const outer = scope.lookupParent(name);
527
+ if ((outer && !isIgnoredName(name))) {
528
+ this.scWarn(name, loc, outer.loc);
529
+ }
530
+ scope.define(name, "val", loc);
531
+ }
532
+
533
+ scWalkStmts(stmts, scope) {
534
+ if (!stmts) {
535
+ return;
536
+ }
537
+ for (const node of stmts) {
538
+ this.scWalkStmt(node, scope);
539
+ }
540
+ }
541
+
542
+ scWalkStmt(node, scope) {
543
+ if (!node) {
544
+ return;
545
+ }
546
+ if ((node.type == "VarDecl")) {
547
+ if (node.init) {
548
+ this.scWalkExpr(node.init, scope);
549
+ }
550
+ this.scDefine(scope, node.name, node.loc);
551
+ return;
552
+ }
553
+ if ((node.type == "DestructureDecl")) {
554
+ if (node.init) {
555
+ this.scWalkExpr(node.init, scope);
556
+ }
557
+ if ((node.patternType == "object")) {
558
+ for (const p of node.pattern) {
559
+ this.scDefine(scope, (p.alias ?? p.name), node.loc);
560
+ }
561
+ }
562
+ else {
563
+ for (const p of node.pattern) {
564
+ if (p) {
565
+ this.scDefine(scope, p.name, node.loc);
566
+ }
567
+ }
568
+ }
569
+ return;
570
+ }
571
+ if ((node.type == "FnDecl")) {
572
+ if (node.name) {
573
+ this.scDefine(scope, node.name, node.loc);
574
+ }
575
+ const inner = makeLintScope(scope, "fn");
576
+ for (const p of (node.params ?? [])) {
577
+ this.scDefine(inner, p.name, node.loc);
578
+ }
579
+ if (node.inline) {
580
+ this.scWalkExpr(node.body, inner);
581
+ }
582
+ else {
583
+ this.scWalkStmts(node.body, inner);
584
+ }
585
+ return;
586
+ }
587
+ if ((node.type == "ClassDecl")) {
588
+ this.scDefine(scope, node.name, node.loc);
589
+ const cls = makeLintScope(scope, "class");
590
+ for (const m of (node.methods ?? [])) {
591
+ this.scWalkStmt(m, cls);
592
+ }
593
+ return;
594
+ }
595
+ if ((node.type == "IfStmt")) {
596
+ this.scWalkExpr(node.cond, scope);
597
+ this.scWalkStmts(node.then, makeLintScope(scope, "block"));
598
+ for (const ei of (node.elseifs ?? [])) {
599
+ this.scWalkExpr(ei.cond, scope);
600
+ this.scWalkStmts(ei.body, makeLintScope(scope, "block"));
601
+ }
602
+ if (node.else_) {
603
+ this.scWalkStmts(node.else_, makeLintScope(scope, "block"));
604
+ }
605
+ return;
606
+ }
607
+ if ((node.type == "ForInStmt")) {
608
+ this.scWalkExpr(node.iter, scope);
609
+ const fs2 = makeLintScope(scope, "block");
610
+ this.scDefine(fs2, node.var, node.loc);
611
+ this.scWalkStmts(node.body, fs2);
612
+ return;
613
+ }
614
+ if ((node.type == "WhileStmt")) {
615
+ this.scWalkExpr(node.cond, scope);
616
+ this.scWalkStmts(node.body, makeLintScope(scope, "block"));
617
+ return;
618
+ }
619
+ if ((node.type == "DoWhileStmt")) {
620
+ this.scWalkStmts(node.body, makeLintScope(scope, "block"));
621
+ this.scWalkExpr(node.cond, scope);
622
+ return;
623
+ }
624
+ if ((node.type == "MatchStmt")) {
625
+ this.scWalkExpr(node.subject, scope);
626
+ for (const arm of (node.arms ?? [])) {
627
+ const as2 = makeLintScope(scope, "block");
628
+ if ((arm.pattern && (arm.pattern.type == "VariantPat"))) {
629
+ for (const b of arm.pattern.bindings) {
630
+ this.scDefine(as2, b, node.loc);
631
+ }
632
+ }
633
+ if (arm.guard) {
634
+ this.scWalkExpr(arm.guard, as2);
635
+ }
636
+ if (arm.inline) {
637
+ let scExpr = ((arm.body && arm.body[0]) ? arm.body[0] : null);
638
+ if (((arm.body && arm.body[0]) && arm.body[0].expr)) {
639
+ scExpr = arm.body[0].expr;
640
+ }
641
+ if (scExpr) {
642
+ this.scWalkExpr(scExpr, as2);
643
+ }
644
+ }
645
+ else {
646
+ this.scWalkStmts((arm.body ?? []), as2);
647
+ }
648
+ }
649
+ return;
650
+ }
651
+ if ((node.type == "ReturnStmt")) {
652
+ if (node.value) {
653
+ this.scWalkExpr(node.value, scope);
654
+ }
655
+ return;
656
+ }
657
+ if ((node.type == "ThrowStmt")) {
658
+ this.scWalkExpr(node.value, scope);
659
+ }
660
+ return;
661
+ if ((node.type == "ExprStmt")) {
662
+ this.scWalkExpr(node.expr, scope);
663
+ }
664
+ return;
665
+ if ((node.type == "TryCatchStmt")) {
666
+ this.scWalkStmts(node.tryBody, makeLintScope(scope, "block"));
667
+ if (node.catchBody) {
668
+ const cs = makeLintScope(scope, "block");
669
+ if (node.catchParam) {
670
+ this.scDefine(cs, node.catchParam, node.loc);
671
+ }
672
+ this.scWalkStmts(node.catchBody, cs);
673
+ }
674
+ if (node.finallyBody) {
675
+ this.scWalkStmts(node.finallyBody, makeLintScope(scope, "block"));
676
+ }
677
+ return;
678
+ }
679
+ if ((node.type == "ImportDecl")) {
680
+ if (node.defaultName) {
681
+ this.scDefine(scope, node.defaultName, node.loc);
682
+ }
683
+ if (node.namespaceName) {
684
+ this.scDefine(scope, node.namespaceName, node.loc);
685
+ }
686
+ for (const n of (node.names ?? [])) {
687
+ this.scDefine(scope, ((typeof n == "string") ? n : n.alias), node.loc);
688
+ }
689
+ return;
690
+ }
691
+ if ((node.type == "ExportDecl")) {
692
+ this.scWalkStmt((node.isDefault ? { type: "ExprStmt", expr: node.decl } : node.decl), scope);
693
+ }
694
+ }
695
+
696
+ scWalkExpr(node, scope) {
697
+ if (!node) {
698
+ return;
699
+ }
700
+ if ((node.type == "LambdaExpr")) {
701
+ const inner = makeLintScope(scope, "fn");
702
+ for (const p of (node.params ?? [])) {
703
+ this.scDefine(inner, p.name, null);
704
+ }
705
+ this.scWalkExpr(node.body, inner);
706
+ return;
707
+ }
708
+ if ((node.type == "FnDecl")) {
709
+ const inner2 = makeLintScope(scope, "fn");
710
+ for (const p of (node.params ?? [])) {
711
+ this.scDefine(inner2, p.name, null);
712
+ }
713
+ if (node.inline) {
714
+ this.scWalkExpr(node.body, inner2);
715
+ }
716
+ else {
717
+ this.scWalkStmts(node.body, inner2);
718
+ }
719
+ return;
720
+ }
721
+ if (((node.type == "BinaryExpr") || (node.type == "PipeExpr"))) {
722
+ this.scWalkExpr(node.left, scope);
723
+ this.scWalkExpr(node.right, scope);
724
+ return;
725
+ }
726
+ if ((((((((((node.type == "UnaryExpr") || (node.type == "AwaitExpr")) || (node.type == "TypeofExpr")) || (node.type == "CastExpr")) || (node.type == "AsConstExpr")) || (node.type == "SatisfiesExpr")) || (node.type == "IsExpr")) || (node.type == "NonNullExpr")) || (node.type == "SpreadExpr"))) {
727
+ this.scWalkExpr((node.operand ?? node.expr), scope);
728
+ return;
729
+ }
730
+ if ((node.type == "TernaryExpr")) {
731
+ this.scWalkExpr(node.cond, scope);
732
+ this.scWalkExpr(node.then, scope);
733
+ this.scWalkExpr(node.else_, scope);
734
+ return;
735
+ }
736
+ if (((node.type == "CallExpr") || (node.type == "OptCallExpr"))) {
737
+ this.scWalkExpr(node.callee, scope);
738
+ for (const a of (node.args ?? [])) {
739
+ this.scWalkExpr(a, scope);
740
+ }
741
+ return;
742
+ }
743
+ if (((node.type == "MemberExpr") || (node.type == "OptMemberExpr"))) {
744
+ this.scWalkExpr(node.obj, scope);
745
+ return;
746
+ }
747
+ if (((node.type == "IndexExpr") || (node.type == "OptIndexExpr"))) {
748
+ this.scWalkExpr(node.obj, scope);
749
+ this.scWalkExpr(node.idx, scope);
750
+ return;
751
+ }
752
+ if ((node.type == "NewExpr")) {
753
+ if (node.callee) {
754
+ this.scWalkExpr(node.callee, scope);
755
+ }
756
+ for (const a of (node.args ?? [])) {
757
+ this.scWalkExpr(a, scope);
758
+ }
759
+ return;
760
+ }
761
+ if ((node.type == "ArrayExpr")) {
762
+ for (const itm of (node.items ?? [])) {
763
+ if (itm) {
764
+ this.scWalkExpr(itm, scope);
765
+ }
766
+ }
767
+ return;
768
+ }
769
+ if ((node.type == "ObjectExpr")) {
770
+ for (const pair of (node.pairs ?? [])) {
771
+ if (pair.value) {
772
+ this.scWalkExpr(pair.value, scope);
773
+ }
774
+ }
775
+ return;
776
+ }
777
+ if ((node.type == "AssignExpr")) {
778
+ this.scWalkExpr(node.target, scope);
779
+ this.scWalkExpr(node.value, scope);
780
+ return;
781
+ }
782
+ if ((node.type == "UpdateExpr")) {
783
+ this.scWalkExpr(node.operand, scope);
784
+ return;
785
+ }
786
+ if ((node.type == "RangeExpr")) {
787
+ this.scWalkExpr(node.start, scope);
788
+ this.scWalkExpr(node.end, scope);
789
+ }
790
+ }
791
+
792
+ }
793
+
794
+ module.exports.ShadowChecker = ShadowChecker;
795
+ function lint(ast) {
796
+ const linter = new Linter([]);
797
+ const shadowChecker = new ShadowChecker([]);
798
+ const unusedAndUnreachable = linter.lint(ast);
799
+ const shadows = shadowChecker.check(ast);
800
+ const combined = [...unusedAndUnreachable, ...shadows];
801
+ combined.sort((a, b) => ((a.line ?? 0) - (b.line ?? 0)));
802
+ return combined;
803
+ }
804
+ module.exports.lint = lint;