@amxts/core 0.1.0 → 0.2.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 (74) hide show
  1. package/README.md +18 -23
  2. package/README.ru.md +19 -22
  3. package/as/amxts.d.ts +63 -3
  4. package/as/constants.ts +684 -116
  5. package/as/entities.ts +1905 -1364
  6. package/as/events.ts +1694 -905
  7. package/as/facade.ts +1240 -220
  8. package/as/fetch.ts +1519 -0
  9. package/as/flags.ts +159 -145
  10. package/as/hlds.ts +1071 -0
  11. package/as/hooks.ts +5226 -5379
  12. package/as/kit.ts +15 -5
  13. package/as/lib/check.ts +1 -1
  14. package/as/natives.ts +2658 -2499
  15. package/as/remote.ts +39 -15
  16. package/as/tsconfig.json +6 -2
  17. package/as/vector.ts +12 -9
  18. package/includes/order.txt +22 -29
  19. package/includes/sources.json +0 -8
  20. package/node_modules/assemblyscript/std/assembly/index.d.ts +20 -11
  21. package/package.json +29 -7
  22. package/runtime/deps/assemblyscript/dist/asc.js +86 -16
  23. package/runtime/deps/assemblyscript/dist/assemblyscript.js +29 -29
  24. package/runtime/licenses/MPL-2.0.txt +373 -0
  25. package/runtime/licenses/README.md +5 -1
  26. package/runtime/licenses/curl-COPYING +22 -0
  27. package/runtime/licenses/libssh2-COPYING +43 -0
  28. package/runtime/licenses/mbedTLS-LICENSE +553 -0
  29. package/runtime/natives.txt +108 -105
  30. package/runtime/patches/assemblyscript-0.28.20-amxts.patch +752 -296
  31. package/runtime/patches/wamr-2.4.5-amxts.patch +148 -0
  32. package/scripts/apply-docs.ts +2 -2
  33. package/scripts/auto-imports.ts +2 -2
  34. package/scripts/build-identity.ts +115 -0
  35. package/scripts/build-wasm.ts +101 -50
  36. package/scripts/check.ts +17 -3
  37. package/scripts/client-messages.ts +246 -0
  38. package/scripts/compile-pool.ts +128 -0
  39. package/scripts/compile-worker.ts +23 -0
  40. package/scripts/compile.ts +156 -59
  41. package/scripts/docker-server.ts +13 -3
  42. package/scripts/docs/as/amxts.ts +86 -0
  43. package/scripts/docs/as/facade.ts +688 -188
  44. package/scripts/docs/as/fetch.ts +805 -0
  45. package/scripts/docs/entities.ts +43 -144
  46. package/scripts/docs/events.ts +15 -26
  47. package/scripts/docs/game.ts +68 -22
  48. package/scripts/docs/messages.ts +330 -16
  49. package/scripts/editor-api.ts +101 -0
  50. package/scripts/hlds-events.ts +370 -0
  51. package/scripts/includes.ts +12 -10
  52. package/scripts/player-fields.ts +16 -15
  53. package/scripts/prebuilt.ts +65 -23
  54. package/scripts/prepare.ts +39 -28
  55. package/scripts/project.ts +120 -20
  56. package/scripts/reapi-events.ts +98 -0
  57. package/scripts/shared-modules.ts +85 -23
  58. package/scripts/source-map.ts +242 -0
  59. package/scripts/system.ts +1 -1
  60. package/scripts/typed-commands.ts +263 -0
  61. package/scripts/typed-configs.ts +23 -12
  62. package/scripts/ui.ts +3 -1
  63. package/scripts/upgrade-menus.ts +274 -0
  64. package/scripts/upgrade-names.ts +384 -0
  65. package/scripts/upgrade.ts +830 -0
  66. package/src/cli-api.mjs +37 -4
  67. package/src/system.mjs +74 -3
  68. package/src/testing/compile.ts +8 -5
  69. package/src/testing/natives.ts +199 -5
  70. package/src/testing/network.ts +531 -0
  71. package/src/testing/server.ts +565 -47
  72. package/src/testing/tables.ts +25 -0
  73. package/as/modules/http.ts +0 -184
  74. package/scripts/docs/as/modules/http.ts +0 -66
@@ -378,7 +378,7 @@ index f876049..8d02018 100644
378
378
  function builtin_isArray(ctx: BuiltinFunctionContext): ExpressionRef {
379
379
  let compiler = ctx.compiler;
380
380
  diff --git a/src/compiler.ts b/src/compiler.ts
381
- index f99bd5a..d9c1b77 100644
381
+ index f99bd5a..282aa0e 100644
382
382
  --- a/src/compiler.ts
383
383
  +++ b/src/compiler.ts
384
384
  @@ -49,6 +49,7 @@ import {
@@ -499,7 +499,15 @@ index f99bd5a..d9c1b77 100644
499
499
 
500
500
  // Error if there's neither a type nor an initializer
501
501
  } else {
502
- @@ -1434,10 +1464,63 @@ export class Compiler extends DiagnosticEmitter {
502
+ @@ -1412,6 +1442,7 @@ export class Compiler extends DiagnosticEmitter {
503
+ }
504
+
505
+ let internalName = global.internalName;
506
+ + if (this.earlyGlobals.has(global)) module.removeGlobal(internalName); // amxts: its stand-in
507
+
508
+ if (initializeInStart) { // initialize to mutable zero and set the actual value in start
509
+ if (isDeclaredInline) {
510
+ @@ -1434,10 +1465,76 @@ export class Compiler extends DiagnosticEmitter {
503
511
  } else if (!isDeclaredInline) { // compile normally
504
512
  module.addGlobal(internalName, typeRef, !isDeclaredConstant, initExpr);
505
513
  }
@@ -539,6 +547,15 @@ index f99bd5a..d9c1b77 100644
539
547
  + }
540
548
  +
541
549
  + /**
550
+ + * amxts: the globals read or written above their declaration before it was
551
+ + * compiled. Binaryen looks a global up when it weighs an expression that
552
+ + * reads it - as an indirect call does the function it calls, `STEPS[i]()` -
553
+ + * so each has a stand-in in the module from its first such use, which
554
+ + * compileGlobal replaces with the global itself.
555
+ + */
556
+ + private earlyGlobals: Set<Global> = new Set();
557
+ +
558
+ + /**
542
559
  + * amxts: `expr`, a read or write of `global`, after a check that its
543
560
  + * declaration has run - JavaScript's ReferenceError in the temporal dead
544
561
  + * zone: an abort that says so and ends the current call. The flag it
@@ -546,6 +563,10 @@ index f99bd5a..d9c1b77 100644
546
563
  + */
547
564
  + private makeGlobalTdzCheck(global: Global, expr: ExpressionRef, type: Type, reportNode: Node): ExpressionRef {
548
565
  + let module = this.module;
566
+ + if ((!global.is(CommonFlags.Compiled) || this.pendingElements.has(global)) && !this.earlyGlobals.has(global)) {
567
+ + this.earlyGlobals.add(global);
568
+ + module.addGlobal(global.internalName, global.type.toRef(), true, this.makeZero(global.type));
569
+ + }
549
570
  + let flag = global.tdzFlag;
550
571
  + if (!flag) {
551
572
  + global.tdzFlag = flag = global.internalName + "~initialized";
@@ -563,7 +584,7 @@ index f99bd5a..d9c1b77 100644
563
584
  // === Enums ====================================================================================
564
585
 
565
586
  /** Compiles an enum. */
566
- @@ -1684,6 +1767,7 @@ export class Compiler extends DiagnosticEmitter {
587
+ @@ -1684,6 +1781,7 @@ export class Compiler extends DiagnosticEmitter {
567
588
  }
568
589
 
569
590
  this.currentFlow = previousFlow;
@@ -571,7 +592,7 @@ index f99bd5a..d9c1b77 100644
571
592
 
572
593
  // create the function
573
594
  funcRef = module.addFunction(
574
- @@ -1798,9 +1882,52 @@ export class Compiler extends DiagnosticEmitter {
595
+ @@ -1798,9 +1896,52 @@ export class Compiler extends DiagnosticEmitter {
575
596
  : null;
576
597
  let bodyStartIndex = stmts.length;
577
598
 
@@ -624,7 +645,7 @@ index f99bd5a..d9c1b77 100644
624
645
  } else {
625
646
  // must be an expression statement if not a block
626
647
  assert(bodyNode.kind == NodeKind.Expression);
627
- @@ -1841,6 +1968,9 @@ export class Compiler extends DiagnosticEmitter {
648
+ @@ -1841,6 +1982,9 @@ export class Compiler extends DiagnosticEmitter {
628
649
  allocStmts.push(
629
650
  this.makeConditionalAllocation(classInstance, thisLocal.index)
630
651
  );
@@ -634,7 +655,7 @@ index f99bd5a..d9c1b77 100644
634
655
  this.makeFieldInitializationInConstructor(classInstance, allocStmts);
635
656
 
636
657
  // Insert right before the body
637
- @@ -1876,8 +2006,9 @@ export class Compiler extends DiagnosticEmitter {
658
+ @@ -1876,8 +2020,9 @@ export class Compiler extends DiagnosticEmitter {
638
659
  flow.set(FlowFlags.Returns | FlowFlags.ReturnsNonNull | FlowFlags.Terminates);
639
660
  }
640
661
 
@@ -646,7 +667,7 @@ index f99bd5a..d9c1b77 100644
646
667
  this.error(
647
668
  DiagnosticCode.Constructors_for_derived_classes_must_contain_a_super_call,
648
669
  instance.prototype.declaration.range
649
- @@ -1893,9 +2024,67 @@ export class Compiler extends DiagnosticEmitter {
670
+ @@ -1893,9 +2038,67 @@ export class Compiler extends DiagnosticEmitter {
650
671
  return false; // not recoverable
651
672
  }
652
673
 
@@ -714,7 +735,7 @@ index f99bd5a..d9c1b77 100644
714
735
  /** Makes a built-in getter of a property that is a field. */
715
736
  private makeBuiltinFieldGetter(property: Property): FunctionRef {
716
737
  let getterInstance = assert(property.getterInstance);
717
- @@ -2363,7 +2552,10 @@ export class Compiler extends DiagnosticEmitter {
738
+ @@ -2363,7 +2566,10 @@ export class Compiler extends DiagnosticEmitter {
718
739
  stmts.length = 0;
719
740
  }
720
741
  let flow = this.currentFlow;
@@ -725,7 +746,7 @@ index f99bd5a..d9c1b77 100644
725
746
  let stmt = this.compileStatement(statements[i]);
726
747
  switch (getExpressionId(stmt)) {
727
748
  case ExpressionId.Block: {
728
- @@ -2418,16 +2610,17 @@ export class Compiler extends DiagnosticEmitter {
749
+ @@ -2418,16 +2624,17 @@ export class Compiler extends DiagnosticEmitter {
729
750
  ): ExpressionRef {
730
751
  let module = this.module;
731
752
  let labelNode = statement.label;
@@ -751,7 +772,7 @@ index f99bd5a..d9c1b77 100644
751
772
  if (breakLabel == null) {
752
773
  this.error(
753
774
  DiagnosticCode.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement,
754
- @@ -2436,7 +2629,11 @@ export class Compiler extends DiagnosticEmitter {
775
+ @@ -2436,7 +2643,11 @@ export class Compiler extends DiagnosticEmitter {
755
776
  return module.unreachable();
756
777
  }
757
778
  flow.set(FlowFlags.Breaks);
@@ -764,7 +785,7 @@ index f99bd5a..d9c1b77 100644
764
785
  }
765
786
 
766
787
  private compileContinueStatement(
767
- @@ -2444,17 +2641,18 @@ export class Compiler extends DiagnosticEmitter {
788
+ @@ -2444,17 +2655,18 @@ export class Compiler extends DiagnosticEmitter {
768
789
  ): ExpressionRef {
769
790
  let module = this.module;
770
791
  let label = statement.label;
@@ -791,7 +812,7 @@ index f99bd5a..d9c1b77 100644
791
812
  if (continueLabel == null) {
792
813
  this.error(
793
814
  DiagnosticCode.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement,
794
- @@ -2463,7 +2661,11 @@ export class Compiler extends DiagnosticEmitter {
815
+ @@ -2463,7 +2675,11 @@ export class Compiler extends DiagnosticEmitter {
795
816
  return module.unreachable();
796
817
  }
797
818
  flow.set(FlowFlags.Continues | FlowFlags.Terminates);
@@ -804,7 +825,7 @@ index f99bd5a..d9c1b77 100644
804
825
  }
805
826
 
806
827
  private compileDoStatement(
807
- @@ -2504,6 +2706,7 @@ export class Compiler extends DiagnosticEmitter {
828
+ @@ -2504,6 +2720,7 @@ export class Compiler extends DiagnosticEmitter {
808
829
  flow.continueLabel = continueLabel;
809
830
  let loopLabel = `do-loop|${label}`;
810
831
  this.currentFlow = flow;
@@ -812,7 +833,7 @@ index f99bd5a..d9c1b77 100644
812
833
  let bodyStmts = new Array<ExpressionRef>();
813
834
  let body = statement.body;
814
835
  if (body.kind == NodeKind.Block) {
815
- @@ -2511,6 +2714,7 @@ export class Compiler extends DiagnosticEmitter {
836
+ @@ -2511,6 +2728,7 @@ export class Compiler extends DiagnosticEmitter {
816
837
  } else {
817
838
  bodyStmts.push(this.compileStatement(body));
818
839
  }
@@ -820,7 +841,7 @@ index f99bd5a..d9c1b77 100644
820
841
  flow.popControlFlowLabel(label);
821
842
 
822
843
  let possiblyContinues = flow.isAny(FlowFlags.Continues | FlowFlags.ConditionallyContinues);
823
- @@ -2634,6 +2838,21 @@ export class Compiler extends DiagnosticEmitter {
844
+ @@ -2634,6 +2852,21 @@ export class Compiler extends DiagnosticEmitter {
824
845
  stmts.push(this.compileStatement(initializer));
825
846
  }
826
847
 
@@ -842,7 +863,7 @@ index f99bd5a..d9c1b77 100644
842
863
  // Precompute the condition if present, or default to `true`
843
864
  let condExpr: ExpressionRef;
844
865
  let condExprTrueish: ExpressionRef;
845
- @@ -2669,6 +2888,7 @@ export class Compiler extends DiagnosticEmitter {
866
+ @@ -2669,6 +2902,7 @@ export class Compiler extends DiagnosticEmitter {
846
867
  bodyFlow.continueLabel = continueLabel;
847
868
  let loopLabel = `for-loop|${label}`;
848
869
  this.currentFlow = bodyFlow;
@@ -850,7 +871,7 @@ index f99bd5a..d9c1b77 100644
850
871
  let bodyStmts = new Array<ExpressionRef>();
851
872
  let body = statement.body;
852
873
  if (body.kind == NodeKind.Block) {
853
- @@ -2676,6 +2896,7 @@ export class Compiler extends DiagnosticEmitter {
874
+ @@ -2676,6 +2910,7 @@ export class Compiler extends DiagnosticEmitter {
854
875
  } else {
855
876
  bodyStmts.push(this.compileStatement(body));
856
877
  }
@@ -858,7 +879,7 @@ index f99bd5a..d9c1b77 100644
858
879
  bodyFlow.popControlFlowLabel(label);
859
880
  bodyFlow.breakLabel = null;
860
881
  bodyFlow.continueLabel = null;
861
- @@ -2700,6 +2921,19 @@ export class Compiler extends DiagnosticEmitter {
882
+ @@ -2700,6 +2935,19 @@ export class Compiler extends DiagnosticEmitter {
862
883
  // Compile the incrementor if it possibly executes
863
884
  let possiblyLoops = possiblyContinues || possiblyFallsThrough;
864
885
  if (possiblyLoops) {
@@ -878,7 +899,7 @@ index f99bd5a..d9c1b77 100644
878
899
  let incrementor = statement.incrementor;
879
900
  if (incrementor) {
880
901
  this.currentFlow = flow;
881
- @@ -2802,6 +3036,7 @@ export class Compiler extends DiagnosticEmitter {
902
+ @@ -2802,6 +3050,7 @@ export class Compiler extends DiagnosticEmitter {
882
903
  // Compile ifTrue assuming the condition turned out true
883
904
  let thenStmts = new Array<ExpressionRef>();
884
905
  let thenFlow = flow.forkThen(condExpr);
@@ -886,7 +907,7 @@ index f99bd5a..d9c1b77 100644
886
907
  this.currentFlow = thenFlow;
887
908
  if (ifTrue.kind == NodeKind.Block) {
888
909
  this.compileStatements((<BlockStatement>ifTrue).statements, thenStmts);
889
- @@ -2812,6 +3047,7 @@ export class Compiler extends DiagnosticEmitter {
910
+ @@ -2812,6 +3061,7 @@ export class Compiler extends DiagnosticEmitter {
890
911
 
891
912
  // Compile ifFalse assuming the condition turned out false, if present
892
913
  let elseFlow = flow.forkElse(condExpr);
@@ -894,7 +915,7 @@ index f99bd5a..d9c1b77 100644
894
915
  if (ifFalse) {
895
916
  this.currentFlow = elseFlow;
896
917
  let elseStmts = new Array<ExpressionRef>();
897
- @@ -2850,6 +3086,14 @@ export class Compiler extends DiagnosticEmitter {
918
+ @@ -2850,6 +3100,14 @@ export class Compiler extends DiagnosticEmitter {
898
919
  let flow = this.currentFlow;
899
920
  let returnType = flow.returnType;
900
921
 
@@ -909,7 +930,7 @@ index f99bd5a..d9c1b77 100644
909
930
  let valueExpression = statement.value;
910
931
  if (valueExpression) {
911
932
  let constraints = Constraints.ConvImplicit;
912
- @@ -2861,6 +3105,19 @@ export class Compiler extends DiagnosticEmitter {
933
+ @@ -2861,6 +3119,19 @@ export class Compiler extends DiagnosticEmitter {
913
934
  if (flow.sourceFunction.is(CommonFlags.Constructor) && valueExpression.kind != NodeKind.This) {
914
935
  flow.set(FlowFlags.MayReturnNonThis);
915
936
  }
@@ -929,7 +950,7 @@ index f99bd5a..d9c1b77 100644
929
950
  } else if (returnType != Type.void) {
930
951
  this.error(
931
952
  DiagnosticCode.Type_0_is_not_assignable_to_type_1,
932
- @@ -2868,27 +3125,33 @@ export class Compiler extends DiagnosticEmitter {
953
+ @@ -2868,27 +3139,33 @@ export class Compiler extends DiagnosticEmitter {
933
954
  );
934
955
  this.currentType = returnType;
935
956
  return module.unreachable();
@@ -971,7 +992,7 @@ index f99bd5a..d9c1b77 100644
971
992
  }
972
993
 
973
994
  private compileSwitchStatement(
974
- @@ -3018,12 +3281,49 @@ export class Compiler extends DiagnosticEmitter {
995
+ @@ -3018,12 +3295,51 @@ export class Compiler extends DiagnosticEmitter {
975
996
  private compileThrowStatement(
976
997
  statement: ThrowStatement
977
998
  ): ExpressionRef {
@@ -1013,6 +1034,8 @@ index f99bd5a..d9c1b77 100644
1013
1034
  + module.i32(source.lineAt(statement.range.start)),
1014
1035
  + module.i32(source.columnAt())
1015
1036
  + ], TypeRef.I32);
1037
+ + // amxts: a failed call's stack stops at this call - its place, in the source map
1038
+ + if (this.options.sourceMap) this.addDebugLocation(thrown, statement.range);
1016
1039
  + this.currentType = Type.void;
1017
1040
  + return this.unwindsIn(target)
1018
1041
  + ? module.block(null, [ module.if(thrown, this.makeUnwind()), module.unreachable() ])
@@ -1022,7 +1045,7 @@ index f99bd5a..d9c1b77 100644
1022
1045
  let stmts = new Array<ExpressionRef>();
1023
1046
  let value = statement.value;
1024
1047
  let message: Expression | null = null;
1025
- @@ -3037,17 +3337,685 @@ export class Compiler extends DiagnosticEmitter {
1048
+ @@ -3037,17 +3353,685 @@ export class Compiler extends DiagnosticEmitter {
1026
1049
  return this.module.flatten(stmts);
1027
1050
  }
1028
1051
 
@@ -1714,14 +1737,10 @@ index f99bd5a..d9c1b77 100644
1714
1737
  }
1715
1738
 
1716
1739
  /** Compiles a variable statement. Returns `0` if an initializer is not necessary. */
1717
- @@ -3078,10 +4046,36 @@ export class Compiler extends DiagnosticEmitter {
1740
+ @@ -3078,6 +4062,32 @@ export class Compiler extends DiagnosticEmitter {
1718
1741
  // Resolve type if annotated
1719
1742
  let typeNode = declaration.type;
1720
1743
  let initializerNode = declaration.initializer;
1721
- - if (typeNode) {
1722
- - type = resolver.resolveType( // reports
1723
- - typeNode, flow,
1724
- - flow.sourceFunction,
1725
1744
  + // amxts: one a hoisted function uses has its box already - see hoistFunctions.
1726
1745
  + let predeclared = flow.getScopedLocal(name);
1727
1746
  + if (predeclared && predeclared.closurePredeclared) {
@@ -1748,14 +1767,10 @@ index f99bd5a..d9c1b77 100644
1748
1767
  + continue;
1749
1768
  + }
1750
1769
  + }
1751
- + if (typeNode) {
1752
- + type = resolver.resolveType( // reports
1753
- + typeNode, flow,
1754
- + flow.sourceFunction,
1755
- cloneMap(flow.contextualTypeArguments)
1756
- );
1757
- if (!type) continue;
1758
- @@ -3238,7 +4232,31 @@ export class Compiler extends DiagnosticEmitter {
1770
+ if (typeNode) {
1771
+ type = resolver.resolveType( // reports
1772
+ typeNode, flow,
1773
+ @@ -3238,7 +4248,31 @@ export class Compiler extends DiagnosticEmitter {
1759
1774
  flow.unsetLocalFlag(local.index, ~0);
1760
1775
  if (isConst) flow.setLocalFlag(local.index, LocalFlags.Constant);
1761
1776
  }
@@ -1788,7 +1803,7 @@ index f99bd5a..d9c1b77 100644
1788
1803
  initializers.push(
1789
1804
  this.makeLocalAssignment(local, initExpr, initType ? initType : type, false)
1790
1805
  );
1791
- @@ -3312,6 +4330,7 @@ export class Compiler extends DiagnosticEmitter {
1806
+ @@ -3312,6 +4346,7 @@ export class Compiler extends DiagnosticEmitter {
1792
1807
  let continueLabel = `while-continue|${label}`;
1793
1808
  thenFlow.continueLabel = continueLabel;
1794
1809
  this.currentFlow = thenFlow;
@@ -1796,7 +1811,7 @@ index f99bd5a..d9c1b77 100644
1796
1811
  let bodyStmts = new Array<ExpressionRef>();
1797
1812
  let body = statement.body;
1798
1813
  if (body.kind == NodeKind.Block) {
1799
- @@ -3319,6 +4338,7 @@ export class Compiler extends DiagnosticEmitter {
1814
+ @@ -3319,6 +4354,7 @@ export class Compiler extends DiagnosticEmitter {
1800
1815
  } else {
1801
1816
  bodyStmts.push(this.compileStatement(body));
1802
1817
  }
@@ -1804,7 +1819,7 @@ index f99bd5a..d9c1b77 100644
1804
1819
  bodyStmts.push(
1805
1820
  module.br(continueLabel)
1806
1821
  );
1807
- @@ -3479,6 +4499,11 @@ export class Compiler extends DiagnosticEmitter {
1822
+ @@ -3479,6 +4515,11 @@ export class Compiler extends DiagnosticEmitter {
1808
1823
  break;
1809
1824
  }
1810
1825
  case NodeKind.Call: {
@@ -1816,7 +1831,7 @@ index f99bd5a..d9c1b77 100644
1816
1831
  expr = this.compileCallExpression(<CallExpression>expression, contextualType, constraints);
1817
1832
  break;
1818
1833
  }
1819
- @@ -3487,6 +4512,10 @@ export class Compiler extends DiagnosticEmitter {
1834
+ @@ -3487,6 +4528,10 @@ export class Compiler extends DiagnosticEmitter {
1820
1835
  break;
1821
1836
  }
1822
1837
  case NodeKind.ElementAccess: {
@@ -1827,7 +1842,7 @@ index f99bd5a..d9c1b77 100644
1827
1842
  expr = this.compileElementAccessExpression(<ElementAccessExpression>expression, contextualType, constraints);
1828
1843
  break;
1829
1844
  }
1830
- @@ -3516,6 +4545,10 @@ export class Compiler extends DiagnosticEmitter {
1845
+ @@ -3516,6 +4561,10 @@ export class Compiler extends DiagnosticEmitter {
1831
1846
  break;
1832
1847
  }
1833
1848
  case NodeKind.PropertyAccess: {
@@ -1838,7 +1853,7 @@ index f99bd5a..d9c1b77 100644
1838
1853
  expr = this.compilePropertyAccessExpression(<PropertyAccessExpression>expression, contextualType, constraints);
1839
1854
  break;
1840
1855
  }
1841
- @@ -3571,6 +4604,20 @@ export class Compiler extends DiagnosticEmitter {
1856
+ @@ -3571,6 +4620,20 @@ export class Compiler extends DiagnosticEmitter {
1842
1857
  return expr;
1843
1858
  }
1844
1859
 
@@ -1859,7 +1874,7 @@ index f99bd5a..d9c1b77 100644
1859
1874
  /** Converts an expression's result from one type to another. */
1860
1875
  convertExpression(
1861
1876
  expr: ExpressionRef,
1862
- @@ -3602,10 +4649,46 @@ export class Compiler extends DiagnosticEmitter {
1877
+ @@ -3602,10 +4665,46 @@ export class Compiler extends DiagnosticEmitter {
1863
1878
  // any to void
1864
1879
  if (toType.kind == TypeKind.Void) return module.drop(expr);
1865
1880
 
@@ -1906,7 +1921,7 @@ index f99bd5a..d9c1b77 100644
1906
1921
  } else if (explicit && fromType.isNullableReference && !toType.isNullableReference) {
1907
1922
  // explicit conversion from nullable to non-nullable requires a runtime
1908
1923
  // check here because nonnull state above already didn't know better
1909
- @@ -3614,7 +4697,7 @@ export class Compiler extends DiagnosticEmitter {
1924
+ @@ -3614,7 +4713,7 @@ export class Compiler extends DiagnosticEmitter {
1910
1925
  }
1911
1926
  fromType = fromType.nonNullableType;
1912
1927
  }
@@ -1915,7 +1930,7 @@ index f99bd5a..d9c1b77 100644
1915
1930
  assert(toType.isExternalReference || fromType.kind == toType.kind);
1916
1931
  this.currentType = toType;
1917
1932
  return expr;
1918
- @@ -3670,7 +4753,26 @@ export class Compiler extends DiagnosticEmitter {
1933
+ @@ -3670,7 +4769,26 @@ export class Compiler extends DiagnosticEmitter {
1919
1934
  return module.unreachable();
1920
1935
  }
1921
1936
 
@@ -1943,7 +1958,7 @@ index f99bd5a..d9c1b77 100644
1943
1958
  if (!explicit) {
1944
1959
  this.error(
1945
1960
  DiagnosticCode.Conversion_from_type_0_to_1_requires_an_explicit_cast,
1946
- @@ -3845,10 +4947,14 @@ export class Compiler extends DiagnosticEmitter {
1961
+ @@ -3845,10 +4963,14 @@ export class Compiler extends DiagnosticEmitter {
1947
1962
  let expr = this.compileExpression(expression.expression, contextualType.exceptVoid, inheritedConstraints);
1948
1963
  let type = this.currentType;
1949
1964
  if (this.currentFlow.isNonnull(expr, type)) {
@@ -1962,7 +1977,7 @@ index f99bd5a..d9c1b77 100644
1962
1977
  } else if (!this.options.noAssert) {
1963
1978
  expr = this.makeRuntimeNonNullCheck(expr, type, expression);
1964
1979
  }
1965
- @@ -3893,6 +4999,10 @@ export class Compiler extends DiagnosticEmitter {
1980
+ @@ -3893,6 +5015,10 @@ export class Compiler extends DiagnosticEmitter {
1966
1981
  contextualType: Type,
1967
1982
  ): ExpressionRef {
1968
1983
 
@@ -1973,7 +1988,7 @@ index f99bd5a..d9c1b77 100644
1973
1988
  const left = expression.left;
1974
1989
  const leftExpr = this.compileExpression(left, contextualType);
1975
1990
  const leftType = this.currentType;
1976
- @@ -4109,6 +5219,13 @@ export class Compiler extends DiagnosticEmitter {
1991
+ @@ -4109,6 +5235,13 @@ export class Compiler extends DiagnosticEmitter {
1977
1992
  }
1978
1993
  case Token.Plus_Equals: compound = true;
1979
1994
  case Token.Plus: {
@@ -1987,7 +2002,7 @@ index f99bd5a..d9c1b77 100644
1987
2002
  leftExpr = this.compileExpression(left, contextualType);
1988
2003
  leftType = this.currentType;
1989
2004
 
1990
- @@ -4315,6 +5432,11 @@ export class Compiler extends DiagnosticEmitter {
2005
+ @@ -4315,6 +5448,11 @@ export class Compiler extends DiagnosticEmitter {
1991
2006
  rightExpr = this.compileExpression(right, leftType);
1992
2007
  rightType = this.currentType;
1993
2008
  commonType = Type.commonType(leftType, rightType, contextualType);
@@ -1999,7 +2014,7 @@ index f99bd5a..d9c1b77 100644
1999
2014
  if (!commonType || !commonType.isNumericValue) {
2000
2015
  this.error(
2001
2016
  DiagnosticCode.Operator_0_cannot_be_applied_to_types_1_and_2,
2002
- @@ -4390,6 +5512,13 @@ export class Compiler extends DiagnosticEmitter {
2017
+ @@ -4390,6 +5528,13 @@ export class Compiler extends DiagnosticEmitter {
2003
2018
  break;
2004
2019
  }
2005
2020
  }
@@ -2013,7 +2028,7 @@ index f99bd5a..d9c1b77 100644
2013
2028
  if (!leftType.isIntegerValue) {
2014
2029
  this.error(
2015
2030
  DiagnosticCode.The_0_operator_cannot_be_applied_to_type_1,
2016
- @@ -4417,6 +5546,13 @@ export class Compiler extends DiagnosticEmitter {
2031
+ @@ -4417,6 +5562,13 @@ export class Compiler extends DiagnosticEmitter {
2017
2032
  break;
2018
2033
  }
2019
2034
  }
@@ -2027,7 +2042,7 @@ index f99bd5a..d9c1b77 100644
2027
2042
  if (!leftType.isIntegerValue) {
2028
2043
  this.error(
2029
2044
  DiagnosticCode.The_0_operator_cannot_be_applied_to_type_1,
2030
- @@ -4445,6 +5581,12 @@ export class Compiler extends DiagnosticEmitter {
2045
+ @@ -4445,6 +5597,12 @@ export class Compiler extends DiagnosticEmitter {
2031
2046
  break;
2032
2047
  }
2033
2048
  }
@@ -2040,7 +2055,7 @@ index f99bd5a..d9c1b77 100644
2040
2055
  if (!leftType.isIntegerValue) {
2041
2056
  this.error(
2042
2057
  DiagnosticCode.The_0_operator_cannot_be_applied_to_type_1,
2043
- @@ -4473,6 +5615,13 @@ export class Compiler extends DiagnosticEmitter {
2058
+ @@ -4473,6 +5631,13 @@ export class Compiler extends DiagnosticEmitter {
2044
2059
  }
2045
2060
  }
2046
2061
 
@@ -2054,7 +2069,7 @@ index f99bd5a..d9c1b77 100644
2054
2069
  if (compound) {
2055
2070
  if (!leftType.isIntegerValue) {
2056
2071
  this.error(
2057
- @@ -4486,6 +5635,10 @@ export class Compiler extends DiagnosticEmitter {
2072
+ @@ -4486,6 +5651,10 @@ export class Compiler extends DiagnosticEmitter {
2058
2073
  } else {
2059
2074
  rightExpr = this.compileExpression(right, leftType);
2060
2075
  rightType = this.currentType;
@@ -2065,7 +2080,7 @@ index f99bd5a..d9c1b77 100644
2065
2080
  commonType = Type.commonType(leftType, rightType, contextualType);
2066
2081
  if (!commonType || !commonType.isIntegerValue) {
2067
2082
  this.error(
2068
- @@ -4518,6 +5671,13 @@ export class Compiler extends DiagnosticEmitter {
2083
+ @@ -4518,6 +5687,13 @@ export class Compiler extends DiagnosticEmitter {
2069
2084
  }
2070
2085
  }
2071
2086
 
@@ -2079,7 +2094,7 @@ index f99bd5a..d9c1b77 100644
2079
2094
  if (compound) {
2080
2095
  if (!leftType.isIntegerValue) {
2081
2096
  this.error(
2082
- @@ -4531,6 +5691,10 @@ export class Compiler extends DiagnosticEmitter {
2097
+ @@ -4531,6 +5707,10 @@ export class Compiler extends DiagnosticEmitter {
2083
2098
  } else {
2084
2099
  rightExpr = this.compileExpression(right, leftType);
2085
2100
  rightType = this.currentType;
@@ -2090,7 +2105,7 @@ index f99bd5a..d9c1b77 100644
2090
2105
  commonType = Type.commonType(leftType, rightType, contextualType);
2091
2106
  if (!commonType || !commonType.isIntegerValue) {
2092
2107
  this.error(
2093
- @@ -4563,6 +5727,13 @@ export class Compiler extends DiagnosticEmitter {
2108
+ @@ -4563,6 +5743,13 @@ export class Compiler extends DiagnosticEmitter {
2094
2109
  }
2095
2110
  }
2096
2111
 
@@ -2104,7 +2119,7 @@ index f99bd5a..d9c1b77 100644
2104
2119
  if (compound) {
2105
2120
  if (!leftType.isIntegerValue) {
2106
2121
  this.error(
2107
- @@ -4576,6 +5747,10 @@ export class Compiler extends DiagnosticEmitter {
2122
+ @@ -4576,6 +5763,10 @@ export class Compiler extends DiagnosticEmitter {
2108
2123
  } else {
2109
2124
  rightExpr = this.compileExpression(right, leftType);
2110
2125
  rightType = this.currentType;
@@ -2115,7 +2130,7 @@ index f99bd5a..d9c1b77 100644
2115
2130
  commonType = Type.commonType(leftType, rightType, contextualType);
2116
2131
  if (!commonType || !commonType.isIntegerValue) {
2117
2132
  this.error(
2118
- @@ -4603,6 +5778,7 @@ export class Compiler extends DiagnosticEmitter {
2133
+ @@ -4603,6 +5794,7 @@ export class Compiler extends DiagnosticEmitter {
2119
2134
  leftType = this.currentType;
2120
2135
 
2121
2136
  let rightFlow = flow.forkThen(leftExpr);
@@ -2123,7 +2138,7 @@ index f99bd5a..d9c1b77 100644
2123
2138
  this.currentFlow = rightFlow;
2124
2139
 
2125
2140
  // simplify if only interested in true or false
2126
- @@ -4782,13 +5958,160 @@ export class Compiler extends DiagnosticEmitter {
2141
+ @@ -4782,13 +5974,160 @@ export class Compiler extends DiagnosticEmitter {
2127
2142
  }
2128
2143
  break;
2129
2144
  }
@@ -2290,7 +2305,7 @@ index f99bd5a..d9c1b77 100644
2290
2305
  }
2291
2306
  default: {
2292
2307
  assert(false);
2293
- @@ -4796,12 +6119,31 @@ export class Compiler extends DiagnosticEmitter {
2308
+ @@ -4796,12 +6135,31 @@ export class Compiler extends DiagnosticEmitter {
2294
2309
  break;
2295
2310
  }
2296
2311
  }
@@ -2322,7 +2337,63 @@ index f99bd5a..d9c1b77 100644
2322
2337
  if (!this.currentType.isStrictlyAssignableTo(targetType)) {
2323
2338
  this.error(
2324
2339
  DiagnosticCode.Type_0_is_not_assignable_to_type_1,
2325
- @@ -5683,6 +7025,157 @@ export class Compiler extends DiagnosticEmitter {
2340
+ @@ -5455,13 +6813,54 @@ export class Compiler extends DiagnosticEmitter {
2341
+ if (!instance || !this.compileFunction(instance)) {
2342
+ return module.unreachable();
2343
+ }
2344
+ - return this.makeCallDirect(instance, [ leftExpr, rightExpr ], reportNode);
2345
+ + return this.makeIntegralRem(leftExpr, rightExpr, instance, reportNode);
2346
+ }
2347
+ }
2348
+ assert(false);
2349
+ return module.unreachable();
2350
+ }
2351
+
2352
+ + /**
2353
+ + * amxts: `x % y` of two f64s, where a plugin's whole numbers are: two whole
2354
+ + * numbers within i32 - each the same after i32.trunc_sat and back - take
2355
+ + * i32's remainder, which has the dividend's sign as JavaScript's does, and
2356
+ + * copysign keeps it on a zero (-4 % 2 is -0); anything else, NaN and a zero
2357
+ + * divisor too, is Math.mod's. In place rather than in Math.mod: the call
2358
+ + * itself was most of what a remainder cost. The top level, whose temps are
2359
+ + * not the start function's own (see makeUnwindCheck), calls Math.mod.
2360
+ + */
2361
+ + private makeIntegralRem(leftExpr: ExpressionRef, rightExpr: ExpressionRef, mod: Function, reportNode: Node): ExpressionRef {
2362
+ + let module = this.module;
2363
+ + let flow = this.currentFlow;
2364
+ + let name = flow.targetFunction.internalName;
2365
+ + if (name.startsWith("start:") || name == BuiltinNames.start) {
2366
+ + return this.makeCallDirect(mod, [ leftExpr, rightExpr ], reportNode);
2367
+ + }
2368
+ + let x = flow.getTempLocal(Type.f64).index;
2369
+ + let y = flow.getTempLocal(Type.f64).index;
2370
+ + let ix = flow.getTempLocal(Type.i32).index;
2371
+ + let iy = flow.getTempLocal(Type.i32).index;
2372
+ + let whole = (value: Index, int: Index): ExpressionRef => module.binary(BinaryOp.EqF64,
2373
+ + module.unary(UnaryOp.ConvertI32ToF64, module.local_tee(int, module.unary(UnaryOp.TruncSatF64ToI32, module.local_get(value, TypeRef.F64)), false, TypeRef.I32)),
2374
+ + module.local_get(value, TypeRef.F64)
2375
+ + );
2376
+ + return module.block(null, [
2377
+ + module.local_set(x, leftExpr, false),
2378
+ + module.local_set(y, rightExpr, false),
2379
+ + module.if(
2380
+ + module.binary(BinaryOp.AndI32,
2381
+ + module.binary(BinaryOp.AndI32, whole(x, ix), whole(y, iy)),
2382
+ + module.binary(BinaryOp.NeI32, module.local_get(iy, TypeRef.I32), module.i32(0))
2383
+ + ),
2384
+ + module.binary(BinaryOp.CopysignF64,
2385
+ + module.unary(UnaryOp.ConvertI32ToF64, module.binary(BinaryOp.RemI32, module.local_get(ix, TypeRef.I32), module.local_get(iy, TypeRef.I32))),
2386
+ + module.local_get(x, TypeRef.F64)
2387
+ + ),
2388
+ + this.makeCallDirect(mod, [ module.local_get(x, TypeRef.F64), module.local_get(y, TypeRef.F64) ], reportNode)
2389
+ + )
2390
+ + ], TypeRef.F64);
2391
+ + }
2392
+ +
2393
+ makeShl(leftExpr: ExpressionRef, rightExpr: ExpressionRef, type: Type): ExpressionRef {
2394
+ // Cares about garbage bits on the RHS, but only for types smaller than 5 bits
2395
+ let module = this.module;
2396
+ @@ -5683,6 +7082,166 @@ export class Compiler extends DiagnosticEmitter {
2326
2397
  return this.makeCallDirect(operatorInstance, [ firstExpr, secondExpr ], reportNode);
2327
2398
  }
2328
2399
 
@@ -2347,11 +2418,12 @@ index f99bd5a..d9c1b77 100644
2347
2418
  + }
2348
2419
  +
2349
2420
  + /**
2350
- + * amxts: a value given where `string | (...) => string` is declared - an
2351
- + * argument, an object literal's field, a field's initializer, an
2352
- + * assignment. The type is held as the function, so a string becomes one
2353
- + * that returns it (__textFunction in std/assembly/function.ts); a function,
2354
- + * or anything that is not a string, is compiled as it is.
2421
+ + * amxts: a value given where `string | (...) => string` - or `boolean |
2422
+ + * (...) => boolean` - is declared: an argument, an object literal's field,
2423
+ + * a field's initializer, an assignment. The type is held as the function,
2424
+ + * so a string becomes one that returns it (__textFunction in
2425
+ + * std/assembly/function.ts), a boolean likewise (__boolFunction); a
2426
+ + * function, or anything else, is compiled as it is.
2355
2427
  + */
2356
2428
  + private compileText(
2357
2429
  + value: Expression,
@@ -2385,6 +2457,14 @@ index f99bd5a..d9c1b77 100644
2385
2457
  + this.currentType = helper.signature.returnType;
2386
2458
  + return call;
2387
2459
  + }
2460
+ + if (valueType == Type.bool) {
2461
+ + let expr = this.compileExpression(inner, Type.bool, Constraints.ConvImplicit);
2462
+ + let helper = this.asyncHood("__boolFunction", value, [ type.nonNullableType ]);
2463
+ + if (!helper) return this.module.unreachable();
2464
+ + let call = this.makeCallDirect(helper, [ expr ], value);
2465
+ + this.currentType = helper.signature.returnType;
2466
+ + return call;
2467
+ + }
2388
2468
  + }
2389
2469
  + }
2390
2470
  + return this.compileExpression(value, type, constraints);
@@ -2480,7 +2560,7 @@ index f99bd5a..d9c1b77 100644
2480
2560
  private compileAssignment(
2481
2561
  expression: Expression,
2482
2562
  valueExpression: Expression,
2483
- @@ -5691,6 +7184,13 @@ export class Compiler extends DiagnosticEmitter {
2563
+ @@ -5691,6 +7250,13 @@ export class Compiler extends DiagnosticEmitter {
2484
2564
  let program = this.program;
2485
2565
  let resolver = program.resolver;
2486
2566
  let flow = this.currentFlow;
@@ -2494,7 +2574,7 @@ index f99bd5a..d9c1b77 100644
2494
2574
  let target = resolver.lookupExpression(expression, flow); // reports
2495
2575
  if (!target) return this.module.unreachable();
2496
2576
  let thisExpression = resolver.currentThisExpression;
2497
- @@ -5698,6 +7198,8 @@ export class Compiler extends DiagnosticEmitter {
2577
+ @@ -5698,6 +7264,8 @@ export class Compiler extends DiagnosticEmitter {
2498
2578
 
2499
2579
  // to compile just the value, we need to know the target's type
2500
2580
  let targetType: Type;
@@ -2503,7 +2583,7 @@ index f99bd5a..d9c1b77 100644
2503
2583
  switch (target.kind) {
2504
2584
  case ElementKind.Global:
2505
2585
  case ElementKind.Local: {
2506
- @@ -5705,15 +7207,8 @@ export class Compiler extends DiagnosticEmitter {
2586
+ @@ -5705,15 +7273,8 @@ export class Compiler extends DiagnosticEmitter {
2507
2587
  if (!this.compileGlobalLazy(<Global>target, expression)) {
2508
2588
  return this.module.unreachable();
2509
2589
  }
@@ -2520,7 +2600,7 @@ index f99bd5a..d9c1b77 100644
2520
2600
  if (this.pendingElements.has(target)) {
2521
2601
  this.error(
2522
2602
  DiagnosticCode.Variable_0_used_before_its_declaration,
2523
- @@ -5756,6 +7251,9 @@ export class Compiler extends DiagnosticEmitter {
2603
+ @@ -5756,6 +7317,9 @@ export class Compiler extends DiagnosticEmitter {
2524
2604
  assert(setterInstance.signature.parameterTypes.length == 1); // parser must guarantee this
2525
2605
  targetType = setterInstance.signature.parameterTypes[0];
2526
2606
  if (setterInstance.hasDecorator(DecoratorFlags.Unsafe)) this.checkUnsafe(expression);
@@ -2530,7 +2610,7 @@ index f99bd5a..d9c1b77 100644
2530
2610
  break;
2531
2611
  }
2532
2612
  case ElementKind.IndexSignature: {
2533
- @@ -5804,7 +7302,7 @@ export class Compiler extends DiagnosticEmitter {
2613
+ @@ -5804,7 +7368,7 @@ export class Compiler extends DiagnosticEmitter {
2534
2614
 
2535
2615
  // compile the value and do the assignment
2536
2616
  assert(targetType != Type.void);
@@ -2539,7 +2619,7 @@ index f99bd5a..d9c1b77 100644
2539
2619
  let valueType = this.currentType;
2540
2620
  if (targetType.isNullableReference && this.currentFlow.isNonnull(valueExpr, valueType)) targetType = targetType.nonNullableType;
2541
2621
  return this.makeAssignment(
2542
- @@ -5841,7 +7339,9 @@ export class Compiler extends DiagnosticEmitter {
2622
+ @@ -5841,7 +7405,9 @@ export class Compiler extends DiagnosticEmitter {
2543
2623
  switch (target.kind) {
2544
2624
  case ElementKind.Local: {
2545
2625
  let local = <Local>target;
@@ -2550,7 +2630,7 @@ index f99bd5a..d9c1b77 100644
2550
2630
  this.error(
2551
2631
  DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property,
2552
2632
  valueExpression.range, target.internalName
2553
- @@ -5849,6 +7349,17 @@ export class Compiler extends DiagnosticEmitter {
2633
+ @@ -5849,6 +7415,17 @@ export class Compiler extends DiagnosticEmitter {
2554
2634
  this.currentType = tee ? local.type : Type.void;
2555
2635
  return module.unreachable();
2556
2636
  }
@@ -2568,15 +2648,17 @@ index f99bd5a..d9c1b77 100644
2568
2648
  return this.makeLocalAssignment(local, valueExpr, valueType, tee);
2569
2649
  }
2570
2650
  case ElementKind.Global: {
2571
- @@ -5856,6 +7367,7 @@ export class Compiler extends DiagnosticEmitter {
2651
+ @@ -5856,6 +7433,9 @@ export class Compiler extends DiagnosticEmitter {
2572
2652
  if (!this.compileGlobalLazy(global, valueExpression)) {
2573
2653
  return module.unreachable();
2574
2654
  }
2575
- + flow.forgetGlobalPaths(global.internalName); // amxts: no longer narrowed
2655
+ + flow.forgetGlobalPaths(global.internalName); // amxts: no longer narrowed - or
2656
+ + // narrowed by what it was given, `client = new Client()`, as TypeScript does
2657
+ + if (global.type.isNullableReference && !valueType.isNullableReference) flow.setGlobalNonNull(global.internalName);
2576
2658
  if (target.isAny(CommonFlags.Const | CommonFlags.Readonly)) {
2577
2659
  this.error(
2578
2660
  DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property,
2579
- @@ -5865,7 +7377,14 @@ export class Compiler extends DiagnosticEmitter {
2661
+ @@ -5865,7 +7445,14 @@ export class Compiler extends DiagnosticEmitter {
2580
2662
  this.currentType = tee ? global.type : Type.void;
2581
2663
  return module.unreachable();
2582
2664
  }
@@ -2592,7 +2674,7 @@ index f99bd5a..d9c1b77 100644
2592
2674
  }
2593
2675
  case ElementKind.PropertyPrototype: {
2594
2676
  let propertyInstance = this.resolver.resolveProperty(<PropertyPrototype>target);
2595
- @@ -5893,6 +7412,9 @@ export class Compiler extends DiagnosticEmitter {
2677
+ @@ -5893,6 +7480,9 @@ export class Compiler extends DiagnosticEmitter {
2596
2678
  if (isConstructor && thisExpression.kind == NodeKind.This) {
2597
2679
  flow.setThisFieldFlag(propertyInstance, FieldFlags.Initialized);
2598
2680
  }
@@ -2602,7 +2684,7 @@ index f99bd5a..d9c1b77 100644
2602
2684
  }
2603
2685
  let setterInstance = propertyInstance.setterInstance;
2604
2686
  if (!setterInstance) {
2605
- @@ -5904,6 +7426,39 @@ export class Compiler extends DiagnosticEmitter {
2687
+ @@ -5904,6 +7494,39 @@ export class Compiler extends DiagnosticEmitter {
2606
2688
  }
2607
2689
  assert(setterInstance.signature.parameterTypes.length == 1);
2608
2690
  assert(setterInstance.signature.returnType == Type.void);
@@ -2642,7 +2724,7 @@ index f99bd5a..d9c1b77 100644
2642
2724
  if (propertyInstance.is(CommonFlags.Instance)) {
2643
2725
  let thisType = assert(setterInstance.signature.thisType);
2644
2726
  let thisExpr = this.compileExpression(
2645
- @@ -6028,11 +7583,31 @@ export class Compiler extends DiagnosticEmitter {
2727
+ @@ -6028,11 +7651,31 @@ export class Compiler extends DiagnosticEmitter {
2646
2728
  tee: bool
2647
2729
  ): ExpressionRef {
2648
2730
  let module = this.module;
@@ -2675,7 +2757,7 @@ index f99bd5a..d9c1b77 100644
2675
2757
  if (type.isNullableReference) {
2676
2758
  if (!valueType.isNullableReference || flow.isNonnull(valueExpr, type)) flow.setLocalFlag(localIndex, LocalFlags.NonNull);
2677
2759
  else flow.unsetLocalFlag(localIndex, LocalFlags.NonNull);
2678
- @@ -6042,13 +7617,6 @@ export class Compiler extends DiagnosticEmitter {
2760
+ @@ -6042,13 +7685,6 @@ export class Compiler extends DiagnosticEmitter {
2679
2761
  if (!flow.canOverflow(valueExpr, type)) flow.setLocalFlag(localIndex, LocalFlags.Wrapped);
2680
2762
  else flow.unsetLocalFlag(localIndex, LocalFlags.Wrapped);
2681
2763
  }
@@ -2689,7 +2771,7 @@ index f99bd5a..d9c1b77 100644
2689
2771
  }
2690
2772
 
2691
2773
  /** Makes an assignment to a global. */
2692
- @@ -6146,6 +7714,42 @@ export class Compiler extends DiagnosticEmitter {
2774
+ @@ -6146,6 +7782,42 @@ export class Compiler extends DiagnosticEmitter {
2693
2775
  return module.local_set(thisLocal.index, superCall, classInstance.type.isManaged);
2694
2776
  }
2695
2777
 
@@ -2732,7 +2814,7 @@ index f99bd5a..d9c1b77 100644
2732
2814
  // otherwise resolve normally
2733
2815
  let target = this.resolver.lookupExpression(expression.expression, flow); // reports
2734
2816
  if (!target) return module.unreachable();
2735
- @@ -6443,7 +8047,7 @@ export class Compiler extends DiagnosticEmitter {
2817
+ @@ -6443,7 +8115,7 @@ export class Compiler extends DiagnosticEmitter {
2736
2818
  // otherwise, the arguments may not be inlined, e.g. `abc(abc(123))`
2737
2819
  let args = new Array<ExpressionRef>(numArguments);
2738
2820
  for (let i = 0; i < numArguments; ++i) {
@@ -2741,7 +2823,7 @@ index f99bd5a..d9c1b77 100644
2741
2823
  }
2742
2824
  // make the inlined call
2743
2825
  inlineStack.push(instance);
2744
- @@ -6464,7 +8068,7 @@ export class Compiler extends DiagnosticEmitter {
2826
+ @@ -6464,7 +8136,7 @@ export class Compiler extends DiagnosticEmitter {
2745
2827
  let parameterTypes = signature.parameterTypes;
2746
2828
  for (let i = 0; i < numArguments; ++i, ++index) {
2747
2829
  let paramType = parameterTypes[i];
@@ -2750,7 +2832,7 @@ index f99bd5a..d9c1b77 100644
2750
2832
  operands[index] = paramExpr;
2751
2833
  }
2752
2834
  assert(index == numArgumentsInclThis);
2753
- @@ -6697,42 +8301,943 @@ export class Compiler extends DiagnosticEmitter {
2835
+ @@ -6697,39 +8369,940 @@ export class Compiler extends DiagnosticEmitter {
2754
2836
  return stub;
2755
2837
  }
2756
2838
 
@@ -2865,9 +2947,6 @@ index f99bd5a..d9c1b77 100644
2865
2947
  - let usizeType = this.options.usizeType;
2866
2948
  - let sizeTypeRef = usizeType.toRef();
2867
2949
  - let parameterTypes = instance.signature.parameterTypes;
2868
- - let returnType = instance.signature.returnType;
2869
- - let numParameters = parameterTypes.length;
2870
- - let tempIndex = 1 + parameterTypes.length; // incl. `this`
2871
2950
  + let key = `${source.id}|${target.id}`;
2872
2951
  + let adapter = this.valueArityAdapters.get(key);
2873
2952
  + if (!adapter) {
@@ -3718,13 +3797,10 @@ index f99bd5a..d9c1b77 100644
3718
3797
  + let usizeType = this.options.usizeType;
3719
3798
  + let sizeTypeRef = usizeType.toRef();
3720
3799
  + let parameterTypes = instance.signature.parameterTypes;
3721
- + let returnType = instance.signature.returnType;
3722
- + let numParameters = parameterTypes.length;
3723
- + let tempIndex = 1 + parameterTypes.length; // incl. `this`
3724
-
3725
- // Switch over this's rtId and map it to the respective overload
3726
- let builder = new SwitchBuilder(this.module,
3727
- @@ -7011,7 +9516,7 @@ export class Compiler extends DiagnosticEmitter {
3800
+ let returnType = instance.signature.returnType;
3801
+ let numParameters = parameterTypes.length;
3802
+ let tempIndex = 1 + parameterTypes.length; // incl. `this`
3803
+ @@ -7011,7 +9584,7 @@ export class Compiler extends DiagnosticEmitter {
3728
3804
  lastOperand
3729
3805
  ], lastOperandType.toRef());
3730
3806
  this.operandsTostack(instance.signature, operands);
@@ -3733,7 +3809,7 @@ index f99bd5a..d9c1b77 100644
3733
3809
  if (returnType != Type.void && immediatelyDropped) {
3734
3810
  expr = module.drop(expr);
3735
3811
  this.currentType = Type.void;
3736
- @@ -7029,6 +9534,9 @@ export class Compiler extends DiagnosticEmitter {
3812
+ @@ -7029,6 +9602,9 @@ export class Compiler extends DiagnosticEmitter {
3737
3813
 
3738
3814
  if (operands) this.operandsTostack(instance.signature, operands);
3739
3815
  let expr = module.call(instance.internalName, operands, returnType.toRef());
@@ -3743,7 +3819,7 @@ index f99bd5a..d9c1b77 100644
3743
3819
  this.currentType = returnType;
3744
3820
  return expr;
3745
3821
  }
3746
- @@ -7122,10 +9630,19 @@ export class Compiler extends DiagnosticEmitter {
3822
+ @@ -7122,10 +9698,19 @@ export class Compiler extends DiagnosticEmitter {
3747
3823
  let stmts = new Array<ExpressionRef>();
3748
3824
  let sizeTypeRef = this.options.sizeTypeRef;
3749
3825
 
@@ -3763,7 +3839,7 @@ index f99bd5a..d9c1b77 100644
3763
3839
  functionArg = module.local_get(functionArgLocal.index, sizeTypeRef);
3764
3840
  }
3765
3841
 
3766
- @@ -7133,10 +9650,16 @@ export class Compiler extends DiagnosticEmitter {
3842
+ @@ -7133,10 +9718,16 @@ export class Compiler extends DiagnosticEmitter {
3767
3843
  // provided, so we must set `argumentsLength` in any case. Inject setting it
3768
3844
  // into the index argument, which becomes executed last after any operands.
3769
3845
  let argumentsLength = this.ensureArgumentsLength();
@@ -3784,7 +3860,7 @@ index f99bd5a..d9c1b77 100644
3784
3860
 
3785
3861
  if (operands) this.operandsTostack(signature, operands);
3786
3862
  let expr = module.call_indirect(
3787
- @@ -7146,6 +9669,7 @@ export class Compiler extends DiagnosticEmitter {
3863
+ @@ -7146,6 +9737,7 @@ export class Compiler extends DiagnosticEmitter {
3788
3864
  signature.paramRefs,
3789
3865
  signature.resultRefs
3790
3866
  );
@@ -3792,7 +3868,7 @@ index f99bd5a..d9c1b77 100644
3792
3868
  this.currentType = returnType;
3793
3869
  stmts.push(expr);
3794
3870
  return module.flatten(stmts, returnType.toRef());
3795
- @@ -7176,6 +9700,12 @@ export class Compiler extends DiagnosticEmitter {
3871
+ @@ -7176,6 +9768,12 @@ export class Compiler extends DiagnosticEmitter {
3796
3872
  let module = this.module;
3797
3873
  let targetExpression = expression.expression;
3798
3874
  let resolver = this.resolver;
@@ -3805,7 +3881,7 @@ index f99bd5a..d9c1b77 100644
3805
3881
  let targetElement = resolver.lookupExpression(targetExpression, this.currentFlow, Type.auto, ReportMode.Swallow);
3806
3882
  if (targetElement && targetElement.kind == ElementKind.Enum) {
3807
3883
  const elementExpr = this.compileExpression(expression.elementExpression, Type.i32, Constraints.ConvImplicit);
3808
- @@ -7202,9 +9732,11 @@ export class Compiler extends DiagnosticEmitter {
3884
+ @@ -7202,9 +9800,11 @@ export class Compiler extends DiagnosticEmitter {
3809
3885
  expression.range
3810
3886
  );
3811
3887
  }
@@ -3818,7 +3894,7 @@ index f99bd5a..d9c1b77 100644
3818
3894
  }
3819
3895
  }
3820
3896
  this.error(
3821
- @@ -7224,6 +9756,13 @@ export class Compiler extends DiagnosticEmitter {
3897
+ @@ -7224,6 +9824,13 @@ export class Compiler extends DiagnosticEmitter {
3822
3898
  assert(!declaration.typeParameters); // function expression cannot be generic
3823
3899
  let flow = this.currentFlow;
3824
3900
  let sourceFunction = flow.sourceFunction;
@@ -3832,7 +3908,7 @@ index f99bd5a..d9c1b77 100644
3832
3908
  let isNamed = declaration.name.text.length > 0;
3833
3909
  let isSemanticallyAnonymous = !isNamed || contextualType != Type.void;
3834
3910
  let prototype = new FunctionPrototype(
3835
- @@ -7237,6 +9776,7 @@ export class Compiler extends DiagnosticEmitter {
3911
+ @@ -7237,6 +9844,7 @@ export class Compiler extends DiagnosticEmitter {
3836
3912
  let instance: Function | null;
3837
3913
  let contextualTypeArguments = cloneMap(flow.contextualTypeArguments);
3838
3914
  let module = this.module;
@@ -3840,7 +3916,7 @@ index f99bd5a..d9c1b77 100644
3840
3916
 
3841
3917
  // compile according to context. this differs from a normal function in that omitted parameter
3842
3918
  // and return types can be inferred and omitted arguments can be replaced with dummies.
3843
- @@ -7280,7 +9820,18 @@ export class Compiler extends DiagnosticEmitter {
3919
+ @@ -7280,7 +9888,18 @@ export class Compiler extends DiagnosticEmitter {
3844
3920
 
3845
3921
  // check non-omitted return type
3846
3922
  let returnType = contextualSignature.returnType;
@@ -3860,7 +3936,7 @@ index f99bd5a..d9c1b77 100644
3860
3936
  let resolvedType = this.resolver.resolveType(
3861
3937
  signatureNode.returnType, flow,
3862
3938
  sourceFunction.parent,
3863
- @@ -7334,7 +9885,7 @@ export class Compiler extends DiagnosticEmitter {
3939
+ @@ -7334,7 +9953,7 @@ export class Compiler extends DiagnosticEmitter {
3864
3940
  signature,
3865
3941
  contextualTypeArguments
3866
3942
  );
@@ -3869,7 +3945,7 @@ index f99bd5a..d9c1b77 100644
3869
3945
  let worked = this.compileFunction(instance);
3870
3946
  this.currentType = contextualSignature.type;
3871
3947
  if (!worked) return module.unreachable();
3872
- @@ -7343,7 +9894,7 @@ export class Compiler extends DiagnosticEmitter {
3948
+ @@ -7343,7 +9962,7 @@ export class Compiler extends DiagnosticEmitter {
3873
3949
  } else {
3874
3950
  instance = this.resolver.resolveFunction(prototype, null, contextualTypeArguments);
3875
3951
  if (!instance) return this.module.unreachable();
@@ -3878,7 +3954,7 @@ index f99bd5a..d9c1b77 100644
3878
3954
  let worked = this.compileFunction(instance);
3879
3955
  this.currentType = instance.signature.type;
3880
3956
  if (!worked) return module.unreachable();
3881
- @@ -7354,6 +9905,27 @@ export class Compiler extends DiagnosticEmitter {
3957
+ @@ -7354,6 +9973,27 @@ export class Compiler extends DiagnosticEmitter {
3882
3958
  ? module.i64(i64_low(offset), i64_high(offset))
3883
3959
  : module.i32(i64_low(offset));
3884
3960
 
@@ -3906,7 +3982,7 @@ index f99bd5a..d9c1b77 100644
3906
3982
  // add a constant local referring to the function if applicable
3907
3983
  if (!isSemanticallyAnonymous) {
3908
3984
  let fname = instance.name;
3909
- @@ -7403,6 +9975,9 @@ export class Compiler extends DiagnosticEmitter {
3985
+ @@ -7403,6 +10043,9 @@ export class Compiler extends DiagnosticEmitter {
3910
3986
  let flow = this.currentFlow;
3911
3987
  let sourceFunction = flow.sourceFunction;
3912
3988
 
@@ -3916,7 +3992,7 @@ index f99bd5a..d9c1b77 100644
3916
3992
  // check special keywords first
3917
3993
  switch (expression.kind) {
3918
3994
  case NodeKind.Null: {
3919
- @@ -7439,6 +10014,15 @@ export class Compiler extends DiagnosticEmitter {
3995
+ @@ -7439,6 +10082,15 @@ export class Compiler extends DiagnosticEmitter {
3920
3996
  }
3921
3997
  case NodeKind.This: {
3922
3998
  let thisType = sourceFunction.signature.thisType;
@@ -3932,7 +4008,7 @@ index f99bd5a..d9c1b77 100644
3932
4008
  if (!thisType) {
3933
4009
  this.error(
3934
4010
  DiagnosticCode._this_cannot_be_referenced_in_current_location,
3935
- @@ -7466,6 +10050,17 @@ export class Compiler extends DiagnosticEmitter {
4011
+ @@ -7466,6 +10118,17 @@ export class Compiler extends DiagnosticEmitter {
3936
4012
  return module.local_get(thisLocal.index, thisType.toRef());
3937
4013
  }
3938
4014
  case NodeKind.Super: {
@@ -3950,7 +4026,7 @@ index f99bd5a..d9c1b77 100644
3950
4026
  if (sourceFunction.is(CommonFlags.Constructor)) {
3951
4027
  if (flow.is(FlowFlags.CtorParamContext)) {
3952
4028
  this.error(
3953
- @@ -7545,6 +10140,26 @@ export class Compiler extends DiagnosticEmitter {
4029
+ @@ -7545,6 +10208,26 @@ export class Compiler extends DiagnosticEmitter {
3954
4030
  return this.compileInlineConstant(local, contextualType, constraints);
3955
4031
  }
3956
4032
  let localIndex = local.index;
@@ -3977,7 +4053,7 @@ index f99bd5a..d9c1b77 100644
3977
4053
  if (!flow.isLocalFlag(localIndex, LocalFlags.Initialized)) {
3978
4054
  this.error(
3979
4055
  DiagnosticCode.Variable_0_is_used_before_being_assigned,
3980
- @@ -7559,14 +10174,12 @@ export class Compiler extends DiagnosticEmitter {
4056
+ @@ -7559,14 +10242,12 @@ export class Compiler extends DiagnosticEmitter {
3981
4057
  this.currentType = localType;
3982
4058
  }
3983
4059
 
@@ -3998,7 +4074,7 @@ index f99bd5a..d9c1b77 100644
3998
4074
  }
3999
4075
  let expr = module.local_get(localIndex, localType.toRef());
4000
4076
  if (isNonNull && localType.isNullableExternalReference && this.options.hasFeature(Feature.GC)) {
4001
- @@ -7582,8 +10195,10 @@ export class Compiler extends DiagnosticEmitter {
4077
+ @@ -7582,8 +10263,10 @@ export class Compiler extends DiagnosticEmitter {
4002
4078
  if (!this.compileGlobalLazy(global, expression)) {
4003
4079
  return module.unreachable();
4004
4080
  }
@@ -4010,7 +4086,7 @@ index f99bd5a..d9c1b77 100644
4010
4086
  this.error(
4011
4087
  DiagnosticCode.Variable_0_used_before_its_declaration,
4012
4088
  expression.range,
4013
- @@ -7603,6 +10218,7 @@ export class Compiler extends DiagnosticEmitter {
4089
+ @@ -7603,6 +10286,7 @@ export class Compiler extends DiagnosticEmitter {
4014
4090
  if (global.is(CommonFlags.DefinitelyAssigned) && globalType.isReference && !globalType.isNullableReference) {
4015
4091
  expr = this.makeRuntimeNonNullCheck(expr, globalType, expression);
4016
4092
  }
@@ -4018,7 +4094,7 @@ index f99bd5a..d9c1b77 100644
4018
4094
  this.currentType = globalType;
4019
4095
  return expr;
4020
4096
  }
4021
- @@ -7656,6 +10272,23 @@ export class Compiler extends DiagnosticEmitter {
4097
+ @@ -7656,6 +10340,23 @@ export class Compiler extends DiagnosticEmitter {
4022
4098
  this.currentType = Type.func;
4023
4099
  return module.ref_func(functionInstance.internalName, ensureType(functionInstance.type));
4024
4100
  }
@@ -4042,7 +4118,7 @@ index f99bd5a..d9c1b77 100644
4042
4118
  let offset = this.ensureRuntimeFunction(functionInstance);
4043
4119
  this.currentType = functionInstance.signature.type;
4044
4120
  return this.options.isWasm64
4045
- @@ -8070,6 +10703,9 @@ export class Compiler extends DiagnosticEmitter {
4121
+ @@ -8070,6 +10771,9 @@ export class Compiler extends DiagnosticEmitter {
4046
4122
  switch (expression.literalKind) {
4047
4123
  case LiteralKind.Array: {
4048
4124
  assert(!implicitlyNegate);
@@ -4052,7 +4128,7 @@ index f99bd5a..d9c1b77 100644
4052
4128
  return this.compileArrayLiteral(
4053
4129
  <ArrayLiteralExpression>expression,
4054
4130
  contextualType,
4055
- @@ -8122,14 +10758,15 @@ export class Compiler extends DiagnosticEmitter {
4131
+ @@ -8122,14 +10826,15 @@ export class Compiler extends DiagnosticEmitter {
4056
4132
  assert(!implicitlyNegate);
4057
4133
  return this.compileObjectLiteral(<ObjectLiteralExpression>expression, contextualType);
4058
4134
  }
@@ -4075,7 +4151,7 @@ index f99bd5a..d9c1b77 100644
4075
4151
  }
4076
4152
  }
4077
4153
  assert(false);
4078
- @@ -8361,6 +10998,22 @@ export class Compiler extends DiagnosticEmitter {
4154
+ @@ -8361,6 +11066,22 @@ export class Compiler extends DiagnosticEmitter {
4079
4155
  return this.compileStaticArrayLiteral(expression, contextualType, constraints);
4080
4156
  }
4081
4157
 
@@ -4098,7 +4174,7 @@ index f99bd5a..d9c1b77 100644
4098
4174
  // handle normal arrays
4099
4175
  let element = this.resolver.lookupExpression(expression, flow, this.currentType);
4100
4176
  if (!element) return module.unreachable();
4101
- @@ -8618,6 +11271,27 @@ export class Compiler extends DiagnosticEmitter {
4177
+ @@ -8618,6 +11339,27 @@ export class Compiler extends DiagnosticEmitter {
4102
4178
 
4103
4179
  // Check that contextual type is a class (TODO: hidden class for interfaces?)
4104
4180
  let classReference = contextualType.getClass();
@@ -4126,7 +4202,7 @@ index f99bd5a..d9c1b77 100644
4126
4202
  if (!classReference) {
4127
4203
  this.error(
4128
4204
  DiagnosticCode.Type_0_is_not_assignable_to_type_1,
4129
- @@ -8625,9 +11299,18 @@ export class Compiler extends DiagnosticEmitter {
4205
+ @@ -8625,9 +11367,18 @@ export class Compiler extends DiagnosticEmitter {
4130
4206
  );
4131
4207
  return module.unreachable();
4132
4208
  }
@@ -4145,7 +4221,7 @@ index f99bd5a..d9c1b77 100644
4145
4221
  this.error(
4146
4222
  DiagnosticCode.Not_implemented_0,
4147
4223
  expression.range, "Interface hidden classes"
4148
- @@ -8689,6 +11372,11 @@ export class Compiler extends DiagnosticEmitter {
4224
+ @@ -8689,6 +11440,11 @@ export class Compiler extends DiagnosticEmitter {
4149
4225
  let deferredProperties = new Array<Property>();
4150
4226
  for (let i = 0; i < numNames; ++i) {
4151
4227
  let memberName = names[i].text;
@@ -4157,7 +4233,7 @@ index f99bd5a..d9c1b77 100644
4157
4233
  let member = classReference.getMember(memberName);
4158
4234
  if (!member || member.kind != ElementKind.PropertyPrototype) {
4159
4235
  this.error(
4160
- @@ -8736,9 +11424,55 @@ export class Compiler extends DiagnosticEmitter {
4236
+ @@ -8736,9 +11492,55 @@ export class Compiler extends DiagnosticEmitter {
4161
4237
  }
4162
4238
 
4163
4239
  let propertyType = propertyInstance.type;
@@ -4214,7 +4290,18 @@ index f99bd5a..d9c1b77 100644
4214
4290
  ], setterInstance.identifierNode, true);
4215
4291
  if (this.currentType != Type.void) { // in case
4216
4292
  expr = module.drop(expr);
4217
- @@ -9128,6 +11862,9 @@ export class Compiler extends DiagnosticEmitter {
4293
+ @@ -8924,7 +11726,9 @@ export class Compiler extends DiagnosticEmitter {
4294
+ let contextualTypeArguments = cloneMap(classInstance.contextualTypeArguments);
4295
+ if (baseClass) {
4296
+ let baseCtor = this.ensureConstructor(baseClass, reportNode);
4297
+ - this.checkFieldInitialization(baseClass, reportNode);
4298
+ + // amxts: a class that implements an interface of fields declares them
4299
+ + // again, as TypeScript has it, and they are checked as its own
4300
+ + if (shapeBaseOf(classInstance) != baseClass) this.checkFieldInitialization(baseClass, reportNode);
4301
+ instance = new Function(
4302
+ CommonNames.constructor,
4303
+ new FunctionPrototype(
4304
+ @@ -9128,6 +11932,9 @@ export class Compiler extends DiagnosticEmitter {
4218
4305
  let resolver = this.resolver;
4219
4306
  let target = resolver.lookupExpression(expression, flow, ctxType); // reports
4220
4307
  if (!target) return module.unreachable();
@@ -4224,7 +4311,7 @@ index f99bd5a..d9c1b77 100644
4224
4311
  let thisExpression = resolver.currentThisExpression;
4225
4312
  if (target.hasDecorator(DecoratorFlags.Unsafe)) this.checkUnsafe(expression);
4226
4313
 
4227
- @@ -9209,7 +11946,12 @@ export class Compiler extends DiagnosticEmitter {
4314
+ @@ -9209,7 +12016,12 @@ export class Compiler extends DiagnosticEmitter {
4228
4315
  Constraints.ConvImplicit | Constraints.IsThis
4229
4316
  );
4230
4317
  }
@@ -4238,7 +4325,7 @@ index f99bd5a..d9c1b77 100644
4238
4325
  }
4239
4326
  case ElementKind.FunctionPrototype: {
4240
4327
  let functionPrototype = <FunctionPrototype>target;
4241
- @@ -9236,6 +11978,18 @@ export class Compiler extends DiagnosticEmitter {
4328
+ @@ -9236,6 +12048,18 @@ export class Compiler extends DiagnosticEmitter {
4242
4329
  return module.unreachable();
4243
4330
  }
4244
4331
 
@@ -4257,7 +4344,7 @@ index f99bd5a..d9c1b77 100644
4257
4344
  let offset = this.ensureRuntimeFunction(functionInstance);
4258
4345
  return this.options.isWasm64
4259
4346
  ? module.i64(i64_low(offset), i64_high(offset))
4260
- @@ -9258,6 +12012,11 @@ export class Compiler extends DiagnosticEmitter {
4347
+ @@ -9258,6 +12082,11 @@ export class Compiler extends DiagnosticEmitter {
4261
4348
  let ifThen = expression.ifThen;
4262
4349
  let ifElse = expression.ifElse;
4263
4350
 
@@ -4269,7 +4356,7 @@ index f99bd5a..d9c1b77 100644
4269
4356
  let condExpr = this.compileExpression(expression.condition, Type.bool);
4270
4357
  let condExprTrueish = this.makeIsTrueish(condExpr, this.currentType, expression.condition);
4271
4358
  // Try to eliminate unnecesssary branches if the condition is constant
4272
- @@ -9272,11 +12031,13 @@ export class Compiler extends DiagnosticEmitter {
4359
+ @@ -9272,14 +12101,17 @@ export class Compiler extends DiagnosticEmitter {
4273
4360
 
4274
4361
  let outerFlow = this.currentFlow;
4275
4362
  let ifThenFlow = outerFlow.forkThen(condExpr);
@@ -4283,7 +4370,34 @@ index f99bd5a..d9c1b77 100644
4283
4370
  this.currentFlow = ifElseFlow;
4284
4371
  let ifElseExpr = this.compileExpression(ifElse, contextualType == Type.auto ? ifThenType : contextualType);
4285
4372
  let ifElseType = this.currentType;
4286
- @@ -9828,7 +12589,7 @@ export class Compiler extends DiagnosticEmitter {
4373
+ + let lenient = false;
4374
+
4375
+ if (contextualType == Type.void) { // values, including type mismatch, are irrelevant
4376
+ if (ifThenType != Type.void) {
4377
+ @@ -9301,6 +12133,11 @@ export class Compiler extends DiagnosticEmitter {
4378
+ this.currentType = contextualType;
4379
+ return module.unreachable();
4380
+ }
4381
+ + // amxts: `map.has(key) ? map.get(key) : fallback` - null only from a
4382
+ + // lenient read is checked where it is used, as for the read alone
4383
+ + lenient = commonType.isNullableReference &&
4384
+ + (!ifThenType.isNullableReference || this.isLenientRead(ifThenExpr)) &&
4385
+ + (!ifElseType.isNullableReference || this.isLenientRead(ifElseExpr));
4386
+ ifThenExpr = this.convertExpression(ifThenExpr, ifThenType, commonType, false, ifThen);
4387
+ ifThenType = commonType;
4388
+ ifElseExpr = this.convertExpression(ifElseExpr, ifElseType, commonType, false, ifElse);
4389
+ @@ -9311,7 +12148,9 @@ export class Compiler extends DiagnosticEmitter {
4390
+ outerFlow.inheritAlternatives(ifThenFlow, ifElseFlow);
4391
+ this.currentFlow = outerFlow;
4392
+
4393
+ - return module.if(condExprTrueish, ifThenExpr, ifElseExpr);
4394
+ + let expr = module.if(condExprTrueish, ifThenExpr, ifElseExpr);
4395
+ + if (lenient) this.recordReads.add(expr);
4396
+ + return expr;
4397
+ }
4398
+
4399
+ private compileUnaryPostfixExpression(
4400
+ @@ -9828,7 +12667,7 @@ export class Compiler extends DiagnosticEmitter {
4287
4401
  contextualType == Type.void
4288
4402
  ? Type.i32
4289
4403
  : contextualType.isFloatValue
@@ -4292,7 +4406,7 @@ index f99bd5a..d9c1b77 100644
4292
4406
  : contextualType,
4293
4407
  Constraints.None
4294
4408
  );
4295
- @@ -9847,7 +12608,12 @@ export class Compiler extends DiagnosticEmitter {
4409
+ @@ -9847,7 +12686,12 @@ export class Compiler extends DiagnosticEmitter {
4296
4410
  return module.unreachable();
4297
4411
  }
4298
4412
 
@@ -4306,7 +4420,7 @@ index f99bd5a..d9c1b77 100644
4306
4420
 
4307
4421
  switch (this.currentType.kind) {
4308
4422
  case TypeKind.Bool:
4309
- @@ -9887,10 +12653,13 @@ export class Compiler extends DiagnosticEmitter {
4423
+ @@ -9887,10 +12731,13 @@ export class Compiler extends DiagnosticEmitter {
4310
4424
  case Token.TypeOf: {
4311
4425
  return this.compileTypeof(expression, contextualType, constraints);
4312
4426
  }
@@ -4321,7 +4435,16 @@ index f99bd5a..d9c1b77 100644
4321
4435
  );
4322
4436
  return module.unreachable();
4323
4437
  }
4324
- @@ -10220,6 +12989,31 @@ export class Compiler extends DiagnosticEmitter {
4438
+ @@ -10067,6 +12914,8 @@ export class Compiler extends DiagnosticEmitter {
4439
+ addDebugLocation(expr: ExpressionRef, range: Range): void {
4440
+ let targetFunction = this.currentFlow.targetFunction;
4441
+ let source = range.source;
4442
+ + // amxts: what the compiler makes itself has no file to point at
4443
+ + if (source == Source.native) return;
4444
+ if (source.debugInfoIndex < 0) source.debugInfoIndex = this.module.addDebugInfoFile(source.normalizedPath);
4445
+ // It's possible that an `expr` is seen multiple times, for example when
4446
+ // first adding debug information for an inner expression and later on for
4447
+ @@ -10220,6 +13069,31 @@ export class Compiler extends DiagnosticEmitter {
4325
4448
  case TypeKind.U64: return module.binary(BinaryOp.NeI64, expr, module.i64(0));
4326
4449
  case TypeKind.Isize:
4327
4450
  case TypeKind.Usize: {
@@ -4353,7 +4476,7 @@ index f99bd5a..d9c1b77 100644
4353
4476
  return type.size == 64
4354
4477
  ? module.binary(BinaryOp.NeI64, expr, module.i64(0))
4355
4478
  : expr;
4356
- @@ -10323,10 +13117,59 @@ export class Compiler extends DiagnosticEmitter {
4479
+ @@ -10323,10 +13197,59 @@ export class Compiler extends DiagnosticEmitter {
4357
4480
  }
4358
4481
  }
4359
4482
 
@@ -4413,7 +4536,7 @@ index f99bd5a..d9c1b77 100644
4413
4536
  if (type == stringType) {
4414
4537
  return expr;
4415
4538
  }
4416
- @@ -10364,7 +13207,7 @@ export class Compiler extends DiagnosticEmitter {
4539
+ @@ -10364,7 +13287,7 @@ export class Compiler extends DiagnosticEmitter {
4417
4540
  type.nonNullableType,
4418
4541
  reportNode
4419
4542
  ),
@@ -4422,7 +4545,7 @@ index f99bd5a..d9c1b77 100644
4422
4545
  );
4423
4546
  }
4424
4547
  let toStringReturnType = toStringSignature.returnType;
4425
- @@ -10436,85 +13279,664 @@ export class Compiler extends DiagnosticEmitter {
4548
+ @@ -10436,85 +13359,664 @@ export class Compiler extends DiagnosticEmitter {
4426
4549
  );
4427
4550
  }
4428
4551
 
@@ -5159,21 +5282,32 @@ index f99bd5a..d9c1b77 100644
5159
5282
  }
5160
5283
 
5161
5284
  /** Makes a call to `abort`, if present, otherwise creates a trap. */
5162
- @@ -10555,7 +13977,7 @@ export class Compiler extends DiagnosticEmitter {
5285
+ @@ -10554,20 +14056,72 @@ export class Compiler extends DiagnosticEmitter {
5286
+ let filenameExpr = this.ensureStaticString(codeLocation.range.source.normalizedPath);
5163
5287
  let range = codeLocation.range;
5164
5288
  let source = range.source;
5289
+ + let abortCall = module.call(
5290
+ + abortInstance.internalName, [
5291
+ + messageExpr,
5292
+ + filenameExpr,
5293
+ + module.i32(source.lineAt(range.start)),
5294
+ + module.i32(source.columnAt())
5295
+ + ],
5296
+ + TypeRef.None
5297
+ + );
5298
+ + // amxts: a failed call's stack stops at this call - its place, in the source map
5299
+ + if (this.options.sourceMap) this.addDebugLocation(abortCall, range);
5165
5300
  return module.block(null, [
5166
5301
  - module.call(
5167
- + this.makeAbortReset(module.call(
5168
- abortInstance.internalName, [
5169
- messageExpr,
5170
- filenameExpr,
5171
- @@ -10563,11 +13985,59 @@ export class Compiler extends DiagnosticEmitter {
5172
- module.i32(source.columnAt())
5173
- ],
5174
- TypeRef.None
5302
+ - abortInstance.internalName, [
5303
+ - messageExpr,
5304
+ - filenameExpr,
5305
+ - module.i32(source.lineAt(range.start)),
5306
+ - module.i32(source.columnAt())
5307
+ - ],
5308
+ - TypeRef.None
5175
5309
  - ),
5176
- + )),
5310
+ + this.makeAbortReset(abortCall),
5177
5311
  module.unreachable()
5178
5312
  ]);
5179
5313
  }
@@ -5188,7 +5322,7 @@ index f99bd5a..d9c1b77 100644
5188
5322
  + let module = this.module;
5189
5323
  + let target = this.currentFlow.targetFunction;
5190
5324
  + let throwHood = this.unwindsIn(target) ? this.exceptionFunction("__throw", reportNode) : null;
5191
- + if (!throwHood) return this.makeStaticAbort(this.ensureStaticString(message), reportNode);
5325
+ + if (!throwHood) return this.makeStaticAbort(this.ensureStaticString(`${kind}: ${message}`), reportNode);
5192
5326
  + let range = reportNode.range;
5193
5327
  + let source = range.source;
5194
5328
  + let previousType = this.currentType;
@@ -5203,6 +5337,7 @@ index f99bd5a..d9c1b77 100644
5203
5337
  + module.i32(source.lineAt(range.start)),
5204
5338
  + module.i32(source.columnAt())
5205
5339
  + ], TypeRef.I32);
5340
+ + if (this.options.sourceMap) this.addDebugLocation(thrown, range);
5206
5341
  + return module.block(null, [ module.if(thrown, this.makeUnwind()), module.unreachable() ]);
5207
5342
  + }
5208
5343
  +
@@ -5229,7 +5364,7 @@ index f99bd5a..d9c1b77 100644
5229
5364
  /** Makes a runtime non-null check, e.g. on `<Type>possiblyNull` or `possiblyNull!`. */
5230
5365
  makeRuntimeNonNullCheck(
5231
5366
  /** Expression being checked. */
5232
- @@ -10575,7 +14045,9 @@ export class Compiler extends DiagnosticEmitter {
5367
+ @@ -10575,7 +14129,9 @@ export class Compiler extends DiagnosticEmitter {
5233
5368
  /** Type of the expression. */
5234
5369
  type: Type,
5235
5370
  /** Report node. */
@@ -5240,7 +5375,7 @@ index f99bd5a..d9c1b77 100644
5240
5375
  ): ExpressionRef {
5241
5376
  let module = this.module;
5242
5377
  let flow = this.currentFlow;
5243
- @@ -10584,10 +14056,7 @@ export class Compiler extends DiagnosticEmitter {
5378
+ @@ -10584,10 +14140,7 @@ export class Compiler extends DiagnosticEmitter {
5244
5379
  if (!flow.canOverflow(expr, type)) flow.setLocalFlag(tempIndex, LocalFlags.Wrapped);
5245
5380
  flow.setLocalFlag(tempIndex, LocalFlags.NonNull);
5246
5381
 
@@ -5252,7 +5387,7 @@ index f99bd5a..d9c1b77 100644
5252
5387
 
5253
5388
  if (type.isExternalReference) {
5254
5389
  let nonNullExpr = module.local_get(tempIndex, type.toRef());
5255
- @@ -10629,10 +14098,7 @@ export class Compiler extends DiagnosticEmitter {
5390
+ @@ -10629,10 +14182,7 @@ export class Compiler extends DiagnosticEmitter {
5256
5391
  let temp = flow.getTempLocal(type);
5257
5392
  let tempIndex = temp.index;
5258
5393
 
@@ -5264,7 +5399,7 @@ index f99bd5a..d9c1b77 100644
5264
5399
 
5265
5400
  if (!toType.isNullableReference || flow.isNonnull(expr, type)) {
5266
5401
  // Simplify if the value cannot be `null`. If toType is non-nullable, a
5267
- @@ -10725,3 +14191,505 @@ function mangleImportName(
5402
+ @@ -10725,3 +14275,505 @@ function mangleImportName(
5268
5403
  );
5269
5404
  }
5270
5405
  }
@@ -5802,10 +5937,18 @@ index 016ba4e..3fda5d4 100644
5802
5937
  "Cannot create an instance of an abstract class.": 2511,
5803
5938
  "Non-abstract class '{0}' does not implement inherited abstract member '{1}' from '{2}'.": 2515,
5804
5939
  diff --git a/src/flow.ts b/src/flow.ts
5805
- index ddc7941..b0f883a 100644
5940
+ index ddc7941..fbe7b3b 100644
5806
5941
  --- a/src/flow.ts
5807
5942
  +++ b/src/flow.ts
5808
- @@ -71,12 +71,15 @@ import {
5943
+ @@ -46,6 +46,7 @@ import {
5944
+ getLocalGetIndex,
5945
+ isLocalTee,
5946
+ getLocalSetValue,
5947
+ + getGlobalSetValue,
5948
+ getGlobalGetName,
5949
+ getBinaryOp,
5950
+ getBinaryLeft,
5951
+ @@ -71,12 +72,15 @@ import {
5809
5952
  getUnaryValue,
5810
5953
  getCallOperandAt,
5811
5954
  getCallOperandCount,
@@ -5822,7 +5965,7 @@ index ddc7941..b0f883a 100644
5822
5965
  } from "./common";
5823
5966
 
5824
5967
  import {
5825
- @@ -88,7 +91,8 @@ import {
5968
+ @@ -88,7 +92,8 @@ import {
5826
5969
  } from "./diagnostics";
5827
5970
 
5828
5971
  import {
@@ -5832,7 +5975,7 @@ index ddc7941..b0f883a 100644
5832
5975
  } from "./ast";
5833
5976
 
5834
5977
  import {
5835
- @@ -259,6 +263,14 @@ export class Flow {
5978
+ @@ -259,6 +264,14 @@ export class Flow {
5836
5979
  localFlags: LocalFlags[] = [];
5837
5980
  /** Field flags on `this`. Constructors only. */
5838
5981
  thisFieldFlags: Map<Property,FieldFlags> | null = null;
@@ -5847,7 +5990,7 @@ index ddc7941..b0f883a 100644
5847
5990
  /** The label we break to when encountering a return statement, when inlining. */
5848
5991
  inlineReturnLabel: string | null = null;
5849
5992
  /** Alternative flows if a compound expression is true-ish. */
5850
- @@ -354,6 +366,8 @@ export class Flow {
5993
+ @@ -354,6 +367,8 @@ export class Flow {
5851
5994
  branch.continueLabel = this.continueLabel;
5852
5995
  }
5853
5996
  branch.localFlags = this.localFlags.slice();
@@ -5856,7 +5999,7 @@ index ddc7941..b0f883a 100644
5856
5999
  if (this.sourceFunction.is(CommonFlags.Constructor)) {
5857
6000
  let thisFieldFlags = assert(this.thisFieldFlags);
5858
6001
  branch.thisFieldFlags = cloneMap(thisFieldFlags);
5859
- @@ -540,9 +554,33 @@ export class Flow {
6002
+ @@ -540,9 +555,33 @@ export class Flow {
5860
6003
  lookup(name: string): Element | null {
5861
6004
  let element = this.lookupLocal(name);
5862
6005
  if (element) return element;
@@ -5890,7 +6033,7 @@ index ddc7941..b0f883a 100644
5890
6033
  /** Tests if the local at the specified index has the specified flag or flags. */
5891
6034
  isLocalFlag(index: i32, flag: LocalFlags, defaultIfInlined: bool = true): bool {
5892
6035
  if (index < 0) return defaultIfInlined;
5893
- @@ -667,6 +705,7 @@ export class Flow {
6036
+ @@ -667,6 +706,7 @@ export class Flow {
5894
6037
  this.flags = this.flags | otherFlags; // what happens before is still true
5895
6038
  this.localFlags = other.localFlags;
5896
6039
  this.thisFieldFlags = other.thisFieldFlags;
@@ -5898,7 +6041,7 @@ index ddc7941..b0f883a 100644
5898
6041
  }
5899
6042
 
5900
6043
 
5901
- @@ -768,6 +807,9 @@ export class Flow {
6044
+ @@ -768,6 +808,9 @@ export class Flow {
5902
6045
 
5903
6046
  // field flags do not matter here since there's only INITIALIZED, which can
5904
6047
  // only be set if it has been observed prior to entering the branch.
@@ -5908,7 +6051,7 @@ index ddc7941..b0f883a 100644
5908
6051
  }
5909
6052
 
5910
6053
  /** Inherits two alternate branches to become this flow, i.e. then with else. */
5911
- @@ -893,6 +935,15 @@ export class Flow {
6054
+ @@ -893,6 +936,15 @@ export class Flow {
5912
6055
  }
5913
6056
  }
5914
6057
 
@@ -5924,7 +6067,7 @@ index ddc7941..b0f883a 100644
5924
6067
  // field flags (currently only INITIALIZED, so can simplify)
5925
6068
  let leftFieldFlags = left.thisFieldFlags;
5926
6069
  if (leftFieldFlags) {
5927
- @@ -944,6 +995,18 @@ export class Flow {
6070
+ @@ -944,6 +996,18 @@ export class Flow {
5928
6071
  }
5929
6072
  }
5930
6073
  }
@@ -5943,7 +6086,7 @@ index ddc7941..b0f883a 100644
5943
6086
  if (needsRecompile) {
5944
6087
  // Reset function locals to state before the compilation attempt
5945
6088
  assert(localsByIndex.length >= numLocalsBefore);
5946
- @@ -971,10 +1034,84 @@ export class Flow {
6089
+ @@ -971,10 +1035,91 @@ export class Flow {
5947
6090
  let local = this.targetFunction.localsByIndex[getLocalGetIndex(expr)];
5948
6091
  return !local.type.isNullableReference || this.isLocalFlag(local.index, LocalFlags.NonNull, false);
5949
6092
  }
@@ -6000,6 +6143,13 @@ index ddc7941..b0f883a 100644
6000
6143
  + * amxts: forgets the paths rooted at local `index` (it was assigned), or,
6001
6144
  + * with `getter`, those that go through that field (it was assigned).
6002
6145
  + */
6146
+ + /** amxts: remembers that global `name` is not null here - it was assigned an object. */
6147
+ + setGlobalNonNull(name: string): void {
6148
+ + let paths = this.nonNullPaths;
6149
+ + if (!paths) this.nonNullPaths = paths = new Set();
6150
+ + paths.add("g@" + name);
6151
+ + }
6152
+ +
6003
6153
  + /** amxts: forgets the paths rooted at global `name` - it was assigned. */
6004
6154
  + forgetGlobalPaths(name: string): void {
6005
6155
  + let paths = this.nonNullPaths;
@@ -6028,7 +6178,20 @@ index ddc7941..b0f883a 100644
6028
6178
  /** Updates local states to reflect that this branch is only taken when `expr` is true-ish. */
6029
6179
  private inheritNonnullIfTrue(
6030
6180
  /** Expression being true. */
6031
- @@ -1019,6 +1156,11 @@ export class Flow {
6181
+ @@ -984,6 +1129,12 @@ export class Flow {
6182
+ ): void {
6183
+ // A: `expr` is true-ish -> Q: how did that happen?
6184
+
6185
+ + // amxts: a call checked for an error is the call - see checkedCallValue
6186
+ + if (getExpressionId(expr) == ExpressionId.Block) {
6187
+ + let value = checkedCallValue(expr);
6188
+ + if (value) expr = value;
6189
+ + }
6190
+ +
6191
+ // The iff argument is useful in situations like
6192
+ //
6193
+ // if (!ref) {
6194
+ @@ -1019,6 +1170,11 @@ export class Flow {
6032
6195
  }
6033
6196
  break;
6034
6197
  }
@@ -6040,7 +6203,7 @@ index ddc7941..b0f883a 100644
6040
6203
  case ExpressionId.Unary: {
6041
6204
  switch (getUnaryOp(expr)) {
6042
6205
  case UnaryOp.EqzI32:
6043
- @@ -1056,7 +1198,13 @@ export class Flow {
6206
+ @@ -1056,7 +1212,13 @@ export class Flow {
6044
6207
  }
6045
6208
  break;
6046
6209
  }
@@ -6054,7 +6217,19 @@ index ddc7941..b0f883a 100644
6054
6217
  // handle string eq/ne/not overloads
6055
6218
  let name = getCallTarget(expr);
6056
6219
  if (name == BuiltinNames.String_eq) {
6057
- @@ -1211,7 +1359,11 @@ export class Flow {
6220
+ @@ -1097,6 +1259,11 @@ export class Flow {
6221
+ iff: Flow | null = null
6222
+ ): void {
6223
+ // A: `expr` is false-ish -> Q: how did that happen?
6224
+ + // amxts: a call checked for an error is the call - see checkedCallValue
6225
+ + if (getExpressionId(expr) == ExpressionId.Block) {
6226
+ + let value = checkedCallValue(expr);
6227
+ + if (value) expr = value;
6228
+ + }
6229
+ switch (getExpressionId(expr)) {
6230
+ case ExpressionId.Unary: {
6231
+ switch (getUnaryOp(expr)) {
6232
+ @@ -1211,7 +1378,11 @@ export class Flow {
6058
6233
  // overflows if the conversion does (globals are wrapped on set)
6059
6234
  case ExpressionId.GlobalGet: {
6060
6235
  // TODO: this is inefficient because it has to read a string
@@ -6067,7 +6242,7 @@ index ddc7941..b0f883a 100644
6067
6242
  assert(global.kind == ElementKind.Global || global.kind == ElementKind.EnumValue);
6068
6243
  return canConversionOverflow((<TypedElement>global).type, type);
6069
6244
  }
6070
- @@ -1477,3 +1629,42 @@ function canConversionOverflow(fromType: Type, toType: Type): bool {
6245
+ @@ -1477,3 +1648,62 @@ function canConversionOverflow(fromType: Type, toType: Type): bool {
6071
6246
  fromType.isSignedIntegerValue != toType.isSignedIntegerValue // signedness mismatch
6072
6247
  );
6073
6248
  }
@@ -6091,10 +6266,30 @@ index ddc7941..b0f883a 100644
6091
6266
  + let inner = fieldPathKey(getCallOperandAt(expr, 0));
6092
6267
  + return inner != null ? inner + ">" + name : null;
6093
6268
  + }
6269
+ + case ExpressionId.Block: {
6270
+ + let value = checkedCallValue(expr);
6271
+ + return value ? fieldPathKey(value) : null;
6272
+ + }
6094
6273
  + }
6095
6274
  + return null;
6096
6275
  +}
6097
6276
  +
6277
+ +/**
6278
+ + * amxts: in a program with a try, a call is checked for an error it threw -
6279
+ + * (set temp (call)) (if __thrown unwind) (get temp), Compiler.makeUnwindCheck
6280
+ + * - and what it reads is still the call's. The call, or 0 for any other block.
6281
+ + */
6282
+ +export function checkedCallValue(expr: ExpressionRef): ExpressionRef {
6283
+ + if (getBlockName(expr) != null || getBlockChildCount(expr) != 3) return 0;
6284
+ + if (getExpressionId(getBlockChildAt(expr, 1)) != ExpressionId.If) return 0;
6285
+ + let set = getBlockChildAt(expr, 0);
6286
+ + switch (getExpressionId(set)) {
6287
+ + case ExpressionId.LocalSet: return getLocalSetValue(set);
6288
+ + case ExpressionId.GlobalSet: return getGlobalSetValue(set);
6289
+ + }
6290
+ + return 0;
6291
+ +}
6292
+ +
6098
6293
  +function copyPaths(paths: Set<string>): Set<string> {
6099
6294
  + let copy = new Set<string>();
6100
6295
  + for (let _values = Set_values(paths), i = 0, k = _values.length; i < k; ++i) copy.add(_values[i]);
@@ -6110,8 +6305,24 @@ index ddc7941..b0f883a 100644
6110
6305
  + }
6111
6306
  + return both;
6112
6307
  +}
6308
+ diff --git a/src/module.ts b/src/module.ts
6309
+ index def4e78..f9cabf9 100644
6310
+ --- a/src/module.ts
6311
+ +++ b/src/module.ts
6312
+ @@ -3276,6 +3276,11 @@ export function getLocalSetValue(expr: ExpressionRef): ExpressionRef {
6313
+ return binaryen._BinaryenLocalSetGetValue(expr);
6314
+ }
6315
+
6316
+ +// amxts: the value a global.set stores - see Flow's fieldPathKey
6317
+ +export function getGlobalSetValue(expr: ExpressionRef): ExpressionRef {
6318
+ + return binaryen._BinaryenGlobalSetGetValue(expr);
6319
+ +}
6320
+ +
6321
+ export function isLocalTee(expr: ExpressionRef): bool {
6322
+ return binaryen._BinaryenLocalSetIsTee(expr);
6323
+ }
6113
6324
  diff --git a/src/parser.ts b/src/parser.ts
6114
- index 157351c..10c3f5c 100644
6325
+ index 157351c..11c0184 100644
6115
6326
  --- a/src/parser.ts
6116
6327
  +++ b/src/parser.ts
6117
6328
  @@ -31,7 +31,8 @@ import {
@@ -6767,7 +6978,7 @@ index 157351c..10c3f5c 100644
6767
6978
  } else {
6768
6979
  if (!suppressErrors) {
6769
6980
  this.error(
6770
- @@ -678,11 +1212,130 @@ export class Parser extends DiagnosticEmitter {
6981
+ @@ -678,11 +1212,145 @@ export class Parser extends DiagnosticEmitter {
6771
6982
  return null;
6772
6983
  }
6773
6984
  // ... | type
@@ -6822,6 +7033,21 @@ index 157351c..10c3f5c 100644
6822
7033
  + continue;
6823
7034
  + }
6824
7035
  +
7036
+ + // amxts: `boolean | ((player: Player) => boolean)` - a yes or no that is
7037
+ + // fixed, or that depends on who asks. Held as the function, as text is:
7038
+ + // a boolean given where this type is declared becomes a function
7039
+ + // returning it (Compiler.compileText, __boolFunction).
7040
+ + let typeIsBoolean = type.kind == NodeKind.NamedType && isBoolName((<NamedTypeNode>type).name.identifier.text);
7041
+ + let nextIsBoolean = nextType.kind == NodeKind.NamedType && isBoolName((<NamedTypeNode>nextType).name.identifier.text);
7042
+ + if ((typeIsBoolean && nextIsFunction) || (typeIsFunction && nextIsBoolean)) {
7043
+ + let fn = <FunctionTypeNode>(typeIsFunction ? type : nextType);
7044
+ + fn.acceptsText = true;
7045
+ + fn.range = tn.range(startPos, tn.pos);
7046
+ + type = fn;
7047
+ + this.needsCallEnv = true;
7048
+ + continue;
7049
+ + }
7050
+ +
6825
7051
  + // amxts: `((player: Player) => boolean) | Requirement[]` - one test, or a
6826
7052
  + // list of objects that each carry one. It is held as the list: a
6827
7053
  + // function given where this type is declared becomes a list of one
@@ -6899,7 +7125,7 @@ index 157351c..10c3f5c 100644
6899
7125
  if (!typeIsNull && !nextTypeIsNull) {
6900
7126
  if (!suppressErrors) {
6901
7127
  this.error(
6902
- @@ -705,6 +1358,26 @@ export class Parser extends DiagnosticEmitter {
7128
+ @@ -705,6 +1373,26 @@ export class Parser extends DiagnosticEmitter {
6903
7129
  // ... [][]
6904
7130
  while (tn.skip(Token.OpenBracket)) {
6905
7131
  let bracketStart = tn.tokenPos;
@@ -6926,7 +7152,7 @@ index 157351c..10c3f5c 100644
6926
7152
  if (!tn.skip(Token.CloseBracket)) {
6927
7153
  if (!suppressErrors) {
6928
7154
  this.error(
6929
- @@ -718,9 +1391,26 @@ export class Parser extends DiagnosticEmitter {
7155
+ @@ -718,9 +1406,26 @@ export class Parser extends DiagnosticEmitter {
6930
7156
 
6931
7157
  // ...[] | null
6932
7158
  let nullable = false;
@@ -6953,7 +7179,7 @@ index 157351c..10c3f5c 100644
6953
7179
  } else {
6954
7180
  if (!suppressErrors) {
6955
7181
  this.error(
6956
- @@ -737,9 +1427,20 @@ export class Parser extends DiagnosticEmitter {
7182
+ @@ -737,9 +1442,20 @@ export class Parser extends DiagnosticEmitter {
6957
7183
  nullable,
6958
7184
  tn.range(startPos, tn.pos)
6959
7185
  );
@@ -6974,7 +7200,7 @@ index 157351c..10c3f5c 100644
6974
7200
  return type;
6975
7201
  }
6976
7202
 
6977
- @@ -984,6 +1685,16 @@ export class Parser extends DiagnosticEmitter {
7203
+ @@ -984,6 +1700,16 @@ export class Parser extends DiagnosticEmitter {
6978
7204
 
6979
7205
  let declarations = new Array<VariableDeclaration>();
6980
7206
  do {
@@ -6991,7 +7217,7 @@ index 157351c..10c3f5c 100644
6991
7217
  let declaration = this.parseVariableDeclaration(tn, flags, decorators, isFor);
6992
7218
  if (!declaration) return null;
6993
7219
  declaration.overriddenModuleName = this.currentModuleName;
6994
- @@ -995,6 +1706,277 @@ export class Parser extends DiagnosticEmitter {
7220
+ @@ -995,6 +1721,277 @@ export class Parser extends DiagnosticEmitter {
6995
7221
  return ret;
6996
7222
  }
6997
7223
 
@@ -7269,7 +7495,7 @@ index 157351c..10c3f5c 100644
7269
7495
  parseVariableDeclaration(
7270
7496
  tn: Tokenizer,
7271
7497
  parentFlags: CommonFlags,
7272
- @@ -1081,7 +2063,7 @@ export class Parser extends DiagnosticEmitter {
7498
+ @@ -1081,7 +2078,7 @@ export class Parser extends DiagnosticEmitter {
7273
7499
  flags: CommonFlags,
7274
7500
  decorators: DecoratorNode[] | null,
7275
7501
  startPos: i32
@@ -7278,7 +7504,7 @@ index 157351c..10c3f5c 100644
7278
7504
 
7279
7505
  // at 'enum': Identifier '{' (EnumValueDeclaration (',' EnumValueDeclaration )*)? '}' ';'?
7280
7506
 
7281
- @@ -1117,6 +2099,8 @@ export class Parser extends DiagnosticEmitter {
7507
+ @@ -1117,6 +2114,8 @@ export class Parser extends DiagnosticEmitter {
7282
7508
  }
7283
7509
  }
7284
7510
  }
@@ -7287,7 +7513,7 @@ index 157351c..10c3f5c 100644
7287
7513
  let ret = Node.createEnumDeclaration(
7288
7514
  identifier,
7289
7515
  decorators,
7290
- @@ -1125,7 +2109,34 @@ export class Parser extends DiagnosticEmitter {
7516
+ @@ -1125,7 +2124,34 @@ export class Parser extends DiagnosticEmitter {
7291
7517
  tn.range(startPos, tn.pos)
7292
7518
  );
7293
7519
  ret.overriddenModuleName = this.currentModuleName;
@@ -7323,7 +7549,7 @@ index 157351c..10c3f5c 100644
7323
7549
  return ret;
7324
7550
  }
7325
7551
 
7326
- @@ -1235,16 +2246,41 @@ export class Parser extends DiagnosticEmitter {
7552
+ @@ -1235,16 +2261,41 @@ export class Parser extends DiagnosticEmitter {
7327
7553
  );
7328
7554
  let extendsType: NamedTypeNode | null = null;
7329
7555
  if (tn.skip(Token.Extends)) {
@@ -7373,7 +7599,7 @@ index 157351c..10c3f5c 100644
7373
7599
  }
7374
7600
  let defaultType: NamedTypeNode | null = null;
7375
7601
  if (tn.skip(Token.Equals)) {
7376
- @@ -1413,9 +2449,21 @@ export class Parser extends DiagnosticEmitter {
7602
+ @@ -1413,9 +2464,21 @@ export class Parser extends DiagnosticEmitter {
7377
7603
  }
7378
7604
  isRest = true;
7379
7605
  }
@@ -7398,7 +7624,7 @@ index 157351c..10c3f5c 100644
7398
7624
  let type: TypeNode | null = null;
7399
7625
  if (isOptional = tn.skip(Token.Question)) {
7400
7626
  if (isRest) {
7401
- @@ -1450,6 +2498,39 @@ export class Parser extends DiagnosticEmitter {
7627
+ @@ -1450,6 +2513,39 @@ export class Parser extends DiagnosticEmitter {
7402
7628
  initializer = this.parseExpression(tn, Precedence.Comma + 1);
7403
7629
  if (!initializer) return null;
7404
7630
  }
@@ -7438,7 +7664,7 @@ index 157351c..10c3f5c 100644
7438
7664
  let param = Node.createParameter(
7439
7665
  isRest
7440
7666
  ? ParameterKind.Rest
7441
- @@ -1462,6 +2543,7 @@ export class Parser extends DiagnosticEmitter {
7667
+ @@ -1462,6 +2558,7 @@ export class Parser extends DiagnosticEmitter {
7442
7668
  Range.join(assert(startRange), tn.range())
7443
7669
  );
7444
7670
  param.flags |= accessFlags;
@@ -7446,7 +7672,7 @@ index 157351c..10c3f5c 100644
7446
7672
  return param;
7447
7673
  } else {
7448
7674
  this.error(
7449
- @@ -1477,7 +2559,7 @@ export class Parser extends DiagnosticEmitter {
7675
+ @@ -1477,7 +2574,7 @@ export class Parser extends DiagnosticEmitter {
7450
7676
  flags: CommonFlags,
7451
7677
  decorators: DecoratorNode[] | null,
7452
7678
  startPos: i32
@@ -7455,7 +7681,7 @@ index 157351c..10c3f5c 100644
7455
7681
 
7456
7682
  // at 'function':
7457
7683
  // Identifier
7458
- @@ -1486,6 +2568,9 @@ export class Parser extends DiagnosticEmitter {
7684
+ @@ -1486,6 +2583,9 @@ export class Parser extends DiagnosticEmitter {
7459
7685
  // '{' Statement* '}'
7460
7686
  // ';'?
7461
7687
 
@@ -7465,7 +7691,7 @@ index 157351c..10c3f5c 100644
7465
7691
  if (!tn.skipIdentifier()) {
7466
7692
  this.error(
7467
7693
  DiagnosticCode.Identifier_expected,
7468
- @@ -1552,16 +2637,25 @@ export class Parser extends DiagnosticEmitter {
7694
+ @@ -1552,16 +2652,25 @@ export class Parser extends DiagnosticEmitter {
7469
7695
  if (!returnType) return null;
7470
7696
  }
7471
7697
 
@@ -7499,7 +7725,7 @@ index 157351c..10c3f5c 100644
7499
7725
  }
7500
7726
 
7501
7727
  let signature = Node.createFunctionType(
7502
- @@ -1571,6 +2665,8 @@ export class Parser extends DiagnosticEmitter {
7728
+ @@ -1571,6 +2680,8 @@ export class Parser extends DiagnosticEmitter {
7503
7729
  false,
7504
7730
  tn.range(signatureStart, tn.pos)
7505
7731
  );
@@ -7508,7 +7734,7 @@ index 157351c..10c3f5c 100644
7508
7734
 
7509
7735
  let body: Statement | null = null;
7510
7736
  if (tn.skip(Token.OpenBrace)) {
7511
- @@ -1581,15 +2677,35 @@ export class Parser extends DiagnosticEmitter {
7737
+ @@ -1581,15 +2692,35 @@ export class Parser extends DiagnosticEmitter {
7512
7738
  ); // recoverable
7513
7739
  }
7514
7740
 
@@ -7544,7 +7770,7 @@ index 157351c..10c3f5c 100644
7544
7770
  let ret = Node.createFunctionDeclaration(
7545
7771
  name,
7546
7772
  decorators,
7547
- @@ -1605,6 +2721,17 @@ export class Parser extends DiagnosticEmitter {
7773
+ @@ -1605,6 +2736,17 @@ export class Parser extends DiagnosticEmitter {
7548
7774
  return ret;
7549
7775
  }
7550
7776
 
@@ -7562,7 +7788,7 @@ index 157351c..10c3f5c 100644
7562
7788
  parseFunctionExpression(tn: Tokenizer): FunctionExpression | null {
7563
7789
  let startPos = tn.tokenPos;
7564
7790
  let name: IdentifierExpression;
7565
- @@ -1641,9 +2768,13 @@ export class Parser extends DiagnosticEmitter {
7791
+ @@ -1641,9 +2783,13 @@ export class Parser extends DiagnosticEmitter {
7566
7792
 
7567
7793
  // TODO: type parameters? doesn't seem worth it.
7568
7794
 
@@ -7576,7 +7802,7 @@ index 157351c..10c3f5c 100644
7576
7802
 
7577
7803
  return this.parseFunctionExpressionCommon(tn, name, parameters, this.parseParametersThis, arrowKind, startPos, signatureStart);
7578
7804
  }
7579
- @@ -1685,17 +2816,32 @@ export class Parser extends DiagnosticEmitter {
7805
+ @@ -1685,17 +2831,32 @@ export class Parser extends DiagnosticEmitter {
7580
7806
  false,
7581
7807
  tn.range(signatureStart, tn.pos)
7582
7808
  );
@@ -7610,7 +7836,7 @@ index 157351c..10c3f5c 100644
7610
7836
  this.error(
7611
7837
  DiagnosticCode._0_expected,
7612
7838
  tn.range(tn.pos), "{"
7613
- @@ -1704,7 +2850,26 @@ export class Parser extends DiagnosticEmitter {
7839
+ @@ -1704,7 +2865,26 @@ export class Parser extends DiagnosticEmitter {
7614
7840
  }
7615
7841
  body = this.parseBlockStatement(tn, false);
7616
7842
  }
@@ -7637,7 +7863,7 @@ index 157351c..10c3f5c 100644
7637
7863
 
7638
7864
  let declaration = Node.createFunctionDeclaration(
7639
7865
  name,
7640
- @@ -1724,7 +2889,7 @@ export class Parser extends DiagnosticEmitter {
7866
+ @@ -1724,7 +2904,7 @@ export class Parser extends DiagnosticEmitter {
7641
7867
  flags: CommonFlags,
7642
7868
  decorators: DecoratorNode[] | null,
7643
7869
  startPos: i32
@@ -7646,7 +7872,7 @@ index 157351c..10c3f5c 100644
7646
7872
 
7647
7873
  // at ('class' | 'interface'):
7648
7874
  // Identifier
7649
- @@ -1852,6 +3017,52 @@ export class Parser extends DiagnosticEmitter {
7875
+ @@ -1852,6 +3032,52 @@ export class Parser extends DiagnosticEmitter {
7650
7876
  }
7651
7877
  declaration.range.end = tn.pos;
7652
7878
  declaration.overriddenModuleName = this.currentModuleName;
@@ -7699,7 +7925,7 @@ index 157351c..10c3f5c 100644
7699
7925
  return declaration;
7700
7926
  }
7701
7927
 
7702
- @@ -2084,6 +3295,20 @@ export class Parser extends DiagnosticEmitter {
7928
+ @@ -2084,6 +3310,20 @@ export class Parser extends DiagnosticEmitter {
7703
7929
  }
7704
7930
  }
7705
7931
 
@@ -7720,7 +7946,7 @@ index 157351c..10c3f5c 100644
7720
7946
  // check if accessor: ('get' | 'set') ^\n Identifier
7721
7947
  let state = tn.mark();
7722
7948
  let isConstructor = false;
7723
- @@ -2093,7 +3318,7 @@ export class Parser extends DiagnosticEmitter {
7949
+ @@ -2093,7 +3333,7 @@ export class Parser extends DiagnosticEmitter {
7724
7950
  let isSetter = false;
7725
7951
  let setStart = 0;
7726
7952
  let setEnd = 0;
@@ -7729,7 +7955,7 @@ index 157351c..10c3f5c 100644
7729
7955
  if (tn.skip(Token.Get)) {
7730
7956
  if (tn.peek(IdentifierHandling.Prefer) == Token.Identifier && !tn.peekOnNewLine()) {
7731
7957
  flags |= CommonFlags.Get;
7732
- @@ -2126,7 +3351,7 @@ export class Parser extends DiagnosticEmitter {
7958
+ @@ -2126,7 +3366,7 @@ export class Parser extends DiagnosticEmitter {
7733
7959
  } else {
7734
7960
  tn.reset(state);
7735
7961
  }
@@ -7738,7 +7964,7 @@ index 157351c..10c3f5c 100644
7738
7964
  flags |= CommonFlags.Constructor;
7739
7965
  isConstructor = true;
7740
7966
  if (!startPos) startPos = tn.tokenPos;
7741
- @@ -2206,15 +3431,22 @@ export class Parser extends DiagnosticEmitter {
7967
+ @@ -2206,15 +3446,22 @@ export class Parser extends DiagnosticEmitter {
7742
7968
  tn.skip(Token.Semicolon);
7743
7969
  return retIndex;
7744
7970
  }
@@ -7769,7 +7995,7 @@ index 157351c..10c3f5c 100644
7769
7995
  }
7770
7996
  let typeParameters: TypeParameterNode[] | null = null;
7771
7997
  if (tn.skip(Token.LessThan)) {
7772
- @@ -2299,6 +3531,7 @@ export class Parser extends DiagnosticEmitter {
7998
+ @@ -2299,6 +3546,7 @@ export class Parser extends DiagnosticEmitter {
7773
7999
  }
7774
8000
 
7775
8001
  let returnType: TypeNode | null = null;
@@ -7777,7 +8003,7 @@ index 157351c..10c3f5c 100644
7777
8003
  if (tn.skip(Token.Colon)) {
7778
8004
  if (name.kind == NodeKind.Constructor) {
7779
8005
  this.error(
7780
- @@ -2313,14 +3546,20 @@ export class Parser extends DiagnosticEmitter {
8006
+ @@ -2313,14 +3561,20 @@ export class Parser extends DiagnosticEmitter {
7781
8007
  }
7782
8008
  returnType = this.parseType(tn, isSetter || name.kind == NodeKind.Constructor);
7783
8009
  if (!returnType) return null;
@@ -7804,7 +8030,7 @@ index 157351c..10c3f5c 100644
7804
8030
  }
7805
8031
 
7806
8032
  let signature = Node.createFunctionType(
7807
- @@ -2330,6 +3569,8 @@ export class Parser extends DiagnosticEmitter {
8033
+ @@ -2330,6 +3584,8 @@ export class Parser extends DiagnosticEmitter {
7808
8034
  false,
7809
8035
  tn.range(signatureStart, tn.pos)
7810
8036
  );
@@ -7813,7 +8039,7 @@ index 157351c..10c3f5c 100644
7813
8039
 
7814
8040
  let body: Statement | null = null;
7815
8041
  if (tn.skip(Token.OpenBrace)) {
7816
- @@ -2349,7 +3590,10 @@ export class Parser extends DiagnosticEmitter {
8042
+ @@ -2349,7 +3605,10 @@ export class Parser extends DiagnosticEmitter {
7817
8043
  tn.range(), ";"
7818
8044
  ); // recoverable
7819
8045
  }
@@ -7824,7 +8050,7 @@ index 157351c..10c3f5c 100644
7824
8050
  if (!body) return null;
7825
8051
  } else if (!isInterface && !(flags & (CommonFlags.Ambient | CommonFlags.Abstract))) {
7826
8052
  this.error(
7827
- @@ -2358,6 +3602,9 @@ export class Parser extends DiagnosticEmitter {
8053
+ @@ -2358,6 +3617,9 @@ export class Parser extends DiagnosticEmitter {
7828
8054
  ); // recoverable
7829
8055
  }
7830
8056
 
@@ -7834,7 +8060,7 @@ index 157351c..10c3f5c 100644
7834
8060
  let retMethod = Node.createMethodDeclaration(
7835
8061
  name,
7836
8062
  decorators,
7837
- @@ -2415,23 +3662,21 @@ export class Parser extends DiagnosticEmitter {
8063
+ @@ -2415,23 +3677,21 @@ export class Parser extends DiagnosticEmitter {
7838
8064
  }
7839
8065
 
7840
8066
  let type: TypeNode | null = null;
@@ -7866,7 +8092,7 @@ index 157351c..10c3f5c 100644
7866
8092
  }
7867
8093
  let initializer: Expression | null = null;
7868
8094
  if (tn.skip(Token.Equals)) {
7869
- @@ -2450,6 +3695,43 @@ export class Parser extends DiagnosticEmitter {
8095
+ @@ -2450,6 +3710,43 @@ export class Parser extends DiagnosticEmitter {
7870
8096
  );
7871
8097
  }
7872
8098
  }
@@ -7910,7 +8136,7 @@ index 157351c..10c3f5c 100644
7910
8136
  let range = tn.range(startPos, tn.pos);
7911
8137
  if ((flags & CommonFlags.DefinitelyAssigned) != 0 && (isInterface || (flags & CommonFlags.Ambient) != 0)) {
7912
8138
  this.error(
7913
- @@ -2465,6 +3747,7 @@ export class Parser extends DiagnosticEmitter {
8139
+ @@ -2465,6 +3762,7 @@ export class Parser extends DiagnosticEmitter {
7914
8140
  initializer,
7915
8141
  range
7916
8142
  );
@@ -7918,7 +8144,7 @@ index 157351c..10c3f5c 100644
7918
8144
  if (!(isInterface && tn.skip(Token.Comma))) {
7919
8145
  tn.skip(Token.Semicolon);
7920
8146
  }
7921
- @@ -2473,6 +3756,200 @@ export class Parser extends DiagnosticEmitter {
8147
+ @@ -2473,6 +3771,208 @@ export class Parser extends DiagnosticEmitter {
7922
8148
  return null;
7923
8149
  }
7924
8150
 
@@ -8040,6 +8266,14 @@ index 157351c..10c3f5c 100644
8040
8266
  + for (let i = 0, k = node.bodyStatements.length; i < k; ++i) this.collectReturns(node.bodyStatements[i], values, locals);
8041
8267
  + let catchStatements = node.catchStatements;
8042
8268
  + if (catchStatements) {
8269
+ + // amxts: `catch (error) { return error.name; }` - the caught value
8270
+ + // is an Error, as Compiler.compileTryStatement declares it.
8271
+ + let caught = node.catchVariable;
8272
+ + if (caught && !locals.has(caught.text)) {
8273
+ + let range = caught.range;
8274
+ + let type = Node.createNamedType(Node.createSimpleTypeName("Error", range), null, false, range);
8275
+ + locals.set(caught.text, Node.createVariableDeclaration(caught, null, CommonFlags.Let, type, null, range));
8276
+ + }
8043
8277
  + for (let i = 0, k = catchStatements.length; i < k; ++i) this.collectReturns(catchStatements[i], values, locals);
8044
8278
  + }
8045
8279
  + let finallyStatements = node.finallyStatements;
@@ -8119,7 +8353,7 @@ index 157351c..10c3f5c 100644
8119
8353
  parseIndexSignature(
8120
8354
  tn: Tokenizer,
8121
8355
  flags: CommonFlags,
8122
- @@ -2490,8 +3967,9 @@ export class Parser extends DiagnosticEmitter {
8356
+ @@ -2490,8 +3990,9 @@ export class Parser extends DiagnosticEmitter {
8123
8357
 
8124
8358
  let start = tn.tokenPos;
8125
8359
  if (tn.skipIdentifier()) {
@@ -8131,7 +8365,7 @@ index 157351c..10c3f5c 100644
8131
8365
  if (tn.skip(Token.Colon)) {
8132
8366
  let keyType = this.parseType(tn);
8133
8367
  if (!keyType) return null;
8134
- @@ -2506,13 +3984,6 @@ export class Parser extends DiagnosticEmitter {
8368
+ @@ -2506,13 +4007,6 @@ export class Parser extends DiagnosticEmitter {
8135
8369
  if (tn.skip(Token.Colon)) {
8136
8370
  let valueType = this.parseType(tn);
8137
8371
  if (!valueType) return null;
@@ -8145,7 +8379,7 @@ index 157351c..10c3f5c 100644
8145
8379
  return Node.createIndexSignature(<NamedTypeNode>keyType, valueType, flags, tn.range(start, tn.pos));
8146
8380
  } else {
8147
8381
  this.error(
8148
- @@ -2532,11 +4003,6 @@ export class Parser extends DiagnosticEmitter {
8382
+ @@ -2532,11 +4026,6 @@ export class Parser extends DiagnosticEmitter {
8149
8383
  tn.range(), ":"
8150
8384
  );
8151
8385
  }
@@ -8157,7 +8391,7 @@ index 157351c..10c3f5c 100644
8157
8391
  }
8158
8392
  } else {
8159
8393
  this.error(
8160
- @@ -2770,6 +4236,18 @@ export class Parser extends DiagnosticEmitter {
8394
+ @@ -2770,6 +4259,18 @@ export class Parser extends DiagnosticEmitter {
8161
8395
  let members: ImportDeclaration[] | null = null;
8162
8396
  let namespaceName: IdentifierExpression | null = null;
8163
8397
  let skipFrom = false;
@@ -8176,7 +8410,7 @@ index 157351c..10c3f5c 100644
8176
8410
  if (tn.skip(Token.OpenBrace)) { // import { ... } from "file"
8177
8411
  members = new Array();
8178
8412
  while (!tn.skip(Token.CloseBrace)) {
8179
- @@ -3026,6 +4504,15 @@ export class Parser extends DiagnosticEmitter {
8413
+ @@ -3026,6 +4527,15 @@ export class Parser extends DiagnosticEmitter {
8180
8414
  // fall-through
8181
8415
  }
8182
8416
  default: {
@@ -8192,7 +8426,7 @@ index 157351c..10c3f5c 100644
8192
8426
  tn.reset(state);
8193
8427
  statement = this.parseExpressionStatement(tn);
8194
8428
  break;
8195
- @@ -3153,17 +4640,114 @@ export class Parser extends DiagnosticEmitter {
8429
+ @@ -3153,17 +4663,114 @@ export class Parser extends DiagnosticEmitter {
8196
8430
  return ret;
8197
8431
  }
8198
8432
 
@@ -8309,7 +8543,7 @@ index 157351c..10c3f5c 100644
8309
8543
  if (tn.skip(Token.Const)) {
8310
8544
  initializer = this.parseVariable(tn, CommonFlags.Const, null, tn.tokenPos, true);
8311
8545
  } else if (tn.skip(Token.Let)) {
8312
- @@ -3291,7 +4875,7 @@ export class Parser extends DiagnosticEmitter {
8546
+ @@ -3291,7 +4898,7 @@ export class Parser extends DiagnosticEmitter {
8313
8547
  tn: Tokenizer,
8314
8548
  startPos: i32,
8315
8549
  variable: Statement,
@@ -8318,7 +8552,7 @@ index 157351c..10c3f5c 100644
8318
8552
 
8319
8553
  // at 'of': Expression ')' Statement
8320
8554
 
8321
- @@ -3308,15 +4892,87 @@ export class Parser extends DiagnosticEmitter {
8555
+ @@ -3308,15 +4915,87 @@ export class Parser extends DiagnosticEmitter {
8322
8556
 
8323
8557
  let statement = this.parseStatement(tn);
8324
8558
  if (!statement) return null;
@@ -8407,7 +8641,7 @@ index 157351c..10c3f5c 100644
8407
8641
  parseIfStatement(
8408
8642
  tn: Tokenizer
8409
8643
  ): IfStatement | null {
8410
- @@ -3496,27 +5152,27 @@ export class Parser extends DiagnosticEmitter {
8644
+ @@ -3496,27 +5175,27 @@ export class Parser extends DiagnosticEmitter {
8411
8645
  let catchStatements: Statement[] | null = null;
8412
8646
  let finallyStatements: Statement[] | null = null;
8413
8647
  if (tn.skip(Token.Catch)) {
@@ -8456,7 +8690,7 @@ index 157351c..10c3f5c 100644
8456
8690
  }
8457
8691
  if (!tn.skip(Token.OpenBrace)) {
8458
8692
  this.error(
8459
- @@ -3561,6 +5217,9 @@ export class Parser extends DiagnosticEmitter {
8693
+ @@ -3561,6 +5240,9 @@ export class Parser extends DiagnosticEmitter {
8460
8694
  finallyStatements,
8461
8695
  tn.range(startPos, tn.pos)
8462
8696
  );
@@ -8466,7 +8700,7 @@ index 157351c..10c3f5c 100644
8466
8700
  tn.skip(Token.Semicolon);
8467
8701
  return ret;
8468
8702
  } else {
8469
- @@ -3608,6 +5267,11 @@ export class Parser extends DiagnosticEmitter {
8703
+ @@ -3608,6 +5290,11 @@ export class Parser extends DiagnosticEmitter {
8470
8704
  type,
8471
8705
  tn.range(startPos, tn.pos)
8472
8706
  );
@@ -8478,7 +8712,7 @@ index 157351c..10c3f5c 100644
8478
8712
  tn.skip(Token.Semicolon);
8479
8713
  ret.overriddenModuleName = this.currentModuleName;
8480
8714
  return ret;
8481
- @@ -3694,6 +5358,19 @@ export class Parser extends DiagnosticEmitter {
8715
+ @@ -3694,6 +5381,19 @@ export class Parser extends DiagnosticEmitter {
8482
8716
  ): Expression | null {
8483
8717
  let token = tn.next(IdentifierHandling.Prefer);
8484
8718
  let startPos = tn.tokenPos;
@@ -8498,7 +8732,7 @@ index 157351c..10c3f5c 100644
8498
8732
  switch (token) {
8499
8733
 
8500
8734
  // TODO: SpreadExpression, YieldExpression
8501
- @@ -3712,6 +5389,51 @@ export class Parser extends DiagnosticEmitter {
8735
+ @@ -3712,6 +5412,51 @@ export class Parser extends DiagnosticEmitter {
8502
8736
  if (!operand) return null;
8503
8737
  return Node.createUnaryPrefixExpression(token, operand, tn.range(startPos, tn.pos));
8504
8738
  }
@@ -8550,7 +8784,7 @@ index 157351c..10c3f5c 100644
8550
8784
  case Token.Plus_Plus:
8551
8785
  case Token.Minus_Minus: {
8552
8786
  let operand = this.parseExpression(tn, Precedence.UnaryPrefix);
8553
- @@ -3752,6 +5474,9 @@ export class Parser extends DiagnosticEmitter {
8787
+ @@ -3752,6 +5497,9 @@ export class Parser extends DiagnosticEmitter {
8554
8788
  } else {
8555
8789
  arguments_ = []; // new Type;
8556
8790
  }
@@ -8560,7 +8794,7 @@ index 157351c..10c3f5c 100644
8560
8794
  return Node.createNewExpression(
8561
8795
  typeName,
8562
8796
  typeArguments,
8563
- @@ -3790,6 +5515,24 @@ export class Parser extends DiagnosticEmitter {
8797
+ @@ -3790,6 +5538,24 @@ export class Parser extends DiagnosticEmitter {
8564
8798
  tn.reset(state);
8565
8799
  return this.parseFunctionExpression(tn);
8566
8800
  }
@@ -8585,7 +8819,7 @@ index 157351c..10c3f5c 100644
8585
8819
  // can be both
8586
8820
  case Token.Identifier: {
8587
8821
  tn.readIdentifier();
8588
- @@ -3896,6 +5639,25 @@ export class Parser extends DiagnosticEmitter {
8822
+ @@ -3896,6 +5662,25 @@ export class Parser extends DiagnosticEmitter {
8589
8823
  let values = new Array<Expression>();
8590
8824
  let name: IdentifierExpression;
8591
8825
  while (!tn.skip(Token.CloseBrace)) {
@@ -8611,7 +8845,7 @@ index 157351c..10c3f5c 100644
8611
8845
  if (!tn.skipIdentifier()) {
8612
8846
  if (!tn.skip(Token.StringLiteral)) {
8613
8847
  this.error(
8614
- @@ -3914,6 +5676,17 @@ export class Parser extends DiagnosticEmitter {
8848
+ @@ -3914,6 +5699,17 @@ export class Parser extends DiagnosticEmitter {
8615
8849
  let value = this.parseExpression(tn, Precedence.Comma + 1);
8616
8850
  if (!value) return null;
8617
8851
  values.push(value);
@@ -8629,7 +8863,7 @@ index 157351c..10c3f5c 100644
8629
8863
  } else if (!name.isQuoted) {
8630
8864
  values.push(name);
8631
8865
  } else {
8632
- @@ -3935,7 +5708,10 @@ export class Parser extends DiagnosticEmitter {
8866
+ @@ -3935,7 +5731,10 @@ export class Parser extends DiagnosticEmitter {
8633
8867
  }
8634
8868
  }
8635
8869
  }
@@ -8641,7 +8875,7 @@ index 157351c..10c3f5c 100644
8641
8875
  }
8642
8876
  // AssertionExpression (unary prefix)
8643
8877
  case Token.LessThan: {
8644
- @@ -4129,20 +5905,32 @@ export class Parser extends DiagnosticEmitter {
8878
+ @@ -4129,20 +5928,32 @@ export class Parser extends DiagnosticEmitter {
8645
8879
  // see: http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm#climbing
8646
8880
  let nextPrecedence: Precedence;
8647
8881
  while (
@@ -8681,7 +8915,7 @@ index 157351c..10c3f5c 100644
8681
8915
  } else {
8682
8916
  let toType = this.parseType(tn); // reports
8683
8917
  if (!toType) return null;
8684
- @@ -4281,6 +6069,44 @@ export class Parser extends DiagnosticEmitter {
8918
+ @@ -4281,6 +6092,44 @@ export class Parser extends DiagnosticEmitter {
8685
8919
  }
8686
8920
  break;
8687
8921
  }
@@ -8726,7 +8960,7 @@ index 157351c..10c3f5c 100644
8726
8960
  // BinaryExpression (right associative)
8727
8961
  case Token.Equals:
8728
8962
  case Token.Plus_Equals:
8729
- @@ -4295,6 +6121,7 @@ export class Parser extends DiagnosticEmitter {
8963
+ @@ -4295,6 +6144,7 @@ export class Parser extends DiagnosticEmitter {
8730
8964
  case Token.Ampersand_Equals:
8731
8965
  case Token.Caret_Equals:
8732
8966
  case Token.Bar_Equals:
@@ -8734,7 +8968,7 @@ index 157351c..10c3f5c 100644
8734
8968
  case Token.Asterisk_Asterisk: {
8735
8969
  let next = this.parseExpression(tn, nextPrecedence);
8736
8970
  if (!next) return null;
8737
- @@ -4323,6 +6150,7 @@ export class Parser extends DiagnosticEmitter {
8971
+ @@ -4323,6 +6173,7 @@ export class Parser extends DiagnosticEmitter {
8738
8972
  case Token.Caret:
8739
8973
  case Token.Ampersand_Ampersand:
8740
8974
  case Token.Bar_Bar:
@@ -8742,7 +8976,7 @@ index 157351c..10c3f5c 100644
8742
8976
  case Token.In: {
8743
8977
  let next = this.parseExpression(tn, nextPrecedence + 1);
8744
8978
  if (!next) return null;
8745
- @@ -4335,6 +6163,26 @@ export class Parser extends DiagnosticEmitter {
8979
+ @@ -4335,6 +6186,26 @@ export class Parser extends DiagnosticEmitter {
8746
8980
  return expr;
8747
8981
  }
8748
8982
 
@@ -8769,7 +9003,7 @@ index 157351c..10c3f5c 100644
8769
9003
  private parseTemplateLiteral(tn: Tokenizer, tag: Expression | null = null): Expression | null {
8770
9004
  // at '`': ... '`'
8771
9005
  let startPos = tag ? tag.range.start : tn.tokenPos;
8772
- @@ -4569,9 +6417,11 @@ function determinePrecedence(kind: Token): Precedence {
9006
+ @@ -4569,9 +6440,11 @@ function determinePrecedence(kind: Token): Precedence {
8773
9007
  case Token.GreaterThan_GreaterThan_GreaterThan_Equals:
8774
9008
  case Token.Ampersand_Equals:
8775
9009
  case Token.Caret_Equals:
@@ -8783,7 +9017,7 @@ index 157351c..10c3f5c 100644
8783
9017
  case Token.Ampersand_Ampersand: return Precedence.LogicalAnd;
8784
9018
  case Token.Bar: return Precedence.BitwiseOr;
8785
9019
  case Token.Caret: return Precedence.BitwiseXor;
8786
- @@ -4599,6 +6449,7 @@ function determinePrecedence(kind: Token): Precedence {
9020
+ @@ -4599,6 +6472,7 @@ function determinePrecedence(kind: Token): Precedence {
8787
9021
  case Token.Plus_Plus:
8788
9022
  case Token.Minus_Minus: return Precedence.UnaryPostfix;
8789
9023
  case Token.Dot:
@@ -8791,7 +9025,7 @@ index 157351c..10c3f5c 100644
8791
9025
  case Token.OpenBracket:
8792
9026
  case Token.Exclamation: return Precedence.MemberAccess;
8793
9027
  }
8794
- @@ -4640,3 +6491,72 @@ function isCircularTypeAlias(name: string, type: TypeNode): bool {
9028
+ @@ -4640,3 +6514,72 @@ function isCircularTypeAlias(name: string, type: TypeNode): bool {
8795
9029
  }
8796
9030
  return false;
8797
9031
  }
@@ -9156,7 +9390,7 @@ index f5d9b7c..81527b0 100644
9156
9390
  + }
9157
9391
  +}
9158
9392
  diff --git a/src/resolver.ts b/src/resolver.ts
9159
- index 9576a47..d1fd13d 100644
9393
+ index 9576a47..3aa2e32 100644
9160
9394
  --- a/src/resolver.ts
9161
9395
  +++ b/src/resolver.ts
9162
9396
  @@ -36,7 +36,9 @@ import {
@@ -9463,7 +9697,7 @@ index 9576a47..d1fd13d 100644
9463
9697
  if (!argumentExpression) {
9464
9698
  // optional but not have initializer should be handled in the other place
9465
9699
  if (parameterNodes[i].parameterKind == ParameterKind.Optional) {
9466
- @@ -743,8 +913,33 @@ export class Resolver extends DiagnosticEmitter {
9700
+ @@ -743,8 +913,43 @@ export class Resolver extends DiagnosticEmitter {
9467
9701
  if (parameterNodes[i].parameterKind == ParameterKind.Rest) {
9468
9702
  typeNode = (<NamedTypeNode> typeNode).typeArguments![0];
9469
9703
  }
@@ -9475,6 +9709,7 @@ index 9576a47..d1fd13d 100644
9475
9709
  + (<LiteralExpression>argumentExpression).literalKind == LiteralKind.Object &&
9476
9710
  + !(<ObjectLiteralExpression>argumentExpression).inferredType
9477
9711
  + ) continue;
9712
+ + if (this.propagateTupleList(typeNode, argumentExpression, ctxFlow, prototype, contextualTypeArguments, typeParameterNames)) continue;
9478
9713
  if (typeNode.hasGenericComponent(typeParameterNodes)) {
9479
9714
  - let type = this.resolveExpression(argumentExpression, ctxFlow, Type.auto, ReportMode.Swallow);
9480
9715
  + // amxts: an arrow with untyped parameters needs a context to resolve
@@ -9484,9 +9719,18 @@ index 9576a47..d1fd13d 100644
9484
9719
  + let argumentContext = Type.auto;
9485
9720
  + if (argumentExpression.kind == NodeKind.Function && typeNode.kind == NodeKind.FunctionType) {
9486
9721
  + let functionNode = <FunctionTypeNode>typeNode;
9722
+ + // amxts: a parameter typed by a generic class of what is still being
9723
+ + // inferred - `MenuContext<Data>` in `new Menu(({ player }) => ...)` -
9724
+ + // stays unknown, and the type argument takes its default: a class of
9725
+ + // `auto` is no type, and resolving it comes back to this very node
9726
+ + // through the class's own members (Menu<Data> holds
9727
+ + // MenuContext<Data>), "Recursive types".
9728
+ + let unbound = typeParameterNodes.filter(each => contextualTypeArguments.get(each.name.text) == Type.auto);
9487
9729
  + let known = new Array<Type>();
9488
9730
  + for (let j = 0, l = functionNode.parameters.length; j < l; ++j) {
9489
- + let known1 = this.resolveType(functionNode.parameters[j].type, null, prototype, contextualTypeArguments, ReportMode.Swallow);
9731
+ + let parameterType = functionNode.parameters[j].type;
9732
+ + if (parameterType.kind == NodeKind.NamedType && (<NamedTypeNode>parameterType).hasTypeArguments && parameterType.hasGenericComponent(unbound)) break;
9733
+ + let known1 = this.resolveType(parameterType, null, prototype, contextualTypeArguments, ReportMode.Swallow);
9490
9734
  + if (!known1) break;
9491
9735
  + known.push(known1);
9492
9736
  + }
@@ -9498,7 +9742,53 @@ index 9576a47..d1fd13d 100644
9498
9742
  if (type) {
9499
9743
  this.propagateInferredGenericTypes(
9500
9744
  typeNode,
9501
- @@ -915,7 +1110,11 @@ export class Resolver extends DiagnosticEmitter {
9745
+ @@ -817,6 +1022,45 @@ export class Resolver extends DiagnosticEmitter {
9746
+ }
9747
+
9748
+ /** Updates contextual types with a possibly encapsulated inferred type. */
9749
+ + /**
9750
+ + * amxts: what an array literal of array literals says of a parameter of a
9751
+ + * list of tuples, `[K, V][]`, one element at a time: `new Map([["a", 1],
9752
+ + * ["b", 2]])` is a Map of string and number. Such a literal is a list of
9753
+ + * tuples only where one goes, and alone it has no type to infer from.
9754
+ + * False when the parameter or the argument is not of that kind.
9755
+ + */
9756
+ + private propagateTupleList(
9757
+ + typeNode: TypeNode,
9758
+ + argument: Expression,
9759
+ + ctxFlow: Flow,
9760
+ + ctxElement: Element,
9761
+ + ctxTypes: Map<string,Type>,
9762
+ + typeParameterNames: Set<string>
9763
+ + ): bool {
9764
+ + if (
9765
+ + typeNode.kind != NodeKind.NamedType ||
9766
+ + argument.kind != NodeKind.Literal ||
9767
+ + (<LiteralExpression>argument).literalKind != LiteralKind.Array
9768
+ + ) return false;
9769
+ + let list = <NamedTypeNode>typeNode;
9770
+ + let items = list.typeArguments;
9771
+ + if (list.name.identifier.text != "Array" || !items || items.length != 1 || items[0].kind != NodeKind.NamedType) return false;
9772
+ + let tuple = <NamedTypeNode>items[0];
9773
+ + let elementNodes = tuple.typeArguments;
9774
+ + if (!tuple.name.identifier.text.startsWith("__Tuple") || !elementNodes) return false;
9775
+ + let literals = (<ArrayLiteralExpression>argument).elementExpressions;
9776
+ + for (let i = 0, k = literals.length; i < k; ++i) {
9777
+ + let literal = literals[i];
9778
+ + if (literal.kind != NodeKind.Literal || (<LiteralExpression>literal).literalKind != LiteralKind.Array) continue;
9779
+ + let values = (<ArrayLiteralExpression>literal).elementExpressions;
9780
+ + for (let j = 0, l = min(values.length, elementNodes.length); j < l; ++j) {
9781
+ + let type = this.resolveExpression(values[j], ctxFlow, Type.auto, ReportMode.Swallow);
9782
+ + if (type) this.propagateInferredGenericTypes(elementNodes[j], type, ctxElement, ctxTypes, typeParameterNames);
9783
+ + }
9784
+ + }
9785
+ + return true;
9786
+ + }
9787
+ +
9788
+ private propagateInferredGenericTypes(
9789
+ /** The inferred type node. */
9790
+ node: TypeNode,
9791
+ @@ -915,7 +1159,11 @@ export class Resolver extends DiagnosticEmitter {
9502
9792
  let classReference = type.getClassOrWrapper(this.program);
9503
9793
  if (classReference) {
9504
9794
  let wrappedType = classReference.wrappedType;
@@ -9511,7 +9801,7 @@ index 9576a47..d1fd13d 100644
9511
9801
  }
9512
9802
  return type;
9513
9803
  }
9514
- @@ -1067,8 +1266,10 @@ export class Resolver extends DiagnosticEmitter {
9804
+ @@ -1067,8 +1315,10 @@ export class Resolver extends DiagnosticEmitter {
9515
9805
  const resolvingExpressions = this.resolvingExpressions;
9516
9806
  if (resolvingExpressions.has(node)) return null;
9517
9807
  resolvingExpressions.add(node);
@@ -9523,7 +9813,7 @@ index 9576a47..d1fd13d 100644
9523
9813
  return resolved;
9524
9814
  }
9525
9815
 
9526
- @@ -1253,6 +1454,19 @@ export class Resolver extends DiagnosticEmitter {
9816
+ @@ -1253,6 +1503,19 @@ export class Resolver extends DiagnosticEmitter {
9527
9817
  /** How to proceed with eventual diagnostics. */
9528
9818
  reportMode: ReportMode = ReportMode.Report
9529
9819
  ): Type | null {
@@ -9543,7 +9833,7 @@ index 9576a47..d1fd13d 100644
9543
9833
  switch (node.kind) {
9544
9834
  case NodeKind.True:
9545
9835
  case NodeKind.False: return Type.bool;
9546
- @@ -1434,6 +1648,12 @@ export class Resolver extends DiagnosticEmitter {
9836
+ @@ -1434,6 +1697,12 @@ export class Resolver extends DiagnosticEmitter {
9547
9837
  }
9548
9838
  }
9549
9839
 
@@ -9556,7 +9846,7 @@ index 9576a47..d1fd13d 100644
9556
9846
  // Look up the member within
9557
9847
  switch (target.kind) {
9558
9848
  case ElementKind.ClassPrototype:
9559
- @@ -1544,6 +1764,9 @@ export class Resolver extends DiagnosticEmitter {
9849
+ @@ -1544,6 +1813,9 @@ export class Resolver extends DiagnosticEmitter {
9560
9850
  /** How to proceed with eventual diagnostics. */
9561
9851
  reportMode: ReportMode = ReportMode.Report
9562
9852
  ): Element | null {
@@ -9566,7 +9856,7 @@ index 9576a47..d1fd13d 100644
9566
9856
  let targetExpression = node.expression;
9567
9857
  let targetType = this.resolveExpression(targetExpression, ctxFlow, ctxType, reportMode);
9568
9858
  if (!targetType) return null;
9569
- @@ -1579,6 +1802,8 @@ export class Resolver extends DiagnosticEmitter {
9859
+ @@ -1579,6 +1851,8 @@ export class Resolver extends DiagnosticEmitter {
9570
9860
  /** How to proceed with eventual diagnostics. */
9571
9861
  reportMode: ReportMode = ReportMode.Report
9572
9862
  ): Type | null {
@@ -9575,7 +9865,7 @@ index 9576a47..d1fd13d 100644
9575
9865
  let element = this.lookupElementAccessExpression(node, ctxFlow, ctxType, reportMode);
9576
9866
  if (!element) return null;
9577
9867
  let type = this.getTypeOfElement(element);
9578
- @@ -1624,6 +1849,9 @@ export class Resolver extends DiagnosticEmitter {
9868
+ @@ -1624,6 +1898,9 @@ export class Resolver extends DiagnosticEmitter {
9579
9869
  }
9580
9870
  intValue = i64_neg(intValue);
9581
9871
  }
@@ -9585,7 +9875,7 @@ index 9576a47..d1fd13d 100644
9585
9875
  if (ctxType.isValue) {
9586
9876
  // compile to contextual type if matching
9587
9877
  switch (ctxType.kind) {
9588
- @@ -1675,6 +1903,13 @@ export class Resolver extends DiagnosticEmitter {
9878
+ @@ -1675,6 +1952,13 @@ export class Resolver extends DiagnosticEmitter {
9589
9879
  case TypeKind.F64: return Type.f64;
9590
9880
  }
9591
9881
  }
@@ -9599,7 +9889,7 @@ index 9576a47..d1fd13d 100644
9599
9889
  // otherwise compile to best fitting type
9600
9890
  if (i64_is_i32(intValue)) return Type.i32;
9601
9891
  if (i64_is_u32(intValue)) return Type.u32;
9602
- @@ -1895,6 +2130,9 @@ export class Resolver extends DiagnosticEmitter {
9892
+ @@ -1895,6 +2179,9 @@ export class Resolver extends DiagnosticEmitter {
9603
9893
  case Token.TypeOf: {
9604
9894
  return this.program.stringInstance.type;
9605
9895
  }
@@ -9609,7 +9899,7 @@ index 9576a47..d1fd13d 100644
9609
9899
  default: assert(false);
9610
9900
  }
9611
9901
  return null;
9612
- @@ -2018,7 +2256,8 @@ export class Resolver extends DiagnosticEmitter {
9902
+ @@ -2018,7 +2305,8 @@ export class Resolver extends DiagnosticEmitter {
9613
9903
  case Token.GreaterThan_GreaterThan_GreaterThan_Equals:
9614
9904
  case Token.Ampersand_Equals:
9615
9905
  case Token.Bar_Equals:
@@ -9619,7 +9909,7 @@ index 9576a47..d1fd13d 100644
9619
9909
  return this.resolveExpression(left, ctxFlow, ctxType, reportMode);
9620
9910
  }
9621
9911
 
9622
- @@ -2091,6 +2330,11 @@ export class Resolver extends DiagnosticEmitter {
9912
+ @@ -2091,6 +2379,11 @@ export class Resolver extends DiagnosticEmitter {
9623
9913
  }
9624
9914
  let rightType = this.resolveExpression(right, ctxFlow, leftType, reportMode);
9625
9915
  if (!rightType) return null;
@@ -9631,7 +9921,7 @@ index 9576a47..d1fd13d 100644
9631
9921
  let commonType = Type.commonType(leftType, rightType, ctxType);
9632
9922
  if (!commonType) {
9633
9923
  if (reportMode == ReportMode.Report) {
9634
- @@ -2100,6 +2344,14 @@ export class Resolver extends DiagnosticEmitter {
9924
+ @@ -2100,6 +2393,14 @@ export class Resolver extends DiagnosticEmitter {
9635
9925
  );
9636
9926
  }
9637
9927
  }
@@ -9646,7 +9936,7 @@ index 9576a47..d1fd13d 100644
9646
9936
  return commonType;
9647
9937
  }
9648
9938
 
9649
- @@ -2115,6 +2367,10 @@ export class Resolver extends DiagnosticEmitter {
9939
+ @@ -2115,6 +2416,10 @@ export class Resolver extends DiagnosticEmitter {
9650
9940
  let overload = classReference.lookupOverload(OperatorKind.fromBinaryToken(operator));
9651
9941
  if (overload) return overload.signature.returnType;
9652
9942
  }
@@ -9657,7 +9947,7 @@ index 9576a47..d1fd13d 100644
9657
9947
  if (!leftType.isIntegerValue) {
9658
9948
  if (reportMode == ReportMode.Report) {
9659
9949
  this.error(
9660
- @@ -2141,6 +2397,9 @@ export class Resolver extends DiagnosticEmitter {
9950
+ @@ -2141,6 +2446,9 @@ export class Resolver extends DiagnosticEmitter {
9661
9951
  }
9662
9952
  let rightType = this.resolveExpression(right, ctxFlow, ctxType, reportMode);
9663
9953
  if (!rightType) return null;
@@ -9667,7 +9957,7 @@ index 9576a47..d1fd13d 100644
9667
9957
  let commonType = Type.commonType(leftType, rightType, ctxType);
9668
9958
  if (!commonType || !commonType.isIntegerValue) {
9669
9959
  if (reportMode == ReportMode.Report) {
9670
- @@ -2191,6 +2450,25 @@ export class Resolver extends DiagnosticEmitter {
9960
+ @@ -2191,6 +2499,25 @@ export class Resolver extends DiagnosticEmitter {
9671
9961
  ? commonType
9672
9962
  : commonType.nonNullableType;
9673
9963
  }
@@ -9693,7 +9983,7 @@ index 9576a47..d1fd13d 100644
9693
9983
  }
9694
9984
  assert(false);
9695
9985
  return null;
9696
- @@ -2215,6 +2493,15 @@ export class Resolver extends DiagnosticEmitter {
9986
+ @@ -2215,6 +2542,15 @@ export class Resolver extends DiagnosticEmitter {
9697
9987
  return thisLocal;
9698
9988
  }
9699
9989
  }
@@ -9709,7 +9999,7 @@ index 9576a47..d1fd13d 100644
9709
9999
  let parent = ctxFlow.sourceFunction.parent;
9710
10000
  if (parent) {
9711
10001
  this.currentThisExpression = null;
9712
- @@ -2274,6 +2561,16 @@ export class Resolver extends DiagnosticEmitter {
10002
+ @@ -2274,6 +2610,16 @@ export class Resolver extends DiagnosticEmitter {
9713
10003
  return superLocal;
9714
10004
  }
9715
10005
  }
@@ -9726,7 +10016,7 @@ index 9576a47..d1fd13d 100644
9726
10016
  let parent: Element | null = ctxFlow.sourceFunction.parent;
9727
10017
  if (parent && parent.kind == ElementKind.Class) {
9728
10018
  let base = (<Class>parent).base;
9729
- @@ -2351,6 +2648,12 @@ export class Resolver extends DiagnosticEmitter {
10019
+ @@ -2351,6 +2697,12 @@ export class Resolver extends DiagnosticEmitter {
9730
10020
  return this.program.regexpInstance;
9731
10021
  }
9732
10022
  case LiteralKind.Array: {
@@ -9739,7 +10029,7 @@ index 9576a47..d1fd13d 100644
9739
10029
  let classReference = ctxType.getClass();
9740
10030
  if (classReference && classReference.prototype == this.program.arrayPrototype) {
9741
10031
  return this.getElementOfType(ctxType);
9742
- @@ -2400,6 +2703,13 @@ export class Resolver extends DiagnosticEmitter {
10032
+ @@ -2400,6 +2752,13 @@ export class Resolver extends DiagnosticEmitter {
9743
10033
  }
9744
10034
  case LiteralKind.Object: {
9745
10035
  if (ctxType.isClass) return ctxType.classReference;
@@ -9753,7 +10043,7 @@ index 9576a47..d1fd13d 100644
9753
10043
  if (reportMode == ReportMode.Report) {
9754
10044
  this.error(
9755
10045
  DiagnosticCode.Expression_cannot_be_represented_by_a_type,
9756
- @@ -2474,6 +2784,24 @@ export class Resolver extends DiagnosticEmitter {
10046
+ @@ -2474,6 +2833,24 @@ export class Resolver extends DiagnosticEmitter {
9757
10047
  /** How to proceed with eventual diagnostics. */
9758
10048
  reportMode: ReportMode = ReportMode.Report
9759
10049
  ): Type | null {
@@ -9778,7 +10068,7 @@ index 9576a47..d1fd13d 100644
9778
10068
  let targetExpression = node.expression;
9779
10069
  let target = this.lookupExpression( // reports
9780
10070
  targetExpression,
9781
- @@ -2623,6 +2951,12 @@ export class Resolver extends DiagnosticEmitter {
10071
+ @@ -2623,6 +3000,12 @@ export class Resolver extends DiagnosticEmitter {
9782
10072
  /** How to proceed with eventual diagnostics. */
9783
10073
  reportMode: ReportMode = ReportMode.Report
9784
10074
  ): Type | null {
@@ -9791,7 +10081,7 @@ index 9576a47..d1fd13d 100644
9791
10081
  let thenType = this.resolveExpression(node.ifThen, ctxFlow, ctxType, reportMode);
9792
10082
  if (!thenType) return null;
9793
10083
  let elseType = this.resolveExpression(node.ifElse, ctxFlow, thenType, reportMode);
9794
- @@ -2736,18 +3070,119 @@ export class Resolver extends DiagnosticEmitter {
10084
+ @@ -2736,18 +3119,129 @@ export class Resolver extends DiagnosticEmitter {
9795
10085
  const declaration = node.declaration;
9796
10086
  const signature = declaration.signature;
9797
10087
  const body = declaration.body;
@@ -9839,23 +10129,33 @@ index 9576a47..d1fd13d 100644
9839
10129
  + // its untyped parameters from that type, as TypeScript's contextual typing
9840
10130
  + // does - which is how game.addEventListener("x", (event) => answer) learns
9841
10131
  + // what the listener returns, and from it the generic R.
10132
+ + // amxts: and an arrow's return type left out is read off its body below,
10133
+ + // `[() => log(1)]` too - no error for it here, where it is void until then.
9842
10134
  + let ctxSignature = ctxType.getSignature();
9843
10135
  + let untyped = false;
9844
10136
  + for (let i = 0, k = signature.parameters.length; i < k; ++i) {
9845
10137
  + if (isTypeOmitted(signature.parameters[i].type)) untyped = true;
9846
10138
  + }
10139
+ + let returnInferred = declaration.arrowKind != ArrowKind.None && isTypeOmitted(signature.returnType);
9847
10140
  + let functionType: Type | null = null;
9848
- + if (untyped && ctxSignature && ctxSignature.parameterTypes.length >= signature.parameters.length) {
10141
+ + if (
10142
+ + untyped ? ctxSignature != null && ctxSignature.parameterTypes.length >= signature.parameters.length : returnInferred
10143
+ + ) {
9849
10144
  + let parameterTypes = new Array<Type>(signature.parameters.length);
10145
+ + let requiredParameters = 0;
10146
+ + let hasRest = false;
9850
10147
  + for (let i = 0, k = signature.parameters.length; i < k; ++i) {
9851
- + let typeNode = signature.parameters[i].type;
10148
+ + let parameter = signature.parameters[i];
10149
+ + if (parameter.parameterKind == ParameterKind.Default) requiredParameters = i + 1;
10150
+ + else if (parameter.parameterKind == ParameterKind.Rest) hasRest = true;
10151
+ + let typeNode = parameter.type;
9852
10152
  + let type = isTypeOmitted(typeNode)
9853
- + ? ctxSignature.parameterTypes[i]
10153
+ + ? ctxSignature!.parameterTypes[i]
9854
10154
  + : this.resolveType(typeNode, null, ctxFlow.sourceFunction, ctxFlow.contextualTypeArguments, reportMode);
9855
10155
  + if (!type) return null;
9856
10156
  + parameterTypes[i] = type;
9857
10157
  + }
9858
- + functionType = Signature.create(this.program, parameterTypes, Type.void, null, parameterTypes.length, false).type;
10158
+ + functionType = Signature.create(this.program, parameterTypes, Type.void, null, requiredParameters, hasRest).type;
9859
10159
  + } else {
9860
10160
  + functionType = this.resolveType(signature, null, ctxFlow.sourceFunction, ctxFlow.contextualTypeArguments, reportMode);
9861
10161
  + }
@@ -9914,7 +10214,7 @@ index 9576a47..d1fd13d 100644
9914
10214
  let parameters = signature.parameters;
9915
10215
  // return type of resolveFunctionType should have same parameter length with signature
9916
10216
  assert(signatureReference.parameterTypes.length == parameters.length);
9917
- @@ -2756,16 +3191,57 @@ export class Resolver extends DiagnosticEmitter {
10217
+ @@ -2756,16 +3250,57 @@ export class Resolver extends DiagnosticEmitter {
9918
10218
  const type = signatureReference.parameterTypes[i];
9919
10219
  tempFlow.addScopedDummyLocal(parameter.name.text, type, parameter);
9920
10220
  }
@@ -9975,7 +10275,7 @@ index 9576a47..d1fd13d 100644
9975
10275
  }
9976
10276
  }
9977
10277
  return functionType;
9978
- @@ -2870,13 +3346,17 @@ export class Resolver extends DiagnosticEmitter {
10278
+ @@ -2870,13 +3405,17 @@ export class Resolver extends DiagnosticEmitter {
9979
10279
  }
9980
10280
  return null;
9981
10281
  }
@@ -10000,7 +10300,7 @@ index 9576a47..d1fd13d 100644
10000
10300
  if (!parameterType) return null;
10001
10301
  if (parameterType == Type.void) {
10002
10302
  if (reportMode == ReportMode.Report) {
10003
- @@ -2891,14 +3371,73 @@ export class Resolver extends DiagnosticEmitter {
10303
+ @@ -2891,14 +3430,73 @@ export class Resolver extends DiagnosticEmitter {
10004
10304
  }
10005
10305
 
10006
10306
  // resolve return type
@@ -10076,7 +10376,7 @@ index 9576a47..d1fd13d 100644
10076
10376
  if (reportMode == ReportMode.Report) {
10077
10377
  this.error(
10078
10378
  DiagnosticCode.Type_expected,
10079
- @@ -2906,7 +3445,7 @@ export class Resolver extends DiagnosticEmitter {
10379
+ @@ -2906,7 +3504,7 @@ export class Resolver extends DiagnosticEmitter {
10080
10380
  );
10081
10381
  }
10082
10382
  return null;
@@ -10085,7 +10385,7 @@ index 9576a47..d1fd13d 100644
10085
10385
  let type = this.resolveType(
10086
10386
  typeNode,
10087
10387
  null,
10088
- @@ -2916,6 +3455,7 @@ export class Resolver extends DiagnosticEmitter {
10388
+ @@ -2916,6 +3514,7 @@ export class Resolver extends DiagnosticEmitter {
10089
10389
  );
10090
10390
  if (!type) return null;
10091
10391
  returnType = type;
@@ -10093,7 +10393,7 @@ index 9576a47..d1fd13d 100644
10093
10393
  }
10094
10394
 
10095
10395
  let signature = Signature.create(this.program, parameterTypes, returnType, thisType, requiredParameters, hasRest);
10096
- @@ -3041,7 +3581,8 @@ export class Resolver extends DiagnosticEmitter {
10396
+ @@ -3041,7 +3640,8 @@ export class Resolver extends DiagnosticEmitter {
10097
10397
  ctxElement,
10098
10398
  ctxTypes, // update
10099
10399
  reportNode,
@@ -10103,7 +10403,7 @@ index 9576a47..d1fd13d 100644
10103
10403
  );
10104
10404
  if (!resolvedTypeArguments) return null;
10105
10405
 
10106
- @@ -3089,7 +3630,7 @@ export class Resolver extends DiagnosticEmitter {
10406
+ @@ -3089,7 +3689,7 @@ export class Resolver extends DiagnosticEmitter {
10107
10407
  for (let _values = Map_values(classInstances), j = 0, l = _values.length; j < l; ++j) {
10108
10408
  let classInstance = _values[j];
10109
10409
  // Check if the parent class is a subtype of instance's class
@@ -10112,7 +10412,7 @@ index 9576a47..d1fd13d 100644
10112
10412
  let overrideInstance: Function | null = null;
10113
10413
  if (instance.isAny(CommonFlags.Get | CommonFlags.Set)) {
10114
10414
  let propertyName = instance.declaration.name.text;
10115
- @@ -3125,6 +3666,21 @@ export class Resolver extends DiagnosticEmitter {
10415
+ @@ -3125,6 +3725,21 @@ export class Resolver extends DiagnosticEmitter {
10116
10416
  return Set_values(overrides);
10117
10417
  }
10118
10418
 
@@ -10134,7 +10434,7 @@ index 9576a47..d1fd13d 100644
10134
10434
  /** Currently resolving classes. */
10135
10435
  private resolveClassPending: Set<Class> = new Set();
10136
10436
 
10137
- @@ -3139,6 +3695,13 @@ export class Resolver extends DiagnosticEmitter {
10437
+ @@ -3139,6 +3754,13 @@ export class Resolver extends DiagnosticEmitter {
10138
10438
  /** How to proceed with eventual diagnostics. */
10139
10439
  reportMode: ReportMode = ReportMode.Report
10140
10440
  ): Class | null {
@@ -10148,7 +10448,7 @@ index 9576a47..d1fd13d 100644
10148
10448
  let instanceKey = typeArguments ? typesToString(typeArguments) : "";
10149
10449
 
10150
10450
  // Do not attempt to resolve the same class twice. This can return a class
10151
- @@ -3416,6 +3979,10 @@ export class Resolver extends DiagnosticEmitter {
10451
+ @@ -3416,6 +4038,10 @@ export class Resolver extends DiagnosticEmitter {
10152
10452
  }
10153
10453
 
10154
10454
  // Resolve instance members
@@ -10159,7 +10459,7 @@ index 9576a47..d1fd13d 100644
10159
10459
  let prototype = instance.prototype;
10160
10460
  let instanceMemberPrototypes = prototype.instanceMembers;
10161
10461
  if (instanceMemberPrototypes) {
10162
- @@ -3465,18 +4032,12 @@ export class Resolver extends DiagnosticEmitter {
10462
+ @@ -3465,18 +4091,12 @@ export class Resolver extends DiagnosticEmitter {
10163
10463
  break; // keep existing
10164
10464
  }
10165
10465
  boundInstance.memoryOffset = existingProperty.memoryOffset;
@@ -10180,7 +10480,7 @@ index 9576a47..d1fd13d 100644
10180
10480
  boundPrototype.instance = boundInstance;
10181
10481
  instance.add(boundPrototype.name, boundPrototype); // reports
10182
10482
  // field materializes here, so check for supported type early
10183
- @@ -3500,6 +4061,31 @@ export class Resolver extends DiagnosticEmitter {
10483
+ @@ -3500,6 +4120,31 @@ export class Resolver extends DiagnosticEmitter {
10184
10484
  }
10185
10485
  }
10186
10486
 
@@ -10212,7 +10512,7 @@ index 9576a47..d1fd13d 100644
10212
10512
  if (instance.kind != ElementKind.Interface) {
10213
10513
 
10214
10514
  // Check that all required members are implemented
10215
- @@ -3675,7 +4261,8 @@ export class Resolver extends DiagnosticEmitter {
10515
+ @@ -3675,7 +4320,8 @@ export class Resolver extends DiagnosticEmitter {
10216
10516
  ctxElement,
10217
10517
  ctxTypes, // update
10218
10518
  reportNode,
@@ -10222,7 +10522,7 @@ index 9576a47..d1fd13d 100644
10222
10522
  );
10223
10523
  }
10224
10524
 
10225
- @@ -3749,6 +4336,1009 @@ export class Resolver extends DiagnosticEmitter {
10525
+ @@ -3749,6 +4395,1009 @@ export class Resolver extends DiagnosticEmitter {
10226
10526
  return instance;
10227
10527
  }
10228
10528
 
@@ -11176,7 +11476,7 @@ index 9576a47..d1fd13d 100644
11176
11476
  + let callee = (<CallExpression>value).expression;
11177
11477
  + if (callee.kind == NodeKind.Identifier && (<IdentifierExpression>callee).text == prototype.name) continue;
11178
11478
  + }
11179
- + // `if (player == null) return Player.all(); return [player];` - an
11479
+ + // `if (player == null) return server.players; return [player];` - an
11180
11480
  + // array literal after another return takes that return's type, as its
11181
11481
  + // elements would in TypeScript once narrowed; the body's own compile
11182
11482
  + // still checks each element against it.
@@ -11232,7 +11532,7 @@ index 9576a47..d1fd13d 100644
11232
11532
  ensureOneTypeArgument(
11233
11533
  /** The type to resolve. */
11234
11534
  node: NamedTypeNode,
11235
- @@ -3769,3 +5359,55 @@ export class Resolver extends DiagnosticEmitter {
11535
+ @@ -3769,3 +5418,55 @@ export class Resolver extends DiagnosticEmitter {
11236
11536
  return typeArgumentNodes[0];
11237
11537
  }
11238
11538
  }
@@ -11525,6 +11825,54 @@ index 85c59ff..203868e 100644
11525
11825
  }
11526
11826
 
11527
11827
  export declare namespace console {
11828
+ diff --git a/std/assembly/console.ts b/std/assembly/console.ts
11829
+ index 26a18a4..73426b9 100644
11830
+ --- a/std/assembly/console.ts
11831
+ +++ b/std/assembly/console.ts
11832
+ @@ -8,24 +8,33 @@ export namespace console {
11833
+ binding.assert(!!condition, message);
11834
+ }
11835
+
11836
+ - export function log(message: string = ""): void {
11837
+ - binding.log(message);
11838
+ + // amxts: a string, or an Error - written as its stack, as JavaScript's console does
11839
+ + export function log<T = string>(message: T = changetype<T>("")): void {
11840
+ + binding.log(text<T>(message));
11841
+ }
11842
+
11843
+ - export function debug(message: string = ""): void {
11844
+ - binding.debug(message);
11845
+ + export function debug<T = string>(message: T = changetype<T>("")): void {
11846
+ + binding.debug(text<T>(message));
11847
+ }
11848
+
11849
+ - export function info(message: string = ""): void {
11850
+ - binding.info(message);
11851
+ + export function info<T = string>(message: T = changetype<T>("")): void {
11852
+ + binding.info(text<T>(message));
11853
+ }
11854
+
11855
+ - export function warn(message: string = ""): void {
11856
+ - binding.warn(message);
11857
+ + export function warn<T = string>(message: T = changetype<T>("")): void {
11858
+ + binding.warn(text<T>(message));
11859
+ }
11860
+
11861
+ - export function error(message: string = ""): void {
11862
+ - binding.error(message);
11863
+ + export function error<T = string>(message: T = changetype<T>("")): void {
11864
+ + binding.error(text<T>(message));
11865
+ + }
11866
+ +
11867
+ + // @ts-ignore: decorator
11868
+ + @inline function text<T>(message: T): string {
11869
+ + if (isString<T>()) return changetype<string>(message);
11870
+ + if (isReference<T>() && !isNullable<T>() && message instanceof Error) return changetype<Error>(message).stack;
11871
+ + ERROR("console takes a string or an Error");
11872
+ + return "";
11873
+ }
11874
+
11875
+ export function time(label: string = "default"): void {
11528
11876
  diff --git a/std/assembly/date.ts b/std/assembly/date.ts
11529
11877
  index 7d273e1..abdb34d 100644
11530
11878
  --- a/std/assembly/date.ts
@@ -11787,10 +12135,60 @@ index 7d273e1..abdb34d 100644
11787
12135
  + return LOCALE_GB;
11788
12136
  +}
11789
12137
  diff --git a/std/assembly/error.ts b/std/assembly/error.ts
11790
- index f4ea058..5f6e74c 100644
12138
+ index f4ea058..a52176c 100644
11791
12139
  --- a/std/assembly/error.ts
11792
12140
  +++ b/std/assembly/error.ts
11793
- @@ -29,6 +29,14 @@ export class TypeError extends Error {
12141
+ @@ -1,12 +1,24 @@
12142
+ export class Error {
12143
+
12144
+ name: string = "Error";
12145
+ - stack: string = ""; // TODO
12146
+ +
12147
+ + // amxts: the calls that made it, as the host keeps them, for `stack`
12148
+ + /** @hidden */
12149
+ + __frames: StaticArray<u32> | null = __errorStack ? changetype<ErrorStack>(__errorStack).frames() : null;
12150
+
12151
+ constructor(
12152
+ public message: string = ""
12153
+ ) {}
12154
+
12155
+ + /** amxts: the error and where it was made, a call a line, as JavaScript writes it. */
12156
+ + get stack(): string {
12157
+ + let hook = __errorStack;
12158
+ + let frames = this.__frames;
12159
+ + if (!hook || !frames) return this.toString();
12160
+ + let calls = hook.text(frames);
12161
+ + return calls.length ? this.toString() + "\n" + calls : this.toString();
12162
+ + }
12163
+ +
12164
+ toString(): string {
12165
+ let message = this.message;
12166
+ return message.length
12167
+ @@ -15,6 +27,23 @@ export class Error {
12168
+ }
12169
+ }
12170
+
12171
+ +/**
12172
+ + * @hidden amxts: what an error's `stack` is made of - the frames of the calls
12173
+ + * that made it, then their words - which only the host the plugin runs on
12174
+ + * has. The hood sets it (as/facade.ts); without it `stack` is the error's
12175
+ + * first line alone.
12176
+ + */
12177
+ +export abstract class ErrorStack {
12178
+ + /** The frames of the calls running now. */
12179
+ + abstract frames(): StaticArray<u32>;
12180
+ + /** `frames` as lines: " at name (file:line:column)". */
12181
+ + abstract text(frames: StaticArray<u32>): string;
12182
+ +}
12183
+ +
12184
+ +/** @hidden see ErrorStack. */
12185
+ +// @ts-ignore: decorator
12186
+ +@lazy export let __errorStack: ErrorStack | null = null;
12187
+ +
12188
+ export class RangeError extends Error {
12189
+ constructor(message: string = "") {
12190
+ super(message);
12191
+ @@ -29,6 +58,14 @@ export class TypeError extends Error {
11794
12192
  }
11795
12193
  }
11796
12194
 
@@ -11805,7 +12203,7 @@ index f4ea058..5f6e74c 100644
11805
12203
  export class SyntaxError extends Error {
11806
12204
  constructor(message: string = "") {
11807
12205
  super(message);
11808
- @@ -42,3 +50,34 @@ export class URIError extends Error {
12206
+ @@ -42,3 +79,34 @@ export class URIError extends Error {
11809
12207
  this.name = "URIError";
11810
12208
  }
11811
12209
  }
@@ -11830,7 +12228,7 @@ index f4ea058..5f6e74c 100644
11830
12228
  + __thrown = error;
11831
12229
  + return true;
11832
12230
  + }
11833
- + abort(error.message, fileName, lineNumber, columnNumber);
12231
+ + abort(error.toString(), fileName, lineNumber, columnNumber);
11834
12232
  + return false;
11835
12233
  +}
11836
12234
  +
@@ -11841,7 +12239,7 @@ index f4ea058..5f6e74c 100644
11841
12239
  + return error;
11842
12240
  +}
11843
12241
  diff --git a/std/assembly/function.ts b/std/assembly/function.ts
11844
- index dd32696..5087e0d 100644
12242
+ index dd32696..5e6d083 100644
11845
12243
  --- a/std/assembly/function.ts
11846
12244
  +++ b/std/assembly/function.ts
11847
12245
  @@ -6,6 +6,11 @@ type auto = i32;
@@ -11856,7 +12254,7 @@ index dd32696..5087e0d 100644
11856
12254
  return load<u32>(changetype<usize>(this), offsetof<Function<T>>("_index"));
11857
12255
  }
11858
12256
 
11859
- @@ -36,3 +41,115 @@ type auto = i32;
12257
+ @@ -36,3 +41,125 @@ type auto = i32;
11860
12258
  __visit(this._env, cookie);
11861
12259
  }
11862
12260
  }
@@ -11972,6 +12370,16 @@ index dd32696..5087e0d 100644
11972
12370
  + const fn: F = () => text;
11973
12371
  + return fn;
11974
12372
  +}
12373
+ +
12374
+ +/**
12375
+ + * amxts: a boolean given where `boolean | (...) => boolean` is declared - held
12376
+ + * as the function, so a boolean becomes one that returns it
12377
+ + * (Compiler.compileText).
12378
+ + */
12379
+ +export function __boolFunction<F>(value: bool): F {
12380
+ + const fn: F = () => value;
12381
+ + return fn;
12382
+ +}
11975
12383
  diff --git a/std/assembly/index.d.ts b/std/assembly/index.d.ts
11976
12384
  index a604397..dd80104 100644
11977
12385
  --- a/std/assembly/index.d.ts
@@ -12530,7 +12938,7 @@ index 0000000..7eaa4f6
12530
12938
  + }
12531
12939
  +}
12532
12940
  diff --git a/std/assembly/map.ts b/std/assembly/map.ts
12533
- index ab7302f..7e96401 100644
12941
+ index ab7302f..3f17444 100644
12534
12942
  --- a/std/assembly/map.ts
12535
12943
  +++ b/std/assembly/map.ts
12536
12944
  @@ -2,6 +2,7 @@
@@ -12541,7 +12949,7 @@ index ab7302f..7e96401 100644
12541
12949
 
12542
12950
  // A deterministic hash map based on CloseTable from https://github.com/jorendorff/dht
12543
12951
 
12544
- @@ -61,7 +62,7 @@ export class Map<K,V> {
12952
+ @@ -61,13 +62,19 @@ export class Map<K,V> {
12545
12953
  private bucketsMask: u32 = INITIAL_CAPACITY - 1;
12546
12954
 
12547
12955
  // entries in insertion order, MapEntry<K,V>[entriesCapacity]
@@ -12550,7 +12958,21 @@ index ab7302f..7e96401 100644
12550
12958
  private entriesCapacity: i32 = INITIAL_CAPACITY;
12551
12959
  private entriesOffset: i32 = 0;
12552
12960
  private entriesCount: i32 = 0;
12553
- @@ -77,7 +78,7 @@ export class Map<K,V> {
12961
+
12962
+ - constructor() {
12963
+ - /* nop */
12964
+ + /** amxts: `new Map(entries)` sets the `[key, value]` entries in their order, as JavaScript's Map does. */
12965
+ + constructor(entries: __Tuple2<K,V>[] | null = null) {
12966
+ + if (entries) {
12967
+ + for (let i = 0, k = entries.length; i < k; ++i) {
12968
+ + let entry = unchecked(entries[i]);
12969
+ + this.set(entry._0, entry._1);
12970
+ + }
12971
+ + }
12972
+ }
12973
+
12974
+ get size(): i32 {
12975
+ @@ -77,7 +84,7 @@ export class Map<K,V> {
12554
12976
  clear(): void {
12555
12977
  this.buckets = new ArrayBuffer(INITIAL_CAPACITY * <i32>BUCKET_SIZE);
12556
12978
  this.bucketsMask = INITIAL_CAPACITY - 1;
@@ -12559,7 +12981,7 @@ index ab7302f..7e96401 100644
12559
12981
  this.entriesCapacity = INITIAL_CAPACITY;
12560
12982
  this.entriesOffset = 0;
12561
12983
  this.entriesCount = 0;
12562
- @@ -106,6 +107,17 @@ export class Map<K,V> {
12984
+ @@ -106,6 +113,17 @@ export class Map<K,V> {
12563
12985
  return entry.value;
12564
12986
  }
12565
12987
 
@@ -12577,7 +12999,7 @@ index ab7302f..7e96401 100644
12577
12999
  @operator("[]=")
12578
13000
  set(key: K, value: V): this {
12579
13001
  let hashCode = HASH<K>(key);
12580
- @@ -125,7 +137,7 @@ export class Map<K,V> {
13002
+ @@ -125,7 +143,7 @@ export class Map<K,V> {
12581
13003
  );
12582
13004
  }
12583
13005
  // append new entry
@@ -12586,7 +13008,7 @@ index ab7302f..7e96401 100644
12586
13008
  entry = changetype<MapEntry<K,V>>(changetype<usize>(entries) + <usize>(this.entriesOffset++) * ENTRY_SIZE<K,V>());
12587
13009
  // link with the map
12588
13010
  entry.key = key;
12589
- @@ -166,7 +178,7 @@ export class Map<K,V> {
13011
+ @@ -166,7 +184,7 @@ export class Map<K,V> {
12590
13012
  let newEntries = new ArrayBuffer(newEntriesCapacity * <i32>ENTRY_SIZE<K,V>());
12591
13013
 
12592
13014
  // copy old entries to new entries
@@ -12595,7 +13017,7 @@ index ab7302f..7e96401 100644
12595
13017
  let oldEnd = oldPtr + <usize>this.entriesOffset * ENTRY_SIZE<K,V>();
12596
13018
  let newPtr = changetype<usize>(newEntries);
12597
13019
  while (oldPtr != oldEnd) {
12598
- @@ -187,14 +199,14 @@ export class Map<K,V> {
13020
+ @@ -187,14 +205,14 @@ export class Map<K,V> {
12599
13021
 
12600
13022
  this.buckets = newBuckets;
12601
13023
  this.bucketsMask = newBucketsMask;
@@ -12612,7 +13034,7 @@ index ab7302f..7e96401 100644
12612
13034
  let size = this.entriesOffset;
12613
13035
  let keys = new Array<K>(size);
12614
13036
  let length = 0;
12615
- @@ -210,7 +222,7 @@ export class Map<K,V> {
13037
+ @@ -210,7 +228,7 @@ export class Map<K,V> {
12616
13038
 
12617
13039
  values(): V[] {
12618
13040
  // FIXME: this is preliminary, needs iterators/closures
@@ -12621,7 +13043,7 @@ index ab7302f..7e96401 100644
12621
13043
  let size = this.entriesOffset;
12622
13044
  let values = new Array<V>(size);
12623
13045
  let length = 0;
12624
- @@ -224,6 +236,29 @@ export class Map<K,V> {
13046
+ @@ -224,6 +242,29 @@ export class Map<K,V> {
12625
13047
  return values;
12626
13048
  }
12627
13049
 
@@ -12651,7 +13073,7 @@ index ab7302f..7e96401 100644
12651
13073
  toString(): string {
12652
13074
  return "[object Map]";
12653
13075
  }
12654
- @@ -232,7 +267,7 @@ export class Map<K,V> {
13076
+ @@ -232,7 +273,7 @@ export class Map<K,V> {
12655
13077
 
12656
13078
  @unsafe private __visit(cookie: u32): void {
12657
13079
  __visit(changetype<usize>(this.buckets), cookie);
@@ -12660,7 +13082,7 @@ index ab7302f..7e96401 100644
12660
13082
  if (isManaged<K>() || isManaged<V>()) {
12661
13083
  let cur = entries;
12662
13084
  let end = cur + <usize>this.entriesOffset * ENTRY_SIZE<K,V>();
12663
- @@ -258,3 +293,92 @@ export class Map<K,V> {
13085
+ @@ -258,3 +299,92 @@ export class Map<K,V> {
12664
13086
  __visit(entries, cookie);
12665
13087
  }
12666
13088
  }
@@ -12754,10 +13176,30 @@ index ab7302f..7e96401 100644
12754
13176
  + }
12755
13177
  +}
12756
13178
  diff --git a/std/assembly/math.ts b/std/assembly/math.ts
12757
- index e93837b..e61947b 100644
13179
+ index e93837b..bdf5633 100644
12758
13180
  --- a/std/assembly/math.ts
12759
13181
  +++ b/std/assembly/math.ts
12760
- @@ -3287,3 +3287,25 @@ switch (e) {
13182
+ @@ -1592,6 +1592,19 @@ export namespace NativeMath {
13183
+ }
13184
+
13185
+ export function mod(x: f64, y: f64): f64 { // see: musl/src/math/fmod.c
13186
+ + // amxts: a plugin's whole numbers are f64, and `n % d` of two of them
13187
+ + // within i32 is i32's remainder, which takes the dividend's sign as
13188
+ + // JavaScript's does; a zero keeps the dividend's sign (-4 % 2 is -0).
13189
+ + // NaN, infinities, fractions, a zero divisor and larger numbers go on
13190
+ + // to the general remainder below.
13191
+ + if (builtin_abs<f64>(x) < 2147483648.0 && builtin_abs<f64>(y) < 2147483648.0) {
13192
+ + let ix = <i32>x;
13193
+ + let iy = <i32>y;
13194
+ + if (<f64>ix == x && <f64>iy == y && iy != 0) {
13195
+ + let r = ix % iy;
13196
+ + return r ? <f64>r : builtin_copysign<f64>(0.0, x);
13197
+ + }
13198
+ + }
13199
+ if (builtin_abs<f64>(y) == 1.0) {
13200
+ // x % 1, x % -1 ==> sign(x) * abs(x - 1.0 * trunc(x / 1.0))
13201
+ // TODO: move this rule to compiler's optimization pass.
13202
+ @@ -3287,3 +3300,25 @@ switch (e) {
12761
13203
  case 63:
12762
13204
  }
12763
13205
  */
@@ -13981,10 +14423,24 @@ index 8ed6063..efa6398 100644
13981
14423
  + return c >= 0x30 && c <= 0x39 || c >= 0x41 && c <= 0x5A || c == 0x5F || c >= 0x61 && c <= 0x7A;
13982
14424
  }
13983
14425
  diff --git a/std/assembly/set.ts b/std/assembly/set.ts
13984
- index ca2d6e4..49dd07a 100644
14426
+ index ca2d6e4..b8959cf 100644
13985
14427
  --- a/std/assembly/set.ts
13986
14428
  +++ b/std/assembly/set.ts
13987
- @@ -192,6 +192,12 @@ export class Set<T> {
14429
+ @@ -63,8 +63,11 @@ export class Set<T> {
14430
+ private entriesOffset: i32 = 0;
14431
+ private entriesCount: i32 = 0;
14432
+
14433
+ - constructor() {
14434
+ - /* nop */
14435
+ + /** amxts: `new Set(values)` adds the values in their order, as JavaScript's Set does. */
14436
+ + constructor(values: T[] | null = null) {
14437
+ + if (values) {
14438
+ + for (let i = 0, k = values.length; i < k; ++i) this.add(unchecked(values[i]));
14439
+ + }
14440
+ }
14441
+
14442
+ get size(): i32 {
14443
+ @@ -192,6 +195,12 @@ export class Set<T> {
13988
14444
  return values;
13989
14445
  }
13990
14446