mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:28:02 +00:00
Reland "[pkg/vm] Handle switch statements in unreachable code eliminator."
This is a reland of commit 92bf76d9e8
In the original CL, the changes to the UCE assumed all
SwitchStatements were exhaustive. Now if a SwitchStatement isn't
explicitly or implicitly (via a default case) exhaustive and no case
matches the tested constant, the SwitchStatement is properly removed.
In addition, if a guaranteed to match case is found, more than one
cases remain (thus the SwitchStatement is not removed or replaced with
the single case's body), and the default case is removed, then the
resulting SwitchStatement is marked as explicitly exhaustive, as this
serves as a signal to backends that they do not need to handle the
possibility of no case matching in the absence of a default case.
Original change's description:
> [pkg/vm] Handle switch statements in unreachable code eliminator.
>
> Namely, if the tested expression for a switch statement is constant,
> then we can remove any constant cases where the constants differ,
> and if all but a single case is removed, we can replace the switch
> with the case body.
>
> If constant functions are not enabled, then getters annotated with
> @pragma("vm:platform-const") are still evaluated with the constant
> function evaluation machinery, but only those and no others (including
> any functions called within an annotated getter). This way, functions
> can be annotated with @pragma("vm:platform-const") without having to
> rewrite them to be a single returned expression.
>
> TEST=pkg/vm/test/transformations/unreachable_code_elimination
> pkg/vm/test/transformations/vm_constant_evaluator
>
> Issue: https://github.com/dart-lang/sdk/issues/50473
> Issue: https://github.com/dart-lang/sdk/issues/31969
> Change-Id: Ie290d2f1f469326238d66c3d9631f8e696685ff0
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/332760
> Commit-Queue: Tess Strickland <sstrickl@google.com>
> Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
> Reviewed-by: Alexander Markov <alexmarkov@google.com>
TEST=pkg/vm/test/transformations/unreachable_code_elimination
pkg/vm/test/transformations/vm_constant_evaluator
Issue: https://github.com/dart-lang/sdk/issues/50473
Issue: https://github.com/dart-lang/sdk/issues/31969
Cq-Include-Trybots: luci.dart.try:vm-aot-linux-release-x64-try,vm-aot-mac-release-arm64-try
Change-Id: I557ca933808012e670e306f2d880221a0d7dd670
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/334224
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
This commit is contained in:
parent
f78759775e
commit
262311772b
12 changed files with 1200 additions and 157 deletions
|
@ -2631,6 +2631,11 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
|
|||
|
||||
/// Execute a function body using the [StatementConstantEvaluator].
|
||||
Constant executeBody(Statement statement) {
|
||||
if (!enableConstFunctions && !inExtensionTypeConstConstructor) {
|
||||
throw new UnsupportedError("Statement evaluation is only supported when "
|
||||
"in extension type const constructors or when the const functions "
|
||||
"feature is enabled.");
|
||||
}
|
||||
StatementConstantEvaluator statementEvaluator =
|
||||
new StatementConstantEvaluator(this);
|
||||
ExecutionStatus status = statement.accept(statementEvaluator);
|
||||
|
@ -2657,6 +2662,11 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
|
|||
/// Returns [null] on success and an error-"constant" on failure, as such the
|
||||
/// return value should be checked.
|
||||
AbortConstant? executeConstructorBody(Constructor constructor) {
|
||||
if (!enableConstFunctions && !inExtensionTypeConstConstructor) {
|
||||
throw new UnsupportedError("Statement evaluation is only supported when "
|
||||
"in extension type const constructors or when the const functions "
|
||||
"feature is enabled.");
|
||||
}
|
||||
final Statement body = constructor.function.body!;
|
||||
StatementConstantEvaluator statementEvaluator =
|
||||
new StatementConstantEvaluator(this);
|
||||
|
@ -5477,14 +5487,7 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
|
|||
class StatementConstantEvaluator implements StatementVisitor<ExecutionStatus> {
|
||||
ConstantEvaluator exprEvaluator;
|
||||
|
||||
StatementConstantEvaluator(this.exprEvaluator) {
|
||||
if (!exprEvaluator.enableConstFunctions &&
|
||||
!exprEvaluator.inExtensionTypeConstConstructor) {
|
||||
throw new UnsupportedError("Statement evaluation is only supported when "
|
||||
"in inline class const constructors or when the const functions "
|
||||
"feature is enabled.");
|
||||
}
|
||||
}
|
||||
StatementConstantEvaluator(this.exprEvaluator);
|
||||
|
||||
/// Evaluate the expression using the [ConstantEvaluator].
|
||||
Constant evaluate(Expression expr) => expr.accept(exprEvaluator);
|
||||
|
|
|
@ -36,25 +36,32 @@ class SimpleUnreachableCodeElimination extends RemovingTransformer {
|
|||
return result;
|
||||
}
|
||||
|
||||
bool _isBoolConstant(Expression node) =>
|
||||
node is BoolLiteral ||
|
||||
(node is ConstantExpression && node.constant is BoolConstant);
|
||||
|
||||
bool _getBoolConstantValue(Expression node) {
|
||||
if (node is BoolLiteral) {
|
||||
return node.value;
|
||||
}
|
||||
if (node is ConstantExpression) {
|
||||
final constant = node.constant;
|
||||
if (constant is BoolConstant) {
|
||||
return constant.value;
|
||||
}
|
||||
}
|
||||
throw 'Expected bool constant: $node';
|
||||
bool? _getBoolConstantValue(Expression node) {
|
||||
if (node is BoolLiteral) return node.value;
|
||||
if (node is! ConstantExpression) return null;
|
||||
final constant = node.constant;
|
||||
return constant is BoolConstant ? constant.value : null;
|
||||
}
|
||||
|
||||
Expression _createBoolLiteral(bool value, int fileOffset) =>
|
||||
new BoolLiteral(value)..fileOffset = fileOffset;
|
||||
Expression _makeConstantExpression(Constant constant, Expression node) {
|
||||
if (constant is UnevaluatedConstant &&
|
||||
constant.expression is InvalidExpression) {
|
||||
return constant.expression;
|
||||
}
|
||||
ConstantExpression constantExpression = new ConstantExpression(
|
||||
constant, node.getStaticType(_staticTypeContext!))
|
||||
..fileOffset = node.fileOffset;
|
||||
if (node is FileUriExpression) {
|
||||
return new FileUriConstantExpression(constantExpression.constant,
|
||||
type: constantExpression.type, fileUri: node.fileUri)
|
||||
..fileOffset = node.fileOffset;
|
||||
}
|
||||
return constantExpression;
|
||||
}
|
||||
|
||||
Expression _createBoolConstantExpression(bool value, Expression node) =>
|
||||
_makeConstantExpression(
|
||||
constantEvaluator.canonicalize(BoolConstant(value)), node);
|
||||
|
||||
Statement _makeEmptyBlockIfEmptyStatement(Statement node, TreeNode parent) =>
|
||||
node is EmptyStatement ? (Block(<Statement>[])..parent = parent) : node;
|
||||
|
@ -63,8 +70,8 @@ class SimpleUnreachableCodeElimination extends RemovingTransformer {
|
|||
TreeNode visitIfStatement(IfStatement node, TreeNode? removalSentinel) {
|
||||
node.transformOrRemoveChildren(this);
|
||||
final condition = node.condition;
|
||||
if (_isBoolConstant(condition)) {
|
||||
final value = _getBoolConstantValue(condition);
|
||||
final value = _getBoolConstantValue(condition);
|
||||
if (value != null) {
|
||||
return value
|
||||
? node.then
|
||||
: (node.otherwise ?? removalSentinel ?? new EmptyStatement());
|
||||
|
@ -78,8 +85,8 @@ class SimpleUnreachableCodeElimination extends RemovingTransformer {
|
|||
ConditionalExpression node, TreeNode? removalSentinel) {
|
||||
node.transformOrRemoveChildren(this);
|
||||
final condition = node.condition;
|
||||
if (_isBoolConstant(condition)) {
|
||||
final value = _getBoolConstantValue(condition);
|
||||
final value = _getBoolConstantValue(condition);
|
||||
if (value != null) {
|
||||
return value ? node.then : node.otherwise;
|
||||
}
|
||||
return node;
|
||||
|
@ -89,9 +96,9 @@ class SimpleUnreachableCodeElimination extends RemovingTransformer {
|
|||
TreeNode visitNot(Not node, TreeNode? removalSentinel) {
|
||||
node.transformOrRemoveChildren(this);
|
||||
final operand = node.operand;
|
||||
if (_isBoolConstant(operand)) {
|
||||
return _createBoolLiteral(
|
||||
!_getBoolConstantValue(operand), node.fileOffset);
|
||||
final value = _getBoolConstantValue(operand);
|
||||
if (value != null) {
|
||||
return _createBoolConstantExpression(!value, node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
@ -100,47 +107,111 @@ class SimpleUnreachableCodeElimination extends RemovingTransformer {
|
|||
TreeNode visitLogicalExpression(
|
||||
LogicalExpression node, TreeNode? removalSentinel) {
|
||||
node.transformOrRemoveChildren(this);
|
||||
final left = node.left;
|
||||
final right = node.right;
|
||||
final operatorEnum = node.operatorEnum;
|
||||
if (_isBoolConstant(left)) {
|
||||
final leftValue = _getBoolConstantValue(left);
|
||||
if (_isBoolConstant(right)) {
|
||||
final rightValue = _getBoolConstantValue(right);
|
||||
if (operatorEnum == LogicalExpressionOperator.OR) {
|
||||
return _createBoolLiteral(leftValue || rightValue, node.fileOffset);
|
||||
} else if (operatorEnum == LogicalExpressionOperator.AND) {
|
||||
return _createBoolLiteral(leftValue && rightValue, node.fileOffset);
|
||||
} else {
|
||||
throw 'Unexpected LogicalExpression operator ${operatorEnum}: $node';
|
||||
}
|
||||
} else {
|
||||
if (leftValue && operatorEnum == LogicalExpressionOperator.OR) {
|
||||
return _createBoolLiteral(true, node.fileOffset);
|
||||
} else if (!leftValue &&
|
||||
operatorEnum == LogicalExpressionOperator.AND) {
|
||||
return _createBoolLiteral(false, node.fileOffset);
|
||||
bool? value = _getBoolConstantValue(node.left);
|
||||
// Because of short-circuiting, these operators cannot be treated as
|
||||
// symmetric, so a non-constant left and a constant right is left as-is.
|
||||
if (value == null) return node;
|
||||
switch (node.operatorEnum) {
|
||||
case LogicalExpressionOperator.OR:
|
||||
return value ? node.left : node.right;
|
||||
case LogicalExpressionOperator.AND:
|
||||
return value ? node.right : node.left;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
TreeNode visitSwitchStatement(
|
||||
SwitchStatement node, TreeNode? removalSentinel) {
|
||||
node.transformOrRemoveChildren(this);
|
||||
final tested = node.expression;
|
||||
if (tested is! ConstantExpression) return node;
|
||||
|
||||
// First, keep any reachable case. As a side effect, any expressions that
|
||||
// cannot match in the SwitchCases are removed. An expression cannot match
|
||||
// if it is a non-matching constant expression or it follows a constant
|
||||
// expression that is guaranteed to match.
|
||||
final toKeep = <SwitchCase>{};
|
||||
bool foundMatchingCase = false;
|
||||
for (final c in node.cases) {
|
||||
if (foundMatchingCase) {
|
||||
c.expressions.clear();
|
||||
continue;
|
||||
}
|
||||
c.expressions.retainWhere((e) {
|
||||
if (foundMatchingCase) return false;
|
||||
if (e is! ConstantExpression) return true;
|
||||
foundMatchingCase = e.constant == tested.constant;
|
||||
return foundMatchingCase;
|
||||
});
|
||||
if (c.isDefault || c.expressions.isNotEmpty) {
|
||||
toKeep.add(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (toKeep.isEmpty) {
|
||||
if (node.isExhaustive) {
|
||||
throw 'Expected at least one kept case from exhaustive switch: $node';
|
||||
}
|
||||
return removalSentinel ?? new EmptyStatement();
|
||||
}
|
||||
|
||||
// Now iteratively find additional cases to keep by following targets of
|
||||
// continue statements in kept cases.
|
||||
final worklist = [...toKeep];
|
||||
final collector = ContinueSwitchStatementTargetCollector(node);
|
||||
while (worklist.isNotEmpty) {
|
||||
final next = worklist.removeLast();
|
||||
final targets = collector.collectTargets(next);
|
||||
for (final target in targets) {
|
||||
if (toKeep.add(target)) {
|
||||
worklist.add(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, remove any cases not marked for keeping. If only one case
|
||||
// is kept, then the switch statement can be replaced with its body.
|
||||
if (toKeep.length == 1) {
|
||||
return toKeep.first.body;
|
||||
}
|
||||
node.cases.retainWhere(toKeep.contains);
|
||||
if (foundMatchingCase && !node.hasDefault) {
|
||||
// While the expression may not be explicitly exhaustive for the type
|
||||
// of the tested expression, it is guaranteed to execute at least one
|
||||
// of the remaining cases, so the backends don't need to handle the case
|
||||
// where no listed case is hit for this switch.
|
||||
//
|
||||
// If the original program has the matching case directly falls through
|
||||
// to the default case for some reason:
|
||||
//
|
||||
// switch (4) {
|
||||
// ...
|
||||
// case 4:
|
||||
// default:
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// this means the default case is kept despite finding a guaranteed to
|
||||
// match expression, as it contains that matching expression. If that
|
||||
// happens, then we don't do this, to keep the invariant that
|
||||
// isExplicitlyExhaustive is false if there is a default case.
|
||||
node.isExplicitlyExhaustive = true;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
@override
|
||||
visitStaticGet(StaticGet node, TreeNode? removalSentinel) {
|
||||
TreeNode visitStaticGet(StaticGet node, TreeNode? removalSentinel) {
|
||||
node.transformOrRemoveChildren(this);
|
||||
final target = node.target;
|
||||
if (target is Field && target.isConst) {
|
||||
throw 'StaticGet from const field $target should be evaluated by front-end: $node';
|
||||
}
|
||||
if (constantEvaluator.transformerShouldEvaluateExpression(node)) {
|
||||
final context = _staticTypeContext!;
|
||||
final result = constantEvaluator.evaluate(context, node);
|
||||
assert(result is! UnevaluatedConstant);
|
||||
return new ConstantExpression(result, node.getStaticType(context))
|
||||
..fileOffset = node.fileOffset;
|
||||
if (!constantEvaluator.transformerShouldEvaluateExpression(node)) {
|
||||
return node;
|
||||
}
|
||||
return node;
|
||||
final result = constantEvaluator.evaluate(_staticTypeContext!, node);
|
||||
return _makeConstantExpression(result, node);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -235,3 +306,25 @@ class SimpleUnreachableCodeElimination extends RemovingTransformer {
|
|||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
class ContinueSwitchStatementTargetCollector extends RecursiveVisitor {
|
||||
final SwitchStatement parent;
|
||||
late Set<SwitchCase> collected;
|
||||
|
||||
ContinueSwitchStatementTargetCollector(this.parent);
|
||||
|
||||
Set<SwitchCase> collectTargets(SwitchCase node) {
|
||||
collected = {};
|
||||
node.accept(this);
|
||||
return collected;
|
||||
}
|
||||
|
||||
@override
|
||||
void visitContinueSwitchStatement(ContinueSwitchStatement node) {
|
||||
node.visitChildren(this);
|
||||
// Only keep targets that are within the original node being checked.
|
||||
if (node.target.parent == parent) {
|
||||
collected.add(node.target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,10 +13,14 @@ import 'package:front_end/src/base/nnbd_mode.dart';
|
|||
import 'package:front_end/src/fasta/kernel/constant_evaluator.dart'
|
||||
show
|
||||
AbortConstant,
|
||||
AbortStatus,
|
||||
ConstantEvaluator,
|
||||
ErrorReporter,
|
||||
EvaluationMode,
|
||||
SimpleErrorReporter;
|
||||
ProceedStatus,
|
||||
ReturnStatus,
|
||||
SimpleErrorReporter,
|
||||
StatementConstantEvaluator;
|
||||
|
||||
import '../target_os.dart';
|
||||
|
||||
|
@ -26,8 +30,10 @@ import '../target_os.dart';
|
|||
/// [targetOS] represents the target operating system and is used when
|
||||
/// evaluating static fields and getters annotated with "vm:platform-const".
|
||||
///
|
||||
/// If [enableConstFunctions] is false, then only getters that return the
|
||||
/// result of a single expression can be evaluated.
|
||||
/// To avoid restricting getters annotated with "vm:platform-const" to be just
|
||||
/// a single return statement whose body is evaluated, we treat annotated
|
||||
/// getters as const functions. If [enableConstFunctions] is false, then
|
||||
/// only annotated getters are treated this way.
|
||||
class VMConstantEvaluator extends ConstantEvaluator {
|
||||
final TargetOS? _targetOS;
|
||||
final Map<String, Constant> _constantFields = {};
|
||||
|
@ -124,6 +130,19 @@ class VMConstantEvaluator extends ConstantEvaluator {
|
|||
bool transformerShouldEvaluateExpression(Expression node) =>
|
||||
_targetOS != null && node is StaticGet && _isPlatformConst(node.target);
|
||||
|
||||
Constant _executePlatformConstBody(Statement statement) {
|
||||
final status = statement.accept(StatementConstantEvaluator(this));
|
||||
if (status is AbortStatus) return status.error;
|
||||
// Happens if there is no return statement in a void Function(...) body.
|
||||
if (status is ProceedStatus) return canonicalize(NullConstant());
|
||||
if (status is ReturnStatus) {
|
||||
final value = status.value;
|
||||
return value != null ? value : canonicalize(NullConstant());
|
||||
}
|
||||
// Other statuses denote intermediate states and not final ones.
|
||||
throw 'No valid constant returned after executing $statement';
|
||||
}
|
||||
|
||||
@override
|
||||
Constant visitStaticGet(StaticGet node) {
|
||||
assert(_targetOS != null);
|
||||
|
@ -153,20 +172,7 @@ class VMConstantEvaluator extends ConstantEvaluator {
|
|||
result = evaluateExpressionInContext(target, target.initializer!);
|
||||
} else if (target is Procedure && target.isGetter) {
|
||||
final body = target.function.body!;
|
||||
// If const functions are enabled, execute the getter as if it were
|
||||
// a const function. Otherwise the annotated getter must be a single
|
||||
// return statement whose expression is evaluated.
|
||||
if (enableConstFunctions) {
|
||||
result = executeBody(body);
|
||||
} else if (body is ReturnStatement) {
|
||||
if (body.expression == null) {
|
||||
return canonicalize(NullConstant());
|
||||
}
|
||||
result = evaluateExpressionInContext(target, body.expression!);
|
||||
} else {
|
||||
throw "Cannot evaluate method '$nameText' since it contains more "
|
||||
"than a single return statement.";
|
||||
}
|
||||
result = _executePlatformConstBody(body);
|
||||
}
|
||||
if (result is AbortConstant) {
|
||||
throw "The body or initialization of member '$nameText' does not "
|
||||
|
|
|
@ -9,6 +9,8 @@ const bool constFalse2 = const bool.fromEnvironment('test.define.notDefined');
|
|||
|
||||
bool? foo() => null;
|
||||
|
||||
Never throws() => throw 'oops';
|
||||
|
||||
void testSimpleConditions() {
|
||||
if (constTrue) {
|
||||
print('1_yes');
|
||||
|
@ -37,6 +39,12 @@ void testAndConditions() {
|
|||
if (constTrue && constTrue && constFalse) {
|
||||
print('4_no');
|
||||
}
|
||||
if (throws() && constTrue) {
|
||||
print('5_calls_throw');
|
||||
}
|
||||
if (throws() && constFalse) {
|
||||
print('6_calls_throw');
|
||||
}
|
||||
}
|
||||
|
||||
void testOrConditions() {
|
||||
|
@ -52,6 +60,12 @@ void testOrConditions() {
|
|||
if (constFalse || !constTrue || constTrue2) {
|
||||
print('4_yes');
|
||||
}
|
||||
if (throws() || constTrue) {
|
||||
print('5_calls_throw');
|
||||
}
|
||||
if (throws() || constFalse) {
|
||||
print('6_calls_throw');
|
||||
}
|
||||
}
|
||||
|
||||
void testNotConditions() {
|
||||
|
@ -112,6 +126,287 @@ testRemovalOfStatementBodies() {
|
|||
}
|
||||
}
|
||||
|
||||
enum TestPlatform {
|
||||
linux,
|
||||
macos,
|
||||
windows,
|
||||
}
|
||||
|
||||
const switchTestString = "noMatch";
|
||||
const switchTestInt = 23;
|
||||
|
||||
testConstantSwitches() {
|
||||
switch (constTrue) {
|
||||
case true:
|
||||
print('1_yes');
|
||||
break;
|
||||
case false:
|
||||
print('2_no');
|
||||
break;
|
||||
}
|
||||
switch (constFalse) {
|
||||
case true:
|
||||
print('3_yes');
|
||||
break;
|
||||
default:
|
||||
print('4_not_yes');
|
||||
}
|
||||
switch (TestPlatform.windows) {
|
||||
case TestPlatform.linux:
|
||||
print("5_linux");
|
||||
break;
|
||||
case TestPlatform.macos:
|
||||
print("6_macos");
|
||||
break;
|
||||
case TestPlatform.windows:
|
||||
print("7_windows");
|
||||
break;
|
||||
}
|
||||
switch (TestPlatform.macos) {
|
||||
case TestPlatform.linux:
|
||||
case TestPlatform.macos:
|
||||
print("8_not_windows");
|
||||
break;
|
||||
case TestPlatform.windows:
|
||||
print("9_windows");
|
||||
break;
|
||||
}
|
||||
switch (TestPlatform.linux) {
|
||||
case TestPlatform.linux:
|
||||
continue L1_macos;
|
||||
L1_macos:
|
||||
case TestPlatform.macos:
|
||||
print("10_not_windows");
|
||||
break;
|
||||
case TestPlatform.windows:
|
||||
print("11_windows");
|
||||
break;
|
||||
}
|
||||
switch (TestPlatform.windows) {
|
||||
case TestPlatform.linux:
|
||||
print("12_linux");
|
||||
break;
|
||||
case TestPlatform.macos:
|
||||
print("13_macos");
|
||||
break;
|
||||
default:
|
||||
print("14_default");
|
||||
}
|
||||
switch (TestPlatform.windows) {
|
||||
case TestPlatform.linux:
|
||||
print("15_linux");
|
||||
break;
|
||||
case TestPlatform.macos:
|
||||
print("16_macos");
|
||||
break;
|
||||
case TestPlatform.windows:
|
||||
continue L2_default;
|
||||
L2_default:
|
||||
default:
|
||||
print("17_default");
|
||||
}
|
||||
// Not explicitly exhaustive as is because there's a default, but once UCE
|
||||
// is run, the resulting switch should be explicitly exhaustive, as the
|
||||
// default is removed but we're still guaranteed that a case will be matched.
|
||||
switch (TestPlatform.macos) {
|
||||
L3_linux:
|
||||
case TestPlatform.linux:
|
||||
print("18_notwindows");
|
||||
break;
|
||||
case TestPlatform.macos:
|
||||
continue L3_linux;
|
||||
case TestPlatform.windows:
|
||||
print("19_windows");
|
||||
break;
|
||||
default:
|
||||
print("20_default");
|
||||
}
|
||||
// Also should be explicitly exhaustive post-UCE, for the reason above.
|
||||
switch (TestPlatform.macos) {
|
||||
L4_linux:
|
||||
case TestPlatform.linux:
|
||||
print("21_notwindows");
|
||||
break;
|
||||
case TestPlatform.macos:
|
||||
if (foo()!) {
|
||||
continue L4_linux;
|
||||
}
|
||||
break;
|
||||
case TestPlatform.windows:
|
||||
print("22_windows");
|
||||
break;
|
||||
default:
|
||||
print("23_default");
|
||||
}
|
||||
switch (switchTestString) {
|
||||
case "isMatch":
|
||||
print("24_isMatch");
|
||||
break;
|
||||
case "isNotMatch":
|
||||
print("25_isNotMatch");
|
||||
break;
|
||||
default:
|
||||
print("26_default");
|
||||
}
|
||||
switch (switchTestString) {
|
||||
case "isMatch":
|
||||
print("27_isMatch");
|
||||
break;
|
||||
L5_isNotMatch:
|
||||
case "isNotMatch":
|
||||
print("28_isNotMatch");
|
||||
break;
|
||||
default:
|
||||
continue L5_isNotMatch;
|
||||
}
|
||||
switch (switchTestInt) {
|
||||
case 0:
|
||||
print("29_zero");
|
||||
break;
|
||||
case 1:
|
||||
print("30_one");
|
||||
break;
|
||||
default:
|
||||
print("31_default");
|
||||
}
|
||||
switch (switchTestInt) {
|
||||
case 0:
|
||||
print("32_zero");
|
||||
break;
|
||||
case 23:
|
||||
print("33_twentythree");
|
||||
break;
|
||||
default:
|
||||
print("34_default");
|
||||
}
|
||||
switch (switchTestString) {
|
||||
case "foo":
|
||||
switch (switchTestInt) {
|
||||
case 0:
|
||||
print("35_foo_zero");
|
||||
break;
|
||||
default:
|
||||
print("36_foo_nonzero");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (switchTestInt) {
|
||||
case 1:
|
||||
print("37_default_one");
|
||||
break;
|
||||
default:
|
||||
print("38_default_default");
|
||||
}
|
||||
}
|
||||
switch (switchTestString) {
|
||||
L6_foo:
|
||||
case "foo":
|
||||
switch (switchTestInt) {
|
||||
case 0:
|
||||
print("39_foo_zero");
|
||||
break;
|
||||
default:
|
||||
print("40_foo_nonzero");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (switchTestInt) {
|
||||
case 1:
|
||||
print("41_default_one");
|
||||
break;
|
||||
default:
|
||||
continue L6_foo;
|
||||
}
|
||||
}
|
||||
switch (switchTestString) {
|
||||
case "foo":
|
||||
switch (switchTestInt) {
|
||||
case 0:
|
||||
continue L7_default;
|
||||
default:
|
||||
print("42_foo_nonzero");
|
||||
}
|
||||
break;
|
||||
L7_default:
|
||||
default:
|
||||
switch (switchTestInt) {
|
||||
case 23:
|
||||
print("43_default_twentythree");
|
||||
break;
|
||||
default:
|
||||
print("44_default_default");
|
||||
}
|
||||
}
|
||||
switch (switchTestString) {
|
||||
L8_foo:
|
||||
case "foo":
|
||||
switch (switchTestInt) {
|
||||
case 23:
|
||||
continue L9_default;
|
||||
default:
|
||||
print("45_foo_nontwentythree");
|
||||
}
|
||||
break;
|
||||
L9_default:
|
||||
default:
|
||||
switch (switchTestInt) {
|
||||
case 23:
|
||||
print("46_default_twentythree");
|
||||
break;
|
||||
default:
|
||||
continue L8_foo;
|
||||
}
|
||||
}
|
||||
switch (switchTestString) {
|
||||
L10_foo:
|
||||
case "foo":
|
||||
switch (switchTestInt) {
|
||||
case 23:
|
||||
continue L11_default;
|
||||
default:
|
||||
print("47_foo_nontwentythree");
|
||||
}
|
||||
break;
|
||||
L11_default:
|
||||
default:
|
||||
switch (switchTestInt) {
|
||||
case 0:
|
||||
print("48_default_zero");
|
||||
break;
|
||||
default:
|
||||
continue L10_foo;
|
||||
}
|
||||
}
|
||||
switch (switchTestInt) {
|
||||
case 23:
|
||||
print("49_twentythree");
|
||||
}
|
||||
switch (switchTestInt) {
|
||||
case 0:
|
||||
print("50_zero");
|
||||
}
|
||||
switch (switchTestInt) {
|
||||
case 0:
|
||||
print("51_zero");
|
||||
break;
|
||||
case 23:
|
||||
default:
|
||||
print("52_23_and_default");
|
||||
}
|
||||
// Should not be marked as isExplicitlyExhaustive, as the case that has the
|
||||
// matching constant is also the default.
|
||||
switch (switchTestInt) {
|
||||
L12_zero:
|
||||
case 0:
|
||||
print("51_zero");
|
||||
break;
|
||||
case 23:
|
||||
default:
|
||||
print("52_23_and_default");
|
||||
continue L12_zero;
|
||||
}
|
||||
}
|
||||
|
||||
main(List<String> args) {
|
||||
testSimpleConditions();
|
||||
testAndConditions();
|
||||
|
|
|
@ -6,12 +6,27 @@ class TestAssertInitializer extends core::Object {
|
|||
constructor •() → self::TestAssertInitializer
|
||||
: super core::Object::•() {}
|
||||
}
|
||||
static const field core::bool constTrue = #C1;
|
||||
static const field core::bool constFalse = #C2;
|
||||
static const field core::bool constTrue2 = #C1;
|
||||
static const field core::bool constFalse2 = #C2;
|
||||
class TestPlatform extends core::_Enum /*isEnum*/ {
|
||||
static const field core::List<self::TestPlatform> values = #C10;
|
||||
enum-element static const field self::TestPlatform linux = #C3;
|
||||
enum-element static const field self::TestPlatform macos = #C6;
|
||||
enum-element static const field self::TestPlatform windows = #C9;
|
||||
const synthetic constructor •(core::int #index, core::String #name) → self::TestPlatform
|
||||
: super core::_Enum::•(#index, #name)
|
||||
;
|
||||
method _enumToString() → core::String
|
||||
return "TestPlatform.${this.{core::_Enum::_name}{core::String}}";
|
||||
}
|
||||
static const field core::bool constTrue = #C11;
|
||||
static const field core::bool constFalse = #C12;
|
||||
static const field core::bool constTrue2 = #C11;
|
||||
static const field core::bool constFalse2 = #C12;
|
||||
static const field core::String switchTestString = #C13;
|
||||
static const field core::int switchTestInt = #C14;
|
||||
static method foo() → core::bool?
|
||||
return null;
|
||||
static method throws() → Never
|
||||
return throw "oops";
|
||||
static method testSimpleConditions() → void {
|
||||
{
|
||||
core::print("1_yes");
|
||||
|
@ -21,20 +36,32 @@ static method testSimpleConditions() → void {
|
|||
}
|
||||
}
|
||||
static method testAndConditions() → void {
|
||||
if(#C1 && self::foo()!) {
|
||||
if(self::foo()!) {
|
||||
core::print("1_yes");
|
||||
}
|
||||
if(self::throws() && #C11) {
|
||||
core::print("5_calls_throw");
|
||||
}
|
||||
if(self::throws() && #C12) {
|
||||
core::print("6_calls_throw");
|
||||
}
|
||||
}
|
||||
static method testOrConditions() → void {
|
||||
{
|
||||
core::print("1_yes");
|
||||
}
|
||||
if(#C2 || self::foo()!) {
|
||||
if(self::foo()!) {
|
||||
core::print("2_yes");
|
||||
}
|
||||
{
|
||||
core::print("4_yes");
|
||||
}
|
||||
if(self::throws() || #C11) {
|
||||
core::print("5_calls_throw");
|
||||
}
|
||||
if(self::throws() || #C12) {
|
||||
core::print("6_calls_throw");
|
||||
}
|
||||
}
|
||||
static method testNotConditions() → void {
|
||||
{
|
||||
|
@ -71,7 +98,7 @@ static method testRemovalOfStatementBodies() → dynamic {
|
|||
#L1:
|
||||
switch(42) /* core::int */ {
|
||||
#L2:
|
||||
case #C3:
|
||||
case #C15:
|
||||
{}
|
||||
}
|
||||
#L3:
|
||||
|
@ -81,6 +108,198 @@ static method testRemovalOfStatementBodies() → dynamic {
|
|||
{}
|
||||
}
|
||||
}
|
||||
static method testConstantSwitches() → dynamic {
|
||||
#L5:
|
||||
{
|
||||
core::print("1_yes");
|
||||
break #L5;
|
||||
}
|
||||
#L6:
|
||||
{
|
||||
core::print("4_not_yes");
|
||||
}
|
||||
#L7:
|
||||
{
|
||||
core::print("7_windows");
|
||||
break #L7;
|
||||
}
|
||||
#L8:
|
||||
{
|
||||
core::print("8_not_windows");
|
||||
break #L8;
|
||||
}
|
||||
#L9:
|
||||
switch(#C3) /* isExplicitlyExhaustive, self::TestPlatform */ {
|
||||
#L10:
|
||||
case #C3:
|
||||
{
|
||||
continue #L11;
|
||||
}
|
||||
#L11:
|
||||
{
|
||||
core::print("10_not_windows");
|
||||
break #L9;
|
||||
}
|
||||
}
|
||||
#L12:
|
||||
{
|
||||
core::print("14_default");
|
||||
}
|
||||
#L13:
|
||||
switch(#C9) /* self::TestPlatform */ {
|
||||
#L14:
|
||||
case #C9:
|
||||
{
|
||||
continue #L15;
|
||||
}
|
||||
#L15:
|
||||
default:
|
||||
{
|
||||
core::print("17_default");
|
||||
}
|
||||
}
|
||||
#L16:
|
||||
switch(#C6) /* isExplicitlyExhaustive, self::TestPlatform */ {
|
||||
#L17:
|
||||
{
|
||||
core::print("18_notwindows");
|
||||
break #L16;
|
||||
}
|
||||
#L18:
|
||||
case #C6:
|
||||
{
|
||||
continue #L17;
|
||||
}
|
||||
}
|
||||
#L19:
|
||||
switch(#C6) /* isExplicitlyExhaustive, self::TestPlatform */ {
|
||||
#L20:
|
||||
{
|
||||
core::print("21_notwindows");
|
||||
break #L19;
|
||||
}
|
||||
#L21:
|
||||
case #C6:
|
||||
{
|
||||
if(self::foo()!) {
|
||||
continue #L20;
|
||||
}
|
||||
break #L19;
|
||||
}
|
||||
}
|
||||
#L22:
|
||||
{
|
||||
core::print("26_default");
|
||||
}
|
||||
#L23:
|
||||
switch(#C13) /* core::String */ {
|
||||
#L24:
|
||||
{
|
||||
core::print("28_isNotMatch");
|
||||
break #L23;
|
||||
}
|
||||
#L25:
|
||||
default:
|
||||
{
|
||||
continue #L24;
|
||||
}
|
||||
}
|
||||
#L26:
|
||||
{
|
||||
core::print("31_default");
|
||||
}
|
||||
#L27:
|
||||
{
|
||||
core::print("33_twentythree");
|
||||
break #L27;
|
||||
}
|
||||
#L28:
|
||||
{
|
||||
#L29:
|
||||
{
|
||||
core::print("38_default_default");
|
||||
}
|
||||
}
|
||||
#L30:
|
||||
switch(#C13) /* core::String */ {
|
||||
#L31:
|
||||
{
|
||||
#L32:
|
||||
{
|
||||
core::print("40_foo_nonzero");
|
||||
}
|
||||
break #L30;
|
||||
}
|
||||
#L33:
|
||||
default:
|
||||
{
|
||||
#L34:
|
||||
{
|
||||
continue #L31;
|
||||
}
|
||||
}
|
||||
}
|
||||
#L35:
|
||||
{
|
||||
#L36:
|
||||
{
|
||||
core::print("43_default_twentythree");
|
||||
break #L36;
|
||||
}
|
||||
}
|
||||
#L37:
|
||||
{
|
||||
#L38:
|
||||
{
|
||||
core::print("46_default_twentythree");
|
||||
break #L38;
|
||||
}
|
||||
}
|
||||
#L39:
|
||||
switch(#C13) /* core::String */ {
|
||||
#L40:
|
||||
{
|
||||
#L41:
|
||||
{
|
||||
continue #L42;
|
||||
}
|
||||
break #L39;
|
||||
}
|
||||
#L42:
|
||||
default:
|
||||
{
|
||||
#L43:
|
||||
{
|
||||
continue #L40;
|
||||
}
|
||||
}
|
||||
}
|
||||
#L44:
|
||||
{
|
||||
core::print("49_twentythree");
|
||||
}
|
||||
#L45:
|
||||
;
|
||||
#L46:
|
||||
{
|
||||
core::print("52_23_and_default");
|
||||
}
|
||||
#L47:
|
||||
switch(#C14) /* core::int */ {
|
||||
#L48:
|
||||
{
|
||||
core::print("51_zero");
|
||||
break #L47;
|
||||
}
|
||||
#L49:
|
||||
case #C14:
|
||||
default:
|
||||
{
|
||||
core::print("52_23_and_default");
|
||||
continue #L48;
|
||||
}
|
||||
}
|
||||
}
|
||||
static method main(core::List<core::String> args) → dynamic {
|
||||
self::testSimpleConditions();
|
||||
self::testAndConditions();
|
||||
|
@ -92,7 +311,19 @@ static method main(core::List<core::String> args) → dynamic {
|
|||
self::testRemovalOfStatementBodies();
|
||||
}
|
||||
constants {
|
||||
#C1 = true
|
||||
#C2 = false
|
||||
#C3 = 10
|
||||
#C1 = 0
|
||||
#C2 = "linux"
|
||||
#C3 = self::TestPlatform {index:#C1, _name:#C2}
|
||||
#C4 = 1
|
||||
#C5 = "macos"
|
||||
#C6 = self::TestPlatform {index:#C4, _name:#C5}
|
||||
#C7 = 2
|
||||
#C8 = "windows"
|
||||
#C9 = self::TestPlatform {index:#C7, _name:#C8}
|
||||
#C10 = <self::TestPlatform>[#C3, #C6, #C9]
|
||||
#C11 = true
|
||||
#C12 = false
|
||||
#C13 = "noMatch"
|
||||
#C14 = 23
|
||||
#C15 = 10
|
||||
}
|
||||
|
|
|
@ -70,6 +70,77 @@ void testWindows(int i) {
|
|||
}
|
||||
}
|
||||
|
||||
void testSwitchStatements(int i) {
|
||||
switch (Platform.operatingSystem) {
|
||||
case "android":
|
||||
print("is android");
|
||||
break;
|
||||
case "fuchsia":
|
||||
print("is fuchsia");
|
||||
break;
|
||||
case "ios":
|
||||
print("is ios");
|
||||
break;
|
||||
case "linux":
|
||||
print("is linux");
|
||||
break;
|
||||
case "macos":
|
||||
print("is macos");
|
||||
break;
|
||||
case "windows":
|
||||
print("is windows");
|
||||
break;
|
||||
default:
|
||||
throw "Unexpected platform";
|
||||
}
|
||||
}
|
||||
|
||||
enum TestPlatform {
|
||||
android,
|
||||
fuchsia,
|
||||
ios,
|
||||
linux,
|
||||
macos,
|
||||
windows,
|
||||
}
|
||||
|
||||
@pragma("vm:platform-const")
|
||||
TestPlatform get defaultTestPlatform {
|
||||
if (Platform.isAndroid) return TestPlatform.android;
|
||||
if (Platform.isFuchsia) return TestPlatform.fuchsia;
|
||||
if (Platform.isIOS) return TestPlatform.ios;
|
||||
if (Platform.isLinux) return TestPlatform.linux;
|
||||
if (Platform.isMacOS) return TestPlatform.macos;
|
||||
if (Platform.isWindows) return TestPlatform.windows;
|
||||
throw 'Unexpected platform';
|
||||
}
|
||||
|
||||
void testPragma(int i) {
|
||||
print(defaultTestPlatform);
|
||||
switch (defaultTestPlatform) {
|
||||
case TestPlatform.android:
|
||||
print("is android");
|
||||
break;
|
||||
case TestPlatform.fuchsia:
|
||||
print("is fuchsia");
|
||||
break;
|
||||
case TestPlatform.ios:
|
||||
print("is ios");
|
||||
break;
|
||||
case TestPlatform.linux:
|
||||
print("is linux");
|
||||
break;
|
||||
case TestPlatform.macos:
|
||||
print("is macos");
|
||||
break;
|
||||
case TestPlatform.windows:
|
||||
print("is windows");
|
||||
break;
|
||||
default:
|
||||
throw "Unexpected platform";
|
||||
}
|
||||
}
|
||||
|
||||
main(List<String> args) {
|
||||
if (args.isEmpty) return;
|
||||
final i = int.parse(args[0]);
|
||||
|
@ -79,4 +150,6 @@ main(List<String> args) {
|
|||
testLinux(i);
|
||||
testMacOS(i);
|
||||
testWindows(i);
|
||||
testSwitchStatements(i);
|
||||
testPragma(i);
|
||||
}
|
||||
|
|
|
@ -4,36 +4,70 @@ import "dart:core" as core;
|
|||
|
||||
import "dart:io";
|
||||
|
||||
class TestPlatform extends core::_Enum /*isEnum*/ {
|
||||
static const field core::List<self::TestPlatform> values = #C19;
|
||||
enum-element static const field self::TestPlatform android = #C3;
|
||||
enum-element static const field self::TestPlatform fuchsia = #C6;
|
||||
enum-element static const field self::TestPlatform ios = #C9;
|
||||
enum-element static const field self::TestPlatform linux = #C12;
|
||||
enum-element static const field self::TestPlatform macos = #C15;
|
||||
enum-element static const field self::TestPlatform windows = #C18;
|
||||
const synthetic constructor •(core::int #index, core::String #name) → self::TestPlatform
|
||||
: super core::_Enum::•(#index, #name)
|
||||
;
|
||||
method _enumToString() → core::String
|
||||
return "TestPlatform.${this.{core::_Enum::_name}{core::String}}";
|
||||
}
|
||||
static method testAndroid(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
{
|
||||
final core::String os = #C2;
|
||||
core::print(os);
|
||||
final core::String sep = #C3;
|
||||
final core::String sep = #C21;
|
||||
core::print(sep);
|
||||
}
|
||||
}
|
||||
static method testFuchsia(core::int i) → void {
|
||||
final core::bool b = #C4;
|
||||
final core::bool b = #C22;
|
||||
core::print(b);
|
||||
}
|
||||
static method testIOS(core::int i) → void {
|
||||
final core::bool b = #C4;
|
||||
final core::bool b = #C22;
|
||||
core::print(b);
|
||||
}
|
||||
static method testLinux(core::int i) → void {
|
||||
final core::bool b = #C4;
|
||||
final core::bool b = #C22;
|
||||
core::print(b);
|
||||
}
|
||||
static method testMacOS(core::int i) → void {
|
||||
final core::bool b = #C4;
|
||||
final core::bool b = #C22;
|
||||
core::print(b);
|
||||
}
|
||||
static method testWindows(core::int i) → void {
|
||||
final core::bool b = #C4;
|
||||
final core::bool b = #C22;
|
||||
core::print(b);
|
||||
}
|
||||
static method testSwitchStatements(core::int i) → void {
|
||||
#L1:
|
||||
{
|
||||
core::print("is android");
|
||||
break #L1;
|
||||
}
|
||||
}
|
||||
@#C25
|
||||
static get defaultTestPlatform() → self::TestPlatform {
|
||||
return #C3;
|
||||
throw "Unexpected platform";
|
||||
}
|
||||
static method testPragma(core::int i) → void {
|
||||
core::print(#C3);
|
||||
#L2:
|
||||
{
|
||||
core::print("is android");
|
||||
break #L2;
|
||||
}
|
||||
}
|
||||
static method main(core::List<core::String> args) → dynamic {
|
||||
if(args.{core::Iterable::isEmpty}{core::bool})
|
||||
return;
|
||||
|
@ -44,10 +78,33 @@ static method main(core::List<core::String> args) → dynamic {
|
|||
self::testLinux(i);
|
||||
self::testMacOS(i);
|
||||
self::testWindows(i);
|
||||
self::testSwitchStatements(i);
|
||||
self::testPragma(i);
|
||||
}
|
||||
constants {
|
||||
#C1 = true
|
||||
#C1 = 0
|
||||
#C2 = "android"
|
||||
#C3 = "/"
|
||||
#C4 = false
|
||||
#C3 = self::TestPlatform {index:#C1, _name:#C2}
|
||||
#C4 = 1
|
||||
#C5 = "fuchsia"
|
||||
#C6 = self::TestPlatform {index:#C4, _name:#C5}
|
||||
#C7 = 2
|
||||
#C8 = "ios"
|
||||
#C9 = self::TestPlatform {index:#C7, _name:#C8}
|
||||
#C10 = 3
|
||||
#C11 = "linux"
|
||||
#C12 = self::TestPlatform {index:#C10, _name:#C11}
|
||||
#C13 = 4
|
||||
#C14 = "macos"
|
||||
#C15 = self::TestPlatform {index:#C13, _name:#C14}
|
||||
#C16 = 5
|
||||
#C17 = "windows"
|
||||
#C18 = self::TestPlatform {index:#C16, _name:#C17}
|
||||
#C19 = <self::TestPlatform>[#C3, #C6, #C9, #C12, #C15, #C18]
|
||||
#C20 = true
|
||||
#C21 = "/"
|
||||
#C22 = false
|
||||
#C23 = "vm:platform-const"
|
||||
#C24 = null
|
||||
#C25 = core::pragma {name:#C23, options:#C24}
|
||||
}
|
||||
|
|
|
@ -4,36 +4,70 @@ import "dart:core" as core;
|
|||
|
||||
import "dart:io";
|
||||
|
||||
class TestPlatform extends core::_Enum /*isEnum*/ {
|
||||
static const field core::List<self::TestPlatform> values = #C19;
|
||||
enum-element static const field self::TestPlatform android = #C3;
|
||||
enum-element static const field self::TestPlatform fuchsia = #C6;
|
||||
enum-element static const field self::TestPlatform ios = #C9;
|
||||
enum-element static const field self::TestPlatform linux = #C12;
|
||||
enum-element static const field self::TestPlatform macos = #C15;
|
||||
enum-element static const field self::TestPlatform windows = #C18;
|
||||
const synthetic constructor •(core::int #index, core::String #name) → self::TestPlatform
|
||||
: super core::_Enum::•(#index, #name)
|
||||
;
|
||||
method _enumToString() → core::String
|
||||
return "TestPlatform.${this.{core::_Enum::_name}{core::String}}";
|
||||
}
|
||||
static method testAndroid(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testFuchsia(core::int i) → void {
|
||||
final core::bool b = #C2;
|
||||
final core::bool b = #C21;
|
||||
core::print(b);
|
||||
{
|
||||
final core::String os = #C3;
|
||||
final core::String os = #C5;
|
||||
core::print(os);
|
||||
final core::String sep = #C4;
|
||||
final core::String sep = #C22;
|
||||
core::print(sep);
|
||||
}
|
||||
}
|
||||
static method testIOS(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testLinux(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testMacOS(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testWindows(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testSwitchStatements(core::int i) → void {
|
||||
#L1:
|
||||
{
|
||||
core::print("is fuchsia");
|
||||
break #L1;
|
||||
}
|
||||
}
|
||||
@#C25
|
||||
static get defaultTestPlatform() → self::TestPlatform {
|
||||
return #C6;
|
||||
throw "Unexpected platform";
|
||||
}
|
||||
static method testPragma(core::int i) → void {
|
||||
core::print(#C6);
|
||||
#L2:
|
||||
{
|
||||
core::print("is fuchsia");
|
||||
break #L2;
|
||||
}
|
||||
}
|
||||
static method main(core::List<core::String> args) → dynamic {
|
||||
if(args.{core::Iterable::isEmpty}{core::bool})
|
||||
return;
|
||||
|
@ -44,10 +78,33 @@ static method main(core::List<core::String> args) → dynamic {
|
|||
self::testLinux(i);
|
||||
self::testMacOS(i);
|
||||
self::testWindows(i);
|
||||
self::testSwitchStatements(i);
|
||||
self::testPragma(i);
|
||||
}
|
||||
constants {
|
||||
#C1 = false
|
||||
#C2 = true
|
||||
#C3 = "fuchsia"
|
||||
#C4 = "/"
|
||||
#C1 = 0
|
||||
#C2 = "android"
|
||||
#C3 = self::TestPlatform {index:#C1, _name:#C2}
|
||||
#C4 = 1
|
||||
#C5 = "fuchsia"
|
||||
#C6 = self::TestPlatform {index:#C4, _name:#C5}
|
||||
#C7 = 2
|
||||
#C8 = "ios"
|
||||
#C9 = self::TestPlatform {index:#C7, _name:#C8}
|
||||
#C10 = 3
|
||||
#C11 = "linux"
|
||||
#C12 = self::TestPlatform {index:#C10, _name:#C11}
|
||||
#C13 = 4
|
||||
#C14 = "macos"
|
||||
#C15 = self::TestPlatform {index:#C13, _name:#C14}
|
||||
#C16 = 5
|
||||
#C17 = "windows"
|
||||
#C18 = self::TestPlatform {index:#C16, _name:#C17}
|
||||
#C19 = <self::TestPlatform>[#C3, #C6, #C9, #C12, #C15, #C18]
|
||||
#C20 = false
|
||||
#C21 = true
|
||||
#C22 = "/"
|
||||
#C23 = "vm:platform-const"
|
||||
#C24 = null
|
||||
#C25 = core::pragma {name:#C23, options:#C24}
|
||||
}
|
||||
|
|
|
@ -4,36 +4,70 @@ import "dart:core" as core;
|
|||
|
||||
import "dart:io";
|
||||
|
||||
class TestPlatform extends core::_Enum /*isEnum*/ {
|
||||
static const field core::List<self::TestPlatform> values = #C19;
|
||||
enum-element static const field self::TestPlatform android = #C3;
|
||||
enum-element static const field self::TestPlatform fuchsia = #C6;
|
||||
enum-element static const field self::TestPlatform ios = #C9;
|
||||
enum-element static const field self::TestPlatform linux = #C12;
|
||||
enum-element static const field self::TestPlatform macos = #C15;
|
||||
enum-element static const field self::TestPlatform windows = #C18;
|
||||
const synthetic constructor •(core::int #index, core::String #name) → self::TestPlatform
|
||||
: super core::_Enum::•(#index, #name)
|
||||
;
|
||||
method _enumToString() → core::String
|
||||
return "TestPlatform.${this.{core::_Enum::_name}{core::String}}";
|
||||
}
|
||||
static method testAndroid(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testFuchsia(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testIOS(core::int i) → void {
|
||||
final core::bool b = #C2;
|
||||
final core::bool b = #C21;
|
||||
core::print(b);
|
||||
{
|
||||
final core::String os = #C3;
|
||||
final core::String os = #C8;
|
||||
core::print(os);
|
||||
final core::String sep = #C4;
|
||||
final core::String sep = #C22;
|
||||
core::print(sep);
|
||||
}
|
||||
}
|
||||
static method testLinux(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testMacOS(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testWindows(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testSwitchStatements(core::int i) → void {
|
||||
#L1:
|
||||
{
|
||||
core::print("is ios");
|
||||
break #L1;
|
||||
}
|
||||
}
|
||||
@#C25
|
||||
static get defaultTestPlatform() → self::TestPlatform {
|
||||
return #C9;
|
||||
throw "Unexpected platform";
|
||||
}
|
||||
static method testPragma(core::int i) → void {
|
||||
core::print(#C9);
|
||||
#L2:
|
||||
{
|
||||
core::print("is ios");
|
||||
break #L2;
|
||||
}
|
||||
}
|
||||
static method main(core::List<core::String> args) → dynamic {
|
||||
if(args.{core::Iterable::isEmpty}{core::bool})
|
||||
return;
|
||||
|
@ -44,10 +78,33 @@ static method main(core::List<core::String> args) → dynamic {
|
|||
self::testLinux(i);
|
||||
self::testMacOS(i);
|
||||
self::testWindows(i);
|
||||
self::testSwitchStatements(i);
|
||||
self::testPragma(i);
|
||||
}
|
||||
constants {
|
||||
#C1 = false
|
||||
#C2 = true
|
||||
#C3 = "ios"
|
||||
#C4 = "/"
|
||||
#C1 = 0
|
||||
#C2 = "android"
|
||||
#C3 = self::TestPlatform {index:#C1, _name:#C2}
|
||||
#C4 = 1
|
||||
#C5 = "fuchsia"
|
||||
#C6 = self::TestPlatform {index:#C4, _name:#C5}
|
||||
#C7 = 2
|
||||
#C8 = "ios"
|
||||
#C9 = self::TestPlatform {index:#C7, _name:#C8}
|
||||
#C10 = 3
|
||||
#C11 = "linux"
|
||||
#C12 = self::TestPlatform {index:#C10, _name:#C11}
|
||||
#C13 = 4
|
||||
#C14 = "macos"
|
||||
#C15 = self::TestPlatform {index:#C13, _name:#C14}
|
||||
#C16 = 5
|
||||
#C17 = "windows"
|
||||
#C18 = self::TestPlatform {index:#C16, _name:#C17}
|
||||
#C19 = <self::TestPlatform>[#C3, #C6, #C9, #C12, #C15, #C18]
|
||||
#C20 = false
|
||||
#C21 = true
|
||||
#C22 = "/"
|
||||
#C23 = "vm:platform-const"
|
||||
#C24 = null
|
||||
#C25 = core::pragma {name:#C23, options:#C24}
|
||||
}
|
||||
|
|
|
@ -4,36 +4,70 @@ import "dart:core" as core;
|
|||
|
||||
import "dart:io";
|
||||
|
||||
class TestPlatform extends core::_Enum /*isEnum*/ {
|
||||
static const field core::List<self::TestPlatform> values = #C19;
|
||||
enum-element static const field self::TestPlatform android = #C3;
|
||||
enum-element static const field self::TestPlatform fuchsia = #C6;
|
||||
enum-element static const field self::TestPlatform ios = #C9;
|
||||
enum-element static const field self::TestPlatform linux = #C12;
|
||||
enum-element static const field self::TestPlatform macos = #C15;
|
||||
enum-element static const field self::TestPlatform windows = #C18;
|
||||
const synthetic constructor •(core::int #index, core::String #name) → self::TestPlatform
|
||||
: super core::_Enum::•(#index, #name)
|
||||
;
|
||||
method _enumToString() → core::String
|
||||
return "TestPlatform.${this.{core::_Enum::_name}{core::String}}";
|
||||
}
|
||||
static method testAndroid(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testFuchsia(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testIOS(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testLinux(core::int i) → void {
|
||||
final core::bool b = #C2;
|
||||
final core::bool b = #C21;
|
||||
core::print(b);
|
||||
{
|
||||
final core::String os = #C3;
|
||||
final core::String os = #C11;
|
||||
core::print(os);
|
||||
final core::String sep = #C4;
|
||||
final core::String sep = #C22;
|
||||
core::print(sep);
|
||||
}
|
||||
}
|
||||
static method testMacOS(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testWindows(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testSwitchStatements(core::int i) → void {
|
||||
#L1:
|
||||
{
|
||||
core::print("is linux");
|
||||
break #L1;
|
||||
}
|
||||
}
|
||||
@#C25
|
||||
static get defaultTestPlatform() → self::TestPlatform {
|
||||
return #C12;
|
||||
throw "Unexpected platform";
|
||||
}
|
||||
static method testPragma(core::int i) → void {
|
||||
core::print(#C12);
|
||||
#L2:
|
||||
{
|
||||
core::print("is linux");
|
||||
break #L2;
|
||||
}
|
||||
}
|
||||
static method main(core::List<core::String> args) → dynamic {
|
||||
if(args.{core::Iterable::isEmpty}{core::bool})
|
||||
return;
|
||||
|
@ -44,10 +78,33 @@ static method main(core::List<core::String> args) → dynamic {
|
|||
self::testLinux(i);
|
||||
self::testMacOS(i);
|
||||
self::testWindows(i);
|
||||
self::testSwitchStatements(i);
|
||||
self::testPragma(i);
|
||||
}
|
||||
constants {
|
||||
#C1 = false
|
||||
#C2 = true
|
||||
#C3 = "linux"
|
||||
#C4 = "/"
|
||||
#C1 = 0
|
||||
#C2 = "android"
|
||||
#C3 = self::TestPlatform {index:#C1, _name:#C2}
|
||||
#C4 = 1
|
||||
#C5 = "fuchsia"
|
||||
#C6 = self::TestPlatform {index:#C4, _name:#C5}
|
||||
#C7 = 2
|
||||
#C8 = "ios"
|
||||
#C9 = self::TestPlatform {index:#C7, _name:#C8}
|
||||
#C10 = 3
|
||||
#C11 = "linux"
|
||||
#C12 = self::TestPlatform {index:#C10, _name:#C11}
|
||||
#C13 = 4
|
||||
#C14 = "macos"
|
||||
#C15 = self::TestPlatform {index:#C13, _name:#C14}
|
||||
#C16 = 5
|
||||
#C17 = "windows"
|
||||
#C18 = self::TestPlatform {index:#C16, _name:#C17}
|
||||
#C19 = <self::TestPlatform>[#C3, #C6, #C9, #C12, #C15, #C18]
|
||||
#C20 = false
|
||||
#C21 = true
|
||||
#C22 = "/"
|
||||
#C23 = "vm:platform-const"
|
||||
#C24 = null
|
||||
#C25 = core::pragma {name:#C23, options:#C24}
|
||||
}
|
||||
|
|
|
@ -4,36 +4,70 @@ import "dart:core" as core;
|
|||
|
||||
import "dart:io";
|
||||
|
||||
class TestPlatform extends core::_Enum /*isEnum*/ {
|
||||
static const field core::List<self::TestPlatform> values = #C19;
|
||||
enum-element static const field self::TestPlatform android = #C3;
|
||||
enum-element static const field self::TestPlatform fuchsia = #C6;
|
||||
enum-element static const field self::TestPlatform ios = #C9;
|
||||
enum-element static const field self::TestPlatform linux = #C12;
|
||||
enum-element static const field self::TestPlatform macos = #C15;
|
||||
enum-element static const field self::TestPlatform windows = #C18;
|
||||
const synthetic constructor •(core::int #index, core::String #name) → self::TestPlatform
|
||||
: super core::_Enum::•(#index, #name)
|
||||
;
|
||||
method _enumToString() → core::String
|
||||
return "TestPlatform.${this.{core::_Enum::_name}{core::String}}";
|
||||
}
|
||||
static method testAndroid(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testFuchsia(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testIOS(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testLinux(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testMacOS(core::int i) → void {
|
||||
final core::bool b = #C2;
|
||||
final core::bool b = #C21;
|
||||
core::print(b);
|
||||
{
|
||||
final core::String os = #C3;
|
||||
final core::String os = #C14;
|
||||
core::print(os);
|
||||
final core::String sep = #C4;
|
||||
final core::String sep = #C22;
|
||||
core::print(sep);
|
||||
}
|
||||
}
|
||||
static method testWindows(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testSwitchStatements(core::int i) → void {
|
||||
#L1:
|
||||
{
|
||||
core::print("is macos");
|
||||
break #L1;
|
||||
}
|
||||
}
|
||||
@#C25
|
||||
static get defaultTestPlatform() → self::TestPlatform {
|
||||
return #C15;
|
||||
throw "Unexpected platform";
|
||||
}
|
||||
static method testPragma(core::int i) → void {
|
||||
core::print(#C15);
|
||||
#L2:
|
||||
{
|
||||
core::print("is macos");
|
||||
break #L2;
|
||||
}
|
||||
}
|
||||
static method main(core::List<core::String> args) → dynamic {
|
||||
if(args.{core::Iterable::isEmpty}{core::bool})
|
||||
return;
|
||||
|
@ -44,10 +78,33 @@ static method main(core::List<core::String> args) → dynamic {
|
|||
self::testLinux(i);
|
||||
self::testMacOS(i);
|
||||
self::testWindows(i);
|
||||
self::testSwitchStatements(i);
|
||||
self::testPragma(i);
|
||||
}
|
||||
constants {
|
||||
#C1 = false
|
||||
#C2 = true
|
||||
#C3 = "macos"
|
||||
#C4 = "/"
|
||||
#C1 = 0
|
||||
#C2 = "android"
|
||||
#C3 = self::TestPlatform {index:#C1, _name:#C2}
|
||||
#C4 = 1
|
||||
#C5 = "fuchsia"
|
||||
#C6 = self::TestPlatform {index:#C4, _name:#C5}
|
||||
#C7 = 2
|
||||
#C8 = "ios"
|
||||
#C9 = self::TestPlatform {index:#C7, _name:#C8}
|
||||
#C10 = 3
|
||||
#C11 = "linux"
|
||||
#C12 = self::TestPlatform {index:#C10, _name:#C11}
|
||||
#C13 = 4
|
||||
#C14 = "macos"
|
||||
#C15 = self::TestPlatform {index:#C13, _name:#C14}
|
||||
#C16 = 5
|
||||
#C17 = "windows"
|
||||
#C18 = self::TestPlatform {index:#C16, _name:#C17}
|
||||
#C19 = <self::TestPlatform>[#C3, #C6, #C9, #C12, #C15, #C18]
|
||||
#C20 = false
|
||||
#C21 = true
|
||||
#C22 = "/"
|
||||
#C23 = "vm:platform-const"
|
||||
#C24 = null
|
||||
#C25 = core::pragma {name:#C23, options:#C24}
|
||||
}
|
||||
|
|
|
@ -4,36 +4,70 @@ import "dart:core" as core;
|
|||
|
||||
import "dart:io";
|
||||
|
||||
class TestPlatform extends core::_Enum /*isEnum*/ {
|
||||
static const field core::List<self::TestPlatform> values = #C19;
|
||||
enum-element static const field self::TestPlatform android = #C3;
|
||||
enum-element static const field self::TestPlatform fuchsia = #C6;
|
||||
enum-element static const field self::TestPlatform ios = #C9;
|
||||
enum-element static const field self::TestPlatform linux = #C12;
|
||||
enum-element static const field self::TestPlatform macos = #C15;
|
||||
enum-element static const field self::TestPlatform windows = #C18;
|
||||
const synthetic constructor •(core::int #index, core::String #name) → self::TestPlatform
|
||||
: super core::_Enum::•(#index, #name)
|
||||
;
|
||||
method _enumToString() → core::String
|
||||
return "TestPlatform.${this.{core::_Enum::_name}{core::String}}";
|
||||
}
|
||||
static method testAndroid(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testFuchsia(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testIOS(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testLinux(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testMacOS(core::int i) → void {
|
||||
final core::bool b = #C1;
|
||||
final core::bool b = #C20;
|
||||
core::print(b);
|
||||
}
|
||||
static method testWindows(core::int i) → void {
|
||||
final core::bool b = #C2;
|
||||
final core::bool b = #C21;
|
||||
core::print(b);
|
||||
{
|
||||
final core::String os = #C3;
|
||||
final core::String os = #C17;
|
||||
core::print(os);
|
||||
final core::String sep = #C4;
|
||||
final core::String sep = #C22;
|
||||
core::print(sep);
|
||||
}
|
||||
}
|
||||
static method testSwitchStatements(core::int i) → void {
|
||||
#L1:
|
||||
{
|
||||
core::print("is windows");
|
||||
break #L1;
|
||||
}
|
||||
}
|
||||
@#C25
|
||||
static get defaultTestPlatform() → self::TestPlatform {
|
||||
return #C18;
|
||||
throw "Unexpected platform";
|
||||
}
|
||||
static method testPragma(core::int i) → void {
|
||||
core::print(#C18);
|
||||
#L2:
|
||||
{
|
||||
core::print("is windows");
|
||||
break #L2;
|
||||
}
|
||||
}
|
||||
static method main(core::List<core::String> args) → dynamic {
|
||||
if(args.{core::Iterable::isEmpty}{core::bool})
|
||||
return;
|
||||
|
@ -44,10 +78,33 @@ static method main(core::List<core::String> args) → dynamic {
|
|||
self::testLinux(i);
|
||||
self::testMacOS(i);
|
||||
self::testWindows(i);
|
||||
self::testSwitchStatements(i);
|
||||
self::testPragma(i);
|
||||
}
|
||||
constants {
|
||||
#C1 = false
|
||||
#C2 = true
|
||||
#C3 = "windows"
|
||||
#C4 = "\\"
|
||||
#C1 = 0
|
||||
#C2 = "android"
|
||||
#C3 = self::TestPlatform {index:#C1, _name:#C2}
|
||||
#C4 = 1
|
||||
#C5 = "fuchsia"
|
||||
#C6 = self::TestPlatform {index:#C4, _name:#C5}
|
||||
#C7 = 2
|
||||
#C8 = "ios"
|
||||
#C9 = self::TestPlatform {index:#C7, _name:#C8}
|
||||
#C10 = 3
|
||||
#C11 = "linux"
|
||||
#C12 = self::TestPlatform {index:#C10, _name:#C11}
|
||||
#C13 = 4
|
||||
#C14 = "macos"
|
||||
#C15 = self::TestPlatform {index:#C13, _name:#C14}
|
||||
#C16 = 5
|
||||
#C17 = "windows"
|
||||
#C18 = self::TestPlatform {index:#C16, _name:#C17}
|
||||
#C19 = <self::TestPlatform>[#C3, #C6, #C9, #C12, #C15, #C18]
|
||||
#C20 = false
|
||||
#C21 = true
|
||||
#C22 = "\\"
|
||||
#C23 = "vm:platform-const"
|
||||
#C24 = null
|
||||
#C25 = core::pragma {name:#C23, options:#C24}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue