| Index: pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
|
| diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
|
| index 131922e545b95df76a0074c7b19ea8c81daec713..d411ee447d6c30eb897f48d287c059f2754ca35b 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
|
| @@ -1648,6 +1648,78 @@ abstract class IrBuilder {
|
| environment = breakCollector.environment;
|
| }
|
|
|
| + void buildSimpleSwitch(JumpTarget target,
|
| + ir.Primitive value,
|
| + List<SwitchCaseInfo> cases,
|
| + SwitchCaseInfo defaultCase,
|
| + Element error,
|
| + SourceInformation sourceInformation) {
|
| + assert(isOpen);
|
| + JumpCollector join = new ForwardJumpCollector(environment, target: target);
|
| +
|
| + IrBuilder casesBuilder = makeDelimitedBuilder();
|
| + casesBuilder.state.breakCollectors.add(join);
|
| + for (SwitchCaseInfo caseInfo in cases) {
|
| + buildConditionsFrom(int index) => (IrBuilder builder) {
|
| + ir.Primitive comparison = builder.addPrimitive(
|
| + new ir.Identical(value, caseInfo.constants[index]));
|
| + return (index == caseInfo.constants.length - 1)
|
| + ? comparison
|
| + : builder.buildLogicalOperator(
|
| + comparison, buildConditionsFrom(index + 1), isLazyOr: true);
|
| + };
|
| +
|
| + ir.Primitive condition = buildConditionsFrom(0)(casesBuilder);
|
| + IrBuilder thenBuilder = makeDelimitedBuilder();
|
| + caseInfo.buildBody(thenBuilder);
|
| + if (thenBuilder.isOpen) {
|
| + // It is a runtime error to reach the end of a switch case, unless
|
| + // it is the last case.
|
| + if (caseInfo == cases.last && defaultCase == null) {
|
| + thenBuilder.jumpTo(join);
|
| + } else {
|
| + ir.Primitive exception = thenBuilder._buildInvokeStatic(
|
| + error,
|
| + new Selector.fromElement(error),
|
| + <ir.Primitive>[],
|
| + sourceInformation);
|
| + thenBuilder.buildThrow(exception);
|
| + }
|
| + }
|
| +
|
| + ir.Continuation thenContinuation = new ir.Continuation([]);
|
| + thenContinuation.body = thenBuilder._root;
|
| + ir.Continuation elseContinuation = new ir.Continuation([]);
|
| + // A LetCont.many term has a hole as the body of the first listed
|
| + // continuation, to be plugged by the translation. Therefore put the
|
| + // else continuation first.
|
| + casesBuilder.add(
|
| + new ir.LetCont.many(<ir.Continuation>[elseContinuation,
|
| + thenContinuation],
|
| + new ir.Branch(new ir.IsTrue(condition),
|
| + thenContinuation,
|
| + elseContinuation)));
|
| + }
|
| +
|
| + if (defaultCase != null) {
|
| + defaultCase.buildBody(casesBuilder);
|
| + }
|
| + if (casesBuilder.isOpen) casesBuilder.jumpTo(join);
|
| +
|
| + casesBuilder.state.breakCollectors.removeLast();
|
| +
|
| + if (!join.isEmpty) {
|
| + add(new ir.LetCont(join.continuation, casesBuilder._root));
|
| + environment = join.environment;
|
| + } else if (casesBuilder._root != null) {
|
| + add(casesBuilder._root);
|
| + _current = casesBuilder._current;
|
| + environment = casesBuilder.environment;
|
| + } else {
|
| + // The translation of the cases did not emit any code.
|
| + }
|
| + }
|
| +
|
| /// Creates a try-statement.
|
| ///
|
| /// [tryInfo] provides information on local variables declared and boxed
|
| @@ -2556,3 +2628,12 @@ class CatchClauseInfo {
|
| this.stackTraceVariable,
|
| this.buildCatchBlock});
|
| }
|
| +
|
| +class SwitchCaseInfo {
|
| + final List<ir.Primitive> constants = <ir.Primitive>[];
|
| + final SubbuildFunction buildBody;
|
| +
|
| + SwitchCaseInfo(this.buildBody);
|
| +
|
| + void addConstant(ir.Primitive constant) => constants.add(constant);
|
| +}
|
|
|