Add other terminal Rtis Change-Id: If70dc283a5fb06fa0d037fb0d30e4ba19352f8d3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/105736 Commit-Queue: Stephen Adams <sra@google.com> Reviewed-by: Mayank Patke <fishythefish@google.com>
diff --git a/sdk/lib/_internal/js_runtime/lib/rti.dart b/sdk/lib/_internal/js_runtime/lib/rti.dart index b9eb479..a3480c2 100644 --- a/sdk/lib/_internal/js_runtime/lib/rti.dart +++ b/sdk/lib/_internal/js_runtime/lib/rti.dart
@@ -110,7 +110,6 @@ /// - Underlying type for unary terms. /// - Class part of a type environment inside a generic class, or `null` for /// type tuple. - /// - Return type of function types. dynamic _primary; static Object _getPrimary(Rti rti) => rti._primary; @@ -225,6 +224,9 @@ int kind = Rti._getKind(rti); if (kind == Rti.kindDynamic) return 'dynamic'; + if (kind == Rti.kindVoid) return 'void'; + if (kind == Rti.kindNever) return 'Never'; + if (kind == Rti.kindAny) return 'any'; if (kind == Rti.kindInterface) { String name = Rti._getInterfaceName(rti); @@ -256,6 +258,9 @@ int kind = Rti._getKind(rti); if (kind == Rti.kindDynamic) return 'dynamic'; + if (kind == Rti.kindVoid) return 'void'; + if (kind == Rti.kindNever) return 'Never'; + if (kind == Rti.kindAny) return 'any'; if (kind == Rti.kindInterface) { String name = Rti._getInterfaceName(rti); @@ -396,18 +401,39 @@ // * `createXXX` to create the type if it does not exist. static String _canonicalRecipeOfDynamic() => '@'; + static String _canonicalRecipeOfVoid() => '~'; + static String _canonicalRecipeOfNever() => '0&'; + static String _canonicalRecipeOfAny() => '1&'; static Rti _lookupDynamicRti(universe) { - var cache = evalCache(universe); - var probe = _cacheGet(cache, _canonicalRecipeOfDynamic()); - if (probe != null) return _castToRti(probe); - return _createDynamicRti(universe); + return _lookupTerminalRti( + universe, Rti.kindDynamic, _canonicalRecipeOfDynamic()); } - static Rti _createDynamicRti(Object universe) { + static Rti _lookupVoidRti(universe) { + return _lookupTerminalRti(universe, Rti.kindVoid, _canonicalRecipeOfVoid()); + } + + static Rti _lookupNeverRti(universe) { + return _lookupTerminalRti( + universe, Rti.kindNever, _canonicalRecipeOfNever()); + } + + static Rti _lookupAnyRti(universe) { + return _lookupTerminalRti(universe, Rti.kindAny, _canonicalRecipeOfAny()); + } + + static Rti _lookupTerminalRti(universe, int kind, String canonicalRecipe) { + var cache = evalCache(universe); + var probe = _cacheGet(cache, canonicalRecipe); + if (probe != null) return _castToRti(probe); + return _createTerminalRti(universe, kind, canonicalRecipe); + } + + static Rti _createTerminalRti(universe, int kind, String canonicalRecipe) { var rti = Rti.allocate(); - Rti._setKind(rti, Rti.kindDynamic); - Rti._setCanonicalRecipe(rti, _canonicalRecipeOfDynamic()); + Rti._setKind(rti, kind); + Rti._setCanonicalRecipe(rti, canonicalRecipe); return _finishRti(universe, rti); } @@ -501,9 +527,9 @@ /// /// Period may be in any position, including first and last e.g. `.x`. /// -/// ',': ignored +/// ',': --- /// -/// Used to separate elements. +/// Ignored. Used to separate elements. /// /// ';': item --- ToType(item) /// @@ -511,8 +537,15 @@ /// /// '@': --- dynamicType /// +/// '~': --- voidType +/// /// '?': type --- type? /// +/// '&': 0 --- NeverType +/// '&': 1 --- anyType +/// +/// Escape op-code with small integer values for encoding rare operations. +/// /// '<': --- position /// /// Saves (pushes) position register, sets position register to end of stack. @@ -650,13 +683,17 @@ // ignored break; + case $SEMICOLON: + push(stack, + toType(universe(parser), environment(parser), pop(stack))); + break; + case $AT: push(stack, _Universe._lookupDynamicRti(universe(parser))); break; - case $SEMICOLON: - push(stack, - toType(universe(parser), environment(parser), pop(stack))); + case $TILDE: + push(stack, _Universe._lookupVoidRti(universe(parser))); break; case $LT: @@ -668,6 +705,10 @@ handleTypeArguments(parser, stack); break; + case $AMPERSAND: + handleExtendedOperations(parser, stack); + break; + default: JS('', 'throw "Bad character " + #', ch); } @@ -727,6 +768,19 @@ } } + static void handleExtendedOperations(Object parser, Object stack) { + var top = pop(stack); + if (0 == top) { + push(stack, _Universe._lookupNeverRti(universe(parser))); + return; + } + if (1 == top) { + push(stack, _Universe._lookupAnyRti(universe(parser))); + return; + } + throw AssertionError('Unexpected extended operation $top'); + } + static Object collectArray(Object parser, Object stack) { var array = _Utils.arraySplice(stack, position(parser)); toTypes(_Parser.universe(parser), environment(parser), array); @@ -796,6 +850,7 @@ (ch == $$); static const int $$ = 0x24; + static const int $AMPERSAND = 0x26; static const int $PLUS = 0x2B; static const int $COMMA = 0x2C; static const int $PERIOD = 0x2E; @@ -813,6 +868,7 @@ static const int $a = $A + 32; static const int $z = $Z + 32; static const int $_ = 0x5F; + static const int $TILDE = 0x7E; } // -------- Subtype tests ------------------------------------------------------
diff --git a/tests/compiler/dart2js_extra/rti/simple_2_test.dart b/tests/compiler/dart2js_extra/rti/simple_2_test.dart index ce81c7b..e092311 100644 --- a/tests/compiler/dart2js_extra/rti/simple_2_test.dart +++ b/tests/compiler/dart2js_extra/rti/simple_2_test.dart
@@ -8,25 +8,72 @@ testDynamic1() { var universe = rti.testingCreateUniverse(); - var dynamicRti1 = rti.testingUniverseEval(universe, 'dynamic'); - var dynamicRti2 = rti.testingUniverseEval(universe, ',,dynamic,,'); + var rti1 = rti.testingUniverseEval(universe, 'dynamic'); + var rti2 = rti.testingUniverseEval(universe, ',,dynamic,,'); - Expect.isTrue( - identical(dynamicRti1, dynamicRti2), 'dynamic should be identical'); - Expect.isFalse(dynamicRti1 is String); - Expect.equals('dynamic', rti.testingRtiToString(dynamicRti1)); + Expect.isTrue(identical(rti1, rti2), 'dynamic should be identical'); + Expect.isFalse(rti1 is String); + Expect.equals('dynamic', rti.testingRtiToString(rti1)); } testDynamic2() { var universe = rti.testingCreateUniverse(); - var dynamicRti1 = rti.testingUniverseEval(universe, 'dynamic'); - var dynamicRti2 = rti.testingUniverseEval(universe, ',,@,,'); + var rti1 = rti.testingUniverseEval(universe, 'dynamic'); + var rti2 = rti.testingUniverseEval(universe, ',,@,,'); - Expect.isTrue( - identical(dynamicRti1, dynamicRti2), 'dynamic should be identical'); - Expect.isFalse(dynamicRti1 is String); - Expect.equals('dynamic', rti.testingRtiToString(dynamicRti1)); + Expect.isTrue(identical(rti1, rti2), 'dynamic should be identical'); + Expect.isFalse(rti1 is String); + Expect.equals('dynamic', rti.testingRtiToString(rti1)); +} + +testVoid() { + var universe = rti.testingCreateUniverse(); + + var rti1 = rti.testingUniverseEval(universe, '~'); + var rti2 = rti.testingUniverseEval(universe, ',,~,,'); + + Expect.isTrue(identical(rti1, rti2), 'void should be identical'); + Expect.isFalse(rti1 is String); + Expect.equals('void', rti.testingRtiToString(rti1)); +} + +testNever() { + var universe = rti.testingCreateUniverse(); + + var rti1 = rti.testingUniverseEval(universe, '0&'); + var rti2 = rti.testingUniverseEval(universe, '0&'); + + Expect.isTrue(identical(rti1, rti2), 'Never should be identical'); + Expect.isFalse(rti1 is String); + Expect.equals('Never', rti.testingRtiToString(rti1)); +} + +testAny() { + var universe = rti.testingCreateUniverse(); + + var rti1 = rti.testingUniverseEval(universe, '1&'); + var rti2 = rti.testingUniverseEval(universe, '1&'); + + Expect.isTrue(identical(rti1, rti2), "'any' should be identical"); + Expect.isFalse(rti1 is String); + Expect.equals('any', rti.testingRtiToString(rti1)); +} + +testTerminal() { + var universe = rti.testingCreateUniverse(); + + var rti1 = rti.testingUniverseEval(universe, '@'); + var rti2 = rti.testingUniverseEval(universe, '~'); + var rti3 = rti.testingUniverseEval(universe, '0&'); + var rti4 = rti.testingUniverseEval(universe, '1&'); + + Expect.isFalse(identical(rti1, rti2)); + Expect.isFalse(identical(rti1, rti3)); + Expect.isFalse(identical(rti1, rti4)); + Expect.isFalse(identical(rti2, rti3)); + Expect.isFalse(identical(rti2, rti4)); + Expect.isFalse(identical(rti3, rti4)); } testInterface1() { @@ -76,6 +123,10 @@ main() { testDynamic1(); testDynamic2(); + testVoid(); + testNever(); + testAny(); + testTerminal(); testInterface1(); testInterface2(); testInterface3();