Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(250)

Unified Diff: sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart

Issue 661923003: Support binary expressions in analyzer2dart. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart
diff --git a/sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart b/sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart
index 6a2c566ff9469224862ea35b446dfe719ec7f4d2..38c036ee37c8b26e4d843553b546195cde68d743 100644
--- a/sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart
@@ -495,4 +495,230 @@ class IrBuilder {
}
return false;
}
+
Johnni Winther 2014/10/17 11:37:40 These are moved/adapted from IrBuilderVisitor.
+ /// Create a negation of [condition].
+ ir.Primitive buildNegation(ir.Primitive condition) {
+ // ! e is translated as e ? false : true
+
+ // Add a continuation parameter for the result of the expression.
+ ir.Parameter resultParameter = new ir.Parameter(null);
+
+ ir.Continuation joinContinuation = new ir.Continuation([resultParameter]);
+ ir.Continuation thenContinuation = new ir.Continuation([]);
+ ir.Continuation elseContinuation = new ir.Continuation([]);
+
+ ir.Constant trueConstant =
+ makePrimConst(state.constantSystem.createBool(true));
+ ir.Constant falseConstant =
+ makePrimConst(state.constantSystem.createBool(false));
+
+ thenContinuation.body = new ir.LetPrim(falseConstant)
+ ..plug(new ir.InvokeContinuation(joinContinuation, [falseConstant]));
+ elseContinuation.body = new ir.LetPrim(trueConstant)
+ ..plug(new ir.InvokeContinuation(joinContinuation, [trueConstant]));
+
+ add(new ir.LetCont(joinContinuation,
+ new ir.LetCont(thenContinuation,
+ new ir.LetCont(elseContinuation,
+ new ir.Branch(new ir.IsTrue(condition),
+ thenContinuation,
+ elseContinuation)))));
+ return resultParameter;
+ }
+
+ /// Create a lazy and/or expression. [leftValue] is the value of the left
+ /// operand and [buildRightValue] is called to process the value of the right
+ /// operand in the context of its own [IrBuilder].
+ ir.Primitive buildLogicalOperator(
+ ir.Primitive leftValue,
+ ir.Primitive buildRightValue(IrBuilder builder),
+ {bool isLazyOr: false}) {
+ // e0 && e1 is translated as if e0 ? (e1 == true) : false.
+ // e0 || e1 is translated as if e0 ? true : (e1 == true).
+ // The translation must convert both e0 and e1 to booleans and handle
+ // local variable assignments in e1.
+
+ IrBuilder rightBuilder = new IrBuilder.delimited(this);
+ ir.Primitive rightValue = buildRightValue(rightBuilder);
+ // A dummy empty target for the branch on the left subexpression branch.
+ // This enables using the same infrastructure for join-point continuations
+ // as in visitIf and visitConditional. It will hold a definition of the
+ // appropriate constant and an invocation of the join-point continuation.
+ IrBuilder emptyBuilder = new IrBuilder.delimited(this);
+ // Dummy empty targets for right true and right false. They hold
+ // definitions of the appropriate constant and an invocation of the
+ // join-point continuation.
+ IrBuilder rightTrueBuilder = new IrBuilder.delimited(rightBuilder);
+ IrBuilder rightFalseBuilder = new IrBuilder.delimited(rightBuilder);
+
+ // If we don't evaluate the right subexpression, the value of the whole
+ // expression is this constant.
+ ir.Constant leftBool = emptyBuilder.makePrimConst(
+ emptyBuilder.state.constantSystem.createBool(isLazyOr));
+ // If we do evaluate the right subexpression, the value of the expression
+ // is a true or false constant.
+ ir.Constant rightTrue = rightTrueBuilder.makePrimConst(
+ rightTrueBuilder.state.constantSystem.createBool(true));
+ ir.Constant rightFalse = rightFalseBuilder.makePrimConst(
+ rightFalseBuilder.state.constantSystem.createBool(false));
+ emptyBuilder.add(new ir.LetPrim(leftBool));
+ rightTrueBuilder.add(new ir.LetPrim(rightTrue));
+ rightFalseBuilder.add(new ir.LetPrim(rightFalse));
+
+ // Treat the result values as named values in the environment, so they
+ // will be treated as arguments to the join-point continuation.
+ assert(environment.length == emptyBuilder.environment.length);
+ assert(environment.length == rightTrueBuilder.environment.length);
+ assert(environment.length == rightFalseBuilder.environment.length);
+ emptyBuilder.environment.extend(null, leftBool);
+ rightTrueBuilder.environment.extend(null, rightTrue);
+ rightFalseBuilder.environment.extend(null, rightFalse);
+
+ // Wire up two continuations for the left subexpression, two continuations
+ // for the right subexpression, and a three-way join continuation.
+ JumpCollector jumps = new JumpCollector(null);
+ jumps.addJump(emptyBuilder);
+ jumps.addJump(rightTrueBuilder);
+ jumps.addJump(rightFalseBuilder);
+ ir.Continuation joinContinuation =
+ createJoin(environment.length + 1, jumps);
+ ir.Continuation leftTrueContinuation = new ir.Continuation([]);
+ ir.Continuation leftFalseContinuation = new ir.Continuation([]);
+ ir.Continuation rightTrueContinuation = new ir.Continuation([]);
+ ir.Continuation rightFalseContinuation = new ir.Continuation([]);
+ rightTrueContinuation.body = rightTrueBuilder._root;
+ rightFalseContinuation.body = rightFalseBuilder._root;
+ // The right subexpression has two continuations.
+ rightBuilder.add(
+ new ir.LetCont(rightTrueContinuation,
+ new ir.LetCont(rightFalseContinuation,
+ new ir.Branch(new ir.IsTrue(rightValue),
+ rightTrueContinuation,
+ rightFalseContinuation))));
+ // Depending on the operator, the left subexpression's continuations are
+ // either the right subexpression or an invocation of the join-point
+ // continuation.
+ if (isLazyOr) {
+ leftTrueContinuation.body = emptyBuilder._root;
+ leftFalseContinuation.body = rightBuilder._root;
+ } else {
+ leftTrueContinuation.body = rightBuilder._root;
+ leftFalseContinuation.body = emptyBuilder._root;
+ }
+
+ add(new ir.LetCont(joinContinuation,
+ new ir.LetCont(leftTrueContinuation,
+ new ir.LetCont(leftFalseContinuation,
+ new ir.Branch(new ir.IsTrue(leftValue),
+ leftTrueContinuation,
+ leftFalseContinuation)))));
+ // There is always a join parameter for the result value, because it
+ // is different on at least two paths.
+ return joinContinuation.parameters.last;
+ }
+
+ /// Create a non-recursive join-point continuation.
+ ///
+ /// Given the environment length at the join point and a list of
+ /// jumps that should reach the join point, create a join-point
+ /// continuation. The join-point continuation has a parameter for each
+ /// variable that has different values reaching on different paths.
+ ///
+ /// The jumps are uninitialized [ir.InvokeContinuation] expressions.
+ /// They are filled in with the target continuation and appropriate
+ /// arguments.
+ ///
+ /// As a side effect, the environment of this builder is updated to include
+ /// the join-point continuation parameters.
+ ir.Continuation createJoin(int environmentLength, JumpCollector jumps) {
+ assert(jumps.length >= 2);
+
+ // Compute which values are identical on all paths reaching the join.
+ // Handle the common case of a pair of contexts efficiently.
+ Environment first = jumps.environments[0];
+ Environment second = jumps.environments[1];
+ assert(environmentLength <= first.length);
+ assert(environmentLength <= second.length);
+ assert(first.sameDomain(environmentLength, second));
+ // A running count of the join-point parameters.
+ int parameterCount = 0;
+ // The null elements of common correspond to required parameters of the
+ // join-point continuation.
+ List<ir.Primitive> common =
+ new List<ir.Primitive>.generate(environmentLength,
+ (i) {
+ ir.Primitive candidate = first[i];
+ if (second[i] == candidate) {
+ return candidate;
+ } else {
+ ++parameterCount;
+ return null;
+ }
+ });
+ // If there is already a parameter for each variable, the other
+ // environments do not need to be considered.
+ if (parameterCount < environmentLength) {
+ for (int i = 0; i < environmentLength; ++i) {
+ ir.Primitive candidate = common[i];
+ if (candidate == null) continue;
+ for (Environment current in jumps.environments.skip(2)) {
+ assert(environmentLength <= current.length);
+ assert(first.sameDomain(environmentLength, current));
+ if (candidate != current[i]) {
+ common[i] = null;
+ ++parameterCount;
+ break;
+ }
+ }
+ if (parameterCount >= environmentLength) break;
+ }
+ }
+
+ // Create the join point continuation.
+ List<ir.Parameter> parameters = <ir.Parameter>[];
+ parameters.length = parameterCount;
+ int index = 0;
+ for (int i = 0; i < environmentLength; ++i) {
+ if (common[i] == null) {
+ parameters[index++] = new ir.Parameter(first.index2variable[i]);
+ }
+ }
+ assert(index == parameterCount);
+ ir.Continuation join = new ir.Continuation(parameters);
+
+ // Fill in all the continuation invocations.
+ for (int i = 0; i < jumps.length; ++i) {
+ Environment currentEnvironment = jumps.environments[i];
+ ir.InvokeContinuation invoke = jumps.invocations[i];
+ // Sharing this.environment with one of the invocations will not do
+ // the right thing (this.environment has already been mutated).
+ List<ir.Reference> arguments = <ir.Reference>[];
+ arguments.length = parameterCount;
+ int index = 0;
+ for (int i = 0; i < environmentLength; ++i) {
+ if (common[i] == null) {
+ arguments[index++] = new ir.Reference(currentEnvironment[i]);
+ }
+ }
+ invoke.continuation = new ir.Reference(join);
+ invoke.arguments = arguments;
+ }
+
+ // Mutate this.environment to be the environment at the join point. Do
+ // this after adding the continuation invocations, because this.environment
+ // might be collected by the jump collector and so the old environment
+ // values are needed for the continuation invocation.
+ //
+ // Iterate to environment.length because environmentLength includes values
+ // outside the environment which are 'phantom' variables used for the
+ // values of expressions like &&, ||, and ?:.
+ index = 0;
+ for (int i = 0; i < environment.length; ++i) {
+ if (common[i] == null) {
+ environment.index2value[i] = parameters[index++];
+ }
+ }
+
+ return join;
+ }
}
« no previous file with comments | « pkg/analyzer2dart/test/end2end_test.dart ('k') | sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder_visitor.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698