| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.ir_builder; | 5 library dart2js.ir_builder; |
| 6 | 6 |
| 7 import '../closure.dart' as closure; | 7 import '../closure.dart' as closure; |
| 8 import '../common.dart'; | 8 import '../common.dart'; |
| 9 import '../common/names.dart' show | 9 import '../common/names.dart' show |
| 10 Names, | 10 Names, |
| (...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 return addPrimitive(new ir.LiteralList(type, values.toList(), | 794 return addPrimitive(new ir.LiteralList(type, values.toList(), |
| 795 allocationSiteType: allocationSiteType)); | 795 allocationSiteType: allocationSiteType)); |
| 796 } | 796 } |
| 797 | 797 |
| 798 /// Creates a conditional expression with the provided [condition] where the | 798 /// Creates a conditional expression with the provided [condition] where the |
| 799 /// then and else expression are created through the [buildThenExpression] | 799 /// then and else expression are created through the [buildThenExpression] |
| 800 /// and [buildElseExpression] functions, respectively. | 800 /// and [buildElseExpression] functions, respectively. |
| 801 ir.Primitive buildConditional( | 801 ir.Primitive buildConditional( |
| 802 ir.Primitive condition, | 802 ir.Primitive condition, |
| 803 ir.Primitive buildThenExpression(IrBuilder builder), | 803 ir.Primitive buildThenExpression(IrBuilder builder), |
| 804 ir.Primitive buildElseExpression(IrBuilder builder)) { | 804 ir.Primitive buildElseExpression(IrBuilder builder), |
| 805 SourceInformation sourceInformation) { |
| 805 assert(isOpen); | 806 assert(isOpen); |
| 806 | 807 |
| 807 // The then and else expressions are delimited. | 808 // The then and else expressions are delimited. |
| 808 IrBuilder thenBuilder = makeDelimitedBuilder(); | 809 IrBuilder thenBuilder = makeDelimitedBuilder(); |
| 809 IrBuilder elseBuilder = makeDelimitedBuilder(); | 810 IrBuilder elseBuilder = makeDelimitedBuilder(); |
| 810 ir.Primitive thenValue = buildThenExpression(thenBuilder); | 811 ir.Primitive thenValue = buildThenExpression(thenBuilder); |
| 811 ir.Primitive elseValue = buildElseExpression(elseBuilder); | 812 ir.Primitive elseValue = buildElseExpression(elseBuilder); |
| 812 | 813 |
| 813 // Treat the values of the subexpressions as named values in the | 814 // Treat the values of the subexpressions as named values in the |
| 814 // environment, so they will be treated as arguments to the join-point | 815 // environment, so they will be treated as arguments to the join-point |
| (...skipping 13 matching lines...) Expand all Loading... |
| 828 // in | 829 // in |
| 829 // if condition (then, else) | 830 // if condition (then, else) |
| 830 ir.Continuation thenContinuation = new ir.Continuation([]); | 831 ir.Continuation thenContinuation = new ir.Continuation([]); |
| 831 ir.Continuation elseContinuation = new ir.Continuation([]); | 832 ir.Continuation elseContinuation = new ir.Continuation([]); |
| 832 thenContinuation.body = thenBuilder.root; | 833 thenContinuation.body = thenBuilder.root; |
| 833 elseContinuation.body = elseBuilder.root; | 834 elseContinuation.body = elseBuilder.root; |
| 834 add(new ir.LetCont(join.continuation, | 835 add(new ir.LetCont(join.continuation, |
| 835 new ir.LetCont.two(thenContinuation, elseContinuation, | 836 new ir.LetCont.two(thenContinuation, elseContinuation, |
| 836 new ir.Branch.strict(condition, | 837 new ir.Branch.strict(condition, |
| 837 thenContinuation, | 838 thenContinuation, |
| 838 elseContinuation)))); | 839 elseContinuation, |
| 840 sourceInformation)))); |
| 839 environment = join.environment; | 841 environment = join.environment; |
| 840 return environment.discard(1); | 842 return environment.discard(1); |
| 841 } | 843 } |
| 842 | 844 |
| 843 /** | 845 /** |
| 844 * Add an explicit `return null` for functions that don't have a return | 846 * Add an explicit `return null` for functions that don't have a return |
| 845 * statement on each branch. This includes functions with an empty body, | 847 * statement on each branch. This includes functions with an empty body, |
| 846 * such as `foo(){ }`. | 848 * such as `foo(){ }`. |
| 847 */ | 849 */ |
| 848 void _ensureReturn() { | 850 void _ensureReturn() { |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1095 | 1097 |
| 1096 /// Creates an if-then-else statement with the provided [condition] where the | 1098 /// Creates an if-then-else statement with the provided [condition] where the |
| 1097 /// then and else branches are created through the [buildThenPart] and | 1099 /// then and else branches are created through the [buildThenPart] and |
| 1098 /// [buildElsePart] functions, respectively. | 1100 /// [buildElsePart] functions, respectively. |
| 1099 /// | 1101 /// |
| 1100 /// An if-then statement is created if [buildElsePart] is a no-op. | 1102 /// An if-then statement is created if [buildElsePart] is a no-op. |
| 1101 // TODO(johnniwinther): Unify implementation with [buildConditional] and | 1103 // TODO(johnniwinther): Unify implementation with [buildConditional] and |
| 1102 // [_buildLogicalOperator]. | 1104 // [_buildLogicalOperator]. |
| 1103 void buildIf(ir.Primitive condition, | 1105 void buildIf(ir.Primitive condition, |
| 1104 void buildThenPart(IrBuilder builder), | 1106 void buildThenPart(IrBuilder builder), |
| 1105 void buildElsePart(IrBuilder builder)) { | 1107 void buildElsePart(IrBuilder builder), |
| 1108 SourceInformation sourceInformation) { |
| 1106 assert(isOpen); | 1109 assert(isOpen); |
| 1107 | 1110 |
| 1108 // The then and else parts are delimited. | 1111 // The then and else parts are delimited. |
| 1109 IrBuilder thenBuilder = makeDelimitedBuilder(); | 1112 IrBuilder thenBuilder = makeDelimitedBuilder(); |
| 1110 IrBuilder elseBuilder = makeDelimitedBuilder(); | 1113 IrBuilder elseBuilder = makeDelimitedBuilder(); |
| 1111 buildThenPart(thenBuilder); | 1114 buildThenPart(thenBuilder); |
| 1112 buildElsePart(elseBuilder); | 1115 buildElsePart(elseBuilder); |
| 1113 | 1116 |
| 1114 // Build the term | 1117 // Build the term |
| 1115 // (Result =) let cont then() = [[thenPart]] | 1118 // (Result =) let cont then() = [[thenPart]] |
| 1116 // and else() = [[elsePart]] | 1119 // and else() = [[elsePart]] |
| 1117 // in | 1120 // in |
| 1118 // if condition (then, else) | 1121 // if condition (then, else) |
| 1119 ir.Continuation thenContinuation = new ir.Continuation([]); | 1122 ir.Continuation thenContinuation = new ir.Continuation([]); |
| 1120 ir.Continuation elseContinuation = new ir.Continuation([]); | 1123 ir.Continuation elseContinuation = new ir.Continuation([]); |
| 1121 // If exactly one of the then and else continuation bodies is open (i.e., | 1124 // If exactly one of the then and else continuation bodies is open (i.e., |
| 1122 // the other one has an exit on all paths), then Continuation.plug expects | 1125 // the other one has an exit on all paths), then Continuation.plug expects |
| 1123 // that continuation to be listed first. Arbitrarily use [then, else] | 1126 // that continuation to be listed first. Arbitrarily use [then, else] |
| 1124 // order otherwise. | 1127 // order otherwise. |
| 1125 List<ir.Continuation> arms = !thenBuilder.isOpen && elseBuilder.isOpen | 1128 List<ir.Continuation> arms = !thenBuilder.isOpen && elseBuilder.isOpen |
| 1126 ? <ir.Continuation>[elseContinuation, thenContinuation] | 1129 ? <ir.Continuation>[elseContinuation, thenContinuation] |
| 1127 : <ir.Continuation>[thenContinuation, elseContinuation]; | 1130 : <ir.Continuation>[thenContinuation, elseContinuation]; |
| 1128 | 1131 |
| 1129 ir.Expression result = | 1132 ir.Expression result = |
| 1130 new ir.LetCont.many(arms, | 1133 new ir.LetCont.many(arms, |
| 1131 new ir.Branch.strict(condition, | 1134 new ir.Branch.strict(condition, |
| 1132 thenContinuation, | 1135 thenContinuation, |
| 1133 elseContinuation)); | 1136 elseContinuation, |
| 1137 sourceInformation)); |
| 1134 | 1138 |
| 1135 JumpCollector join; // Null if there is no join. | 1139 JumpCollector join; // Null if there is no join. |
| 1136 if (thenBuilder.isOpen && elseBuilder.isOpen) { | 1140 if (thenBuilder.isOpen && elseBuilder.isOpen) { |
| 1137 // There is a join-point continuation. Build the term | 1141 // There is a join-point continuation. Build the term |
| 1138 // 'let cont join(x, ...) = [] in Result' and plug invocations of the | 1142 // 'let cont join(x, ...) = [] in Result' and plug invocations of the |
| 1139 // join-point continuation into the then and else continuations. | 1143 // join-point continuation into the then and else continuations. |
| 1140 join = new ForwardJumpCollector(environment); | 1144 join = new ForwardJumpCollector(environment); |
| 1141 thenBuilder.jumpTo(join); | 1145 thenBuilder.jumpTo(join); |
| 1142 elseBuilder.jumpTo(join); | 1146 elseBuilder.jumpTo(join); |
| 1143 result = new ir.LetCont(join.continuation, result); | 1147 result = new ir.LetCont(join.continuation, result); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1191 /// statements that have this `for` statement as their target. | 1195 /// statements that have this `for` statement as their target. |
| 1192 /// | 1196 /// |
| 1193 /// The [closureScope] identifies variables that should be boxed in this loop. | 1197 /// The [closureScope] identifies variables that should be boxed in this loop. |
| 1194 /// This includes variables declared inside the body of the loop as well as | 1198 /// This includes variables declared inside the body of the loop as well as |
| 1195 /// in the for-loop initializer. | 1199 /// in the for-loop initializer. |
| 1196 /// | 1200 /// |
| 1197 /// [loopVariables] is the list of variables declared in the for-loop | 1201 /// [loopVariables] is the list of variables declared in the for-loop |
| 1198 /// initializer. | 1202 /// initializer. |
| 1199 void buildFor({SubbuildFunction buildInitializer, | 1203 void buildFor({SubbuildFunction buildInitializer, |
| 1200 SubbuildFunction buildCondition, | 1204 SubbuildFunction buildCondition, |
| 1205 SourceInformation conditionSourceInformation, |
| 1201 SubbuildFunction buildBody, | 1206 SubbuildFunction buildBody, |
| 1202 SubbuildFunction buildUpdate, | 1207 SubbuildFunction buildUpdate, |
| 1203 JumpTarget target, | 1208 JumpTarget target, |
| 1204 ClosureScope closureScope, | 1209 ClosureScope closureScope, |
| 1205 List<LocalElement> loopVariables}) { | 1210 List<LocalElement> loopVariables}) { |
| 1206 assert(isOpen); | 1211 assert(isOpen); |
| 1207 | 1212 |
| 1208 // For loops use four named continuations: the entry to the condition, | 1213 // For loops use four named continuations: the entry to the condition, |
| 1209 // the entry to the body, the loop exit, and the loop successor (break). | 1214 // the entry to the body, the loop exit, and the loop successor (break). |
| 1210 // The CPS translation of | 1215 // The CPS translation of |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1295 // Create loop exit and body entry continuations and a branch to them. | 1300 // Create loop exit and body entry continuations and a branch to them. |
| 1296 ir.Continuation exitContinuation = new ir.Continuation([]); | 1301 ir.Continuation exitContinuation = new ir.Continuation([]); |
| 1297 ir.Continuation bodyContinuation = new ir.Continuation([]); | 1302 ir.Continuation bodyContinuation = new ir.Continuation([]); |
| 1298 bodyContinuation.body = outerBodyBuilder.root; | 1303 bodyContinuation.body = outerBodyBuilder.root; |
| 1299 // Note the order of continuations: the first one is the one that will | 1304 // Note the order of continuations: the first one is the one that will |
| 1300 // be filled by LetCont.plug. | 1305 // be filled by LetCont.plug. |
| 1301 ir.LetCont branch = | 1306 ir.LetCont branch = |
| 1302 new ir.LetCont.two(exitContinuation, bodyContinuation, | 1307 new ir.LetCont.two(exitContinuation, bodyContinuation, |
| 1303 new ir.Branch.strict(condition, | 1308 new ir.Branch.strict(condition, |
| 1304 bodyContinuation, | 1309 bodyContinuation, |
| 1305 exitContinuation)); | 1310 exitContinuation, |
| 1311 conditionSourceInformation)); |
| 1306 // If there are breaks in the body, then there must be a join-point | 1312 // If there are breaks in the body, then there must be a join-point |
| 1307 // continuation for the normal exit and the breaks. Otherwise, the | 1313 // continuation for the normal exit and the breaks. Otherwise, the |
| 1308 // successor is translated in the hole in the exit continuation. | 1314 // successor is translated in the hole in the exit continuation. |
| 1309 bool hasBreaks = !breakCollector.isEmpty; | 1315 bool hasBreaks = !breakCollector.isEmpty; |
| 1310 ir.LetCont letBreak; | 1316 ir.LetCont letBreak; |
| 1311 if (hasBreaks) { | 1317 if (hasBreaks) { |
| 1312 IrBuilder exitBuilder = makeDelimitedBuilder(); | 1318 IrBuilder exitBuilder = makeDelimitedBuilder(); |
| 1313 exitBuilder.jumpTo(breakCollector); | 1319 exitBuilder.jumpTo(breakCollector); |
| 1314 exitContinuation.body = exitBuilder.root; | 1320 exitContinuation.body = exitBuilder.root; |
| 1315 letBreak = new ir.LetCont(breakCollector.continuation, branch); | 1321 letBreak = new ir.LetCont(breakCollector.continuation, branch); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1343 TypeMask variableMask, | 1349 TypeMask variableMask, |
| 1344 SourceInformation variableSetSourceInformation, | 1350 SourceInformation variableSetSourceInformation, |
| 1345 TypeMask currentMask, | 1351 TypeMask currentMask, |
| 1346 SourceInformation currentSourceInformation, | 1352 SourceInformation currentSourceInformation, |
| 1347 TypeMask iteratorMask, | 1353 TypeMask iteratorMask, |
| 1348 SourceInformation iteratorSourceInformation, | 1354 SourceInformation iteratorSourceInformation, |
| 1349 TypeMask moveNextMask, | 1355 TypeMask moveNextMask, |
| 1350 SourceInformation moveNextSourceInformation, | 1356 SourceInformation moveNextSourceInformation, |
| 1351 SubbuildFunction buildBody, | 1357 SubbuildFunction buildBody, |
| 1352 JumpTarget target, | 1358 JumpTarget target, |
| 1353 ClosureScope closureScope}) { | 1359 ClosureScope closureScope, |
| 1360 SourceInformation conditionSourceInformation}) { |
| 1354 // The for-in loop | 1361 // The for-in loop |
| 1355 // | 1362 // |
| 1356 // for (a in e) s; | 1363 // for (a in e) s; |
| 1357 // | 1364 // |
| 1358 // Is compiled analogously to: | 1365 // Is compiled analogously to: |
| 1359 // | 1366 // |
| 1360 // it = e.iterator; | 1367 // it = e.iterator; |
| 1361 // while (it.moveNext()) { | 1368 // while (it.moveNext()) { |
| 1362 // var a = it.current; | 1369 // var a = it.current; |
| 1363 // s; | 1370 // s; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1467 // in branch condition (body, exit) | 1474 // in branch condition (body, exit) |
| 1468 ir.Continuation exitContinuation = new ir.Continuation([]); | 1475 ir.Continuation exitContinuation = new ir.Continuation([]); |
| 1469 ir.Continuation bodyContinuation = new ir.Continuation([]); | 1476 ir.Continuation bodyContinuation = new ir.Continuation([]); |
| 1470 bodyContinuation.body = bodyBuilder.root; | 1477 bodyContinuation.body = bodyBuilder.root; |
| 1471 // Note the order of continuations: the first one is the one that will | 1478 // Note the order of continuations: the first one is the one that will |
| 1472 // be filled by LetCont.plug. | 1479 // be filled by LetCont.plug. |
| 1473 ir.LetCont branch = | 1480 ir.LetCont branch = |
| 1474 new ir.LetCont.two(exitContinuation, bodyContinuation, | 1481 new ir.LetCont.two(exitContinuation, bodyContinuation, |
| 1475 new ir.Branch.strict(condition, | 1482 new ir.Branch.strict(condition, |
| 1476 bodyContinuation, | 1483 bodyContinuation, |
| 1477 exitContinuation)); | 1484 exitContinuation, |
| 1485 conditionSourceInformation)); |
| 1478 // If there are breaks in the body, then there must be a join-point | 1486 // If there are breaks in the body, then there must be a join-point |
| 1479 // continuation for the normal exit and the breaks. Otherwise, the | 1487 // continuation for the normal exit and the breaks. Otherwise, the |
| 1480 // successor is translated in the hole in the exit continuation. | 1488 // successor is translated in the hole in the exit continuation. |
| 1481 bool hasBreaks = !breakCollector.isEmpty; | 1489 bool hasBreaks = !breakCollector.isEmpty; |
| 1482 ir.LetCont letBreak; | 1490 ir.LetCont letBreak; |
| 1483 if (hasBreaks) { | 1491 if (hasBreaks) { |
| 1484 IrBuilder exitBuilder = makeDelimitedBuilder(); | 1492 IrBuilder exitBuilder = makeDelimitedBuilder(); |
| 1485 exitBuilder.jumpTo(breakCollector); | 1493 exitBuilder.jumpTo(breakCollector); |
| 1486 exitContinuation.body = exitBuilder.root; | 1494 exitContinuation.body = exitBuilder.root; |
| 1487 letBreak = new ir.LetCont(breakCollector.continuation, branch); | 1495 letBreak = new ir.LetCont(breakCollector.continuation, branch); |
| 1488 add(letBreak); | 1496 add(letBreak); |
| 1489 environment = breakCollector.environment; | 1497 environment = breakCollector.environment; |
| 1490 } else { | 1498 } else { |
| 1491 add(branch); | 1499 add(branch); |
| 1492 } | 1500 } |
| 1493 } | 1501 } |
| 1494 | 1502 |
| 1495 /// Creates a while loop in which the condition and body are created by | 1503 /// Creates a while loop in which the condition and body are created by |
| 1496 /// [buildCondition] and [buildBody], respectively. | 1504 /// [buildCondition] and [buildBody], respectively. |
| 1497 /// | 1505 /// |
| 1498 /// The jump [target] is used to identify which `break` and `continue` | 1506 /// The jump [target] is used to identify which `break` and `continue` |
| 1499 /// statements that have this `while` statement as their target. | 1507 /// statements that have this `while` statement as their target. |
| 1500 void buildWhile({SubbuildFunction buildCondition, | 1508 void buildWhile({SubbuildFunction buildCondition, |
| 1501 SubbuildFunction buildBody, | 1509 SubbuildFunction buildBody, |
| 1502 JumpTarget target, | 1510 JumpTarget target, |
| 1503 ClosureScope closureScope}) { | 1511 ClosureScope closureScope, |
| 1512 SourceInformation sourceInformation}) { |
| 1504 assert(isOpen); | 1513 assert(isOpen); |
| 1505 // While loops use four named continuations: the entry to the body, the | 1514 // While loops use four named continuations: the entry to the body, the |
| 1506 // loop exit, the loop back edge (continue), and the loop exit (break). | 1515 // loop exit, the loop back edge (continue), and the loop exit (break). |
| 1507 // The CPS translation of [[while (condition) body; successor]] is: | 1516 // The CPS translation of [[while (condition) body; successor]] is: |
| 1508 // | 1517 // |
| 1509 // let cont continue(x, ...) = | 1518 // let cont continue(x, ...) = |
| 1510 // let prim cond = [[condition]] in | 1519 // let prim cond = [[condition]] in |
| 1511 // let cont break(x, ...) = [[successor]] in | 1520 // let cont break(x, ...) = [[successor]] in |
| 1512 // let cont exit() = break(v, ...) | 1521 // let cont exit() = break(v, ...) |
| 1513 // and body() = | 1522 // and body() = |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1542 // Create body entry and loop exit continuations and a branch to them. | 1551 // Create body entry and loop exit continuations and a branch to them. |
| 1543 ir.Continuation exitContinuation = new ir.Continuation([]); | 1552 ir.Continuation exitContinuation = new ir.Continuation([]); |
| 1544 ir.Continuation bodyContinuation = new ir.Continuation([]); | 1553 ir.Continuation bodyContinuation = new ir.Continuation([]); |
| 1545 bodyContinuation.body = bodyBuilder.root; | 1554 bodyContinuation.body = bodyBuilder.root; |
| 1546 // Note the order of continuations: the first one is the one that will | 1555 // Note the order of continuations: the first one is the one that will |
| 1547 // be filled by LetCont.plug. | 1556 // be filled by LetCont.plug. |
| 1548 ir.LetCont branch = | 1557 ir.LetCont branch = |
| 1549 new ir.LetCont.two(exitContinuation, bodyContinuation, | 1558 new ir.LetCont.two(exitContinuation, bodyContinuation, |
| 1550 new ir.Branch.strict(condition, | 1559 new ir.Branch.strict(condition, |
| 1551 bodyContinuation, | 1560 bodyContinuation, |
| 1552 exitContinuation)); | 1561 exitContinuation, |
| 1562 sourceInformation)); |
| 1553 // If there are breaks in the body, then there must be a join-point | 1563 // If there are breaks in the body, then there must be a join-point |
| 1554 // continuation for the normal exit and the breaks. Otherwise, the | 1564 // continuation for the normal exit and the breaks. Otherwise, the |
| 1555 // successor is translated in the hole in the exit continuation. | 1565 // successor is translated in the hole in the exit continuation. |
| 1556 bool hasBreaks = !breakCollector.isEmpty; | 1566 bool hasBreaks = !breakCollector.isEmpty; |
| 1557 ir.LetCont letBreak; | 1567 ir.LetCont letBreak; |
| 1558 if (hasBreaks) { | 1568 if (hasBreaks) { |
| 1559 IrBuilder exitBuilder = makeDelimitedBuilder(); | 1569 IrBuilder exitBuilder = makeDelimitedBuilder(); |
| 1560 exitBuilder.jumpTo(breakCollector); | 1570 exitBuilder.jumpTo(breakCollector); |
| 1561 exitContinuation.body = exitBuilder.root; | 1571 exitContinuation.body = exitBuilder.root; |
| 1562 letBreak = new ir.LetCont(breakCollector.continuation, branch); | 1572 letBreak = new ir.LetCont(breakCollector.continuation, branch); |
| 1563 add(letBreak); | 1573 add(letBreak); |
| 1564 environment = breakCollector.environment; | 1574 environment = breakCollector.environment; |
| 1565 } else { | 1575 } else { |
| 1566 add(branch); | 1576 add(branch); |
| 1567 } | 1577 } |
| 1568 } | 1578 } |
| 1569 | 1579 |
| 1570 | 1580 |
| 1571 /// Creates a do-while loop. | 1581 /// Creates a do-while loop. |
| 1572 /// | 1582 /// |
| 1573 /// The body and condition are created by [buildBody] and [buildCondition]. | 1583 /// The body and condition are created by [buildBody] and [buildCondition]. |
| 1574 /// The jump target [target] is the target of `break` and `continue` | 1584 /// The jump target [target] is the target of `break` and `continue` |
| 1575 /// statements in the body that have the loop as their target. | 1585 /// statements in the body that have the loop as their target. |
| 1576 /// [closureScope] contains all the variables declared in the loop (but not | 1586 /// [closureScope] contains all the variables declared in the loop (but not |
| 1577 /// declared in some inner closure scope). | 1587 /// declared in some inner closure scope). |
| 1578 void buildDoWhile({SubbuildFunction buildBody, | 1588 void buildDoWhile({SubbuildFunction buildBody, |
| 1579 SubbuildFunction buildCondition, | 1589 SubbuildFunction buildCondition, |
| 1580 JumpTarget target, | 1590 JumpTarget target, |
| 1581 ClosureScope closureScope}) { | 1591 ClosureScope closureScope, |
| 1592 SourceInformation sourceInformation}) { |
| 1582 assert(isOpen); | 1593 assert(isOpen); |
| 1583 // The CPS translation of [[do body; while (condition); successor]] is: | 1594 // The CPS translation of [[do body; while (condition); successor]] is: |
| 1584 // | 1595 // |
| 1585 // let cont break(x, ...) = [[successor]] in | 1596 // let cont break(x, ...) = [[successor]] in |
| 1586 // let cont rec loop(x, ...) = | 1597 // let cont rec loop(x, ...) = |
| 1587 // let cont continue(x, ...) = | 1598 // let cont continue(x, ...) = |
| 1588 // let prim cond = [[condition]] in | 1599 // let prim cond = [[condition]] in |
| 1589 // let cont exit() = break(v, ...) | 1600 // let cont exit() = break(v, ...) |
| 1590 // and repeat() = loop(v, ...) | 1601 // and repeat() = loop(v, ...) |
| 1591 // in branch cond (repeat, exit) | 1602 // in branch cond (repeat, exit) |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1628 exitContinuation.body = exitBuilder.root; | 1639 exitContinuation.body = exitBuilder.root; |
| 1629 ir.Continuation repeatContinuation = new ir.Continuation([]); | 1640 ir.Continuation repeatContinuation = new ir.Continuation([]); |
| 1630 IrBuilder repeatBuilder = continueBuilder.makeDelimitedBuilder(); | 1641 IrBuilder repeatBuilder = continueBuilder.makeDelimitedBuilder(); |
| 1631 repeatBuilder.jumpTo(loop); | 1642 repeatBuilder.jumpTo(loop); |
| 1632 repeatContinuation.body = repeatBuilder.root; | 1643 repeatContinuation.body = repeatBuilder.root; |
| 1633 | 1644 |
| 1634 continueBuilder.add( | 1645 continueBuilder.add( |
| 1635 new ir.LetCont.two(exitContinuation, repeatContinuation, | 1646 new ir.LetCont.two(exitContinuation, repeatContinuation, |
| 1636 new ir.Branch.strict(condition, | 1647 new ir.Branch.strict(condition, |
| 1637 repeatContinuation, | 1648 repeatContinuation, |
| 1638 exitContinuation))); | 1649 exitContinuation, |
| 1650 sourceInformation))); |
| 1639 continueCollector.continuation.body = continueBuilder.root; | 1651 continueCollector.continuation.body = continueBuilder.root; |
| 1640 | 1652 |
| 1641 // Construct the loop continuation (i.e., the body and condition). | 1653 // Construct the loop continuation (i.e., the body and condition). |
| 1642 // <Loop> = | 1654 // <Loop> = |
| 1643 // let cont continue(x, ...) = | 1655 // let cont continue(x, ...) = |
| 1644 // <Continue> | 1656 // <Continue> |
| 1645 // in [[body]]; continue(v, ...) | 1657 // in [[body]]; continue(v, ...) |
| 1646 loopBuilder.add( | 1658 loopBuilder.add( |
| 1647 new ir.LetCont(continueCollector.continuation, | 1659 new ir.LetCont(continueCollector.continuation, |
| 1648 bodyBuilder.root)); | 1660 bodyBuilder.root)); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1663 ir.Continuation thenContinuation = new ir.Continuation([]); | 1675 ir.Continuation thenContinuation = new ir.Continuation([]); |
| 1664 thenContinuation.body = thenBuilder.root; | 1676 thenContinuation.body = thenBuilder.root; |
| 1665 ir.Continuation elseContinuation = new ir.Continuation([]); | 1677 ir.Continuation elseContinuation = new ir.Continuation([]); |
| 1666 // A LetCont.two term has a hole as the body of the first listed | 1678 // A LetCont.two term has a hole as the body of the first listed |
| 1667 // continuation, to be plugged by the translation. Therefore put the | 1679 // continuation, to be plugged by the translation. Therefore put the |
| 1668 // else continuation first. | 1680 // else continuation first. |
| 1669 casesBuilder.add( | 1681 casesBuilder.add( |
| 1670 new ir.LetCont.two(elseContinuation, thenContinuation, | 1682 new ir.LetCont.two(elseContinuation, thenContinuation, |
| 1671 new ir.Branch.strict(condition, | 1683 new ir.Branch.strict(condition, |
| 1672 thenContinuation, | 1684 thenContinuation, |
| 1673 elseContinuation))); | 1685 elseContinuation, |
| 1686 caseInfo.sourceInformation))); |
| 1674 } | 1687 } |
| 1675 | 1688 |
| 1676 if (buildDefaultBody == null) { | 1689 if (buildDefaultBody == null) { |
| 1677 casesBuilder.jumpTo(join); | 1690 casesBuilder.jumpTo(join); |
| 1678 } else { | 1691 } else { |
| 1679 buildDefaultBody(casesBuilder); | 1692 buildDefaultBody(casesBuilder); |
| 1680 } | 1693 } |
| 1681 | 1694 |
| 1682 if (!join.isEmpty) { | 1695 if (!join.isEmpty) { |
| 1683 add(new ir.LetCont(join.continuation, casesBuilder.root)); | 1696 add(new ir.LetCont(join.continuation, casesBuilder.root)); |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1872 // it. | 1885 // it. |
| 1873 IrBuilder checkBuilder = builder.makeDelimitedBuilder(environment); | 1886 IrBuilder checkBuilder = builder.makeDelimitedBuilder(environment); |
| 1874 ir.Primitive typeMatches = | 1887 ir.Primitive typeMatches = |
| 1875 checkBuilder.buildTypeOperator(exceptionParameter, | 1888 checkBuilder.buildTypeOperator(exceptionParameter, |
| 1876 clause.type, | 1889 clause.type, |
| 1877 clause.sourceInformation, | 1890 clause.sourceInformation, |
| 1878 isTypeTest: true); | 1891 isTypeTest: true); |
| 1879 checkBuilder.add(new ir.LetCont.two(thenContinuation, elseContinuation, | 1892 checkBuilder.add(new ir.LetCont.two(thenContinuation, elseContinuation, |
| 1880 new ir.Branch.strict(typeMatches, | 1893 new ir.Branch.strict(typeMatches, |
| 1881 thenContinuation, | 1894 thenContinuation, |
| 1882 elseContinuation))); | 1895 elseContinuation, |
| 1896 clause.sourceInformation))); |
| 1883 catchBody = checkBuilder.root; | 1897 catchBody = checkBuilder.root; |
| 1884 } | 1898 } |
| 1885 builder.add(catchBody); | 1899 builder.add(catchBody); |
| 1886 | 1900 |
| 1887 return <ir.Parameter>[exceptionParameter, traceParameter]; | 1901 return <ir.Parameter>[exceptionParameter, traceParameter]; |
| 1888 } | 1902 } |
| 1889 | 1903 |
| 1890 void leaveTryCatch(IrBuilder builder, JumpCollector join, | 1904 void leaveTryCatch(IrBuilder builder, JumpCollector join, |
| 1891 ir.Expression body) { | 1905 ir.Expression body) { |
| 1892 // Add the binding for the join-point continuation and continue the | 1906 // Add the binding for the join-point continuation and continue the |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2269 return param; | 2283 return param; |
| 2270 } | 2284 } |
| 2271 | 2285 |
| 2272 void buildRethrow() { | 2286 void buildRethrow() { |
| 2273 assert(isOpen); | 2287 assert(isOpen); |
| 2274 add(new ir.Rethrow()); | 2288 add(new ir.Rethrow()); |
| 2275 _current = null; | 2289 _current = null; |
| 2276 } | 2290 } |
| 2277 | 2291 |
| 2278 /// Create a negation of [condition]. | 2292 /// Create a negation of [condition]. |
| 2279 ir.Primitive buildNegation(ir.Primitive condition) { | 2293 ir.Primitive buildNegation( |
| 2294 ir.Primitive condition, |
| 2295 SourceInformation sourceInformation) { |
| 2280 // ! e is translated as e ? false : true | 2296 // ! e is translated as e ? false : true |
| 2281 | 2297 |
| 2282 // Add a continuation parameter for the result of the expression. | 2298 // Add a continuation parameter for the result of the expression. |
| 2283 ir.Parameter resultParameter = new ir.Parameter(null); | 2299 ir.Parameter resultParameter = new ir.Parameter(null); |
| 2284 | 2300 |
| 2285 ir.Continuation joinContinuation = new ir.Continuation([resultParameter]); | 2301 ir.Continuation joinContinuation = new ir.Continuation([resultParameter]); |
| 2286 ir.Continuation thenContinuation = new ir.Continuation([]); | 2302 ir.Continuation thenContinuation = new ir.Continuation([]); |
| 2287 ir.Continuation elseContinuation = new ir.Continuation([]); | 2303 ir.Continuation elseContinuation = new ir.Continuation([]); |
| 2288 | 2304 |
| 2289 ir.Constant makeBoolConstant(bool value) { | 2305 ir.Constant makeBoolConstant(bool value) { |
| 2290 return new ir.Constant(state.constantSystem.createBool(value)); | 2306 return new ir.Constant(state.constantSystem.createBool(value)); |
| 2291 } | 2307 } |
| 2292 | 2308 |
| 2293 ir.Constant trueConstant = makeBoolConstant(true); | 2309 ir.Constant trueConstant = makeBoolConstant(true); |
| 2294 ir.Constant falseConstant = makeBoolConstant(false); | 2310 ir.Constant falseConstant = makeBoolConstant(false); |
| 2295 | 2311 |
| 2296 thenContinuation.body = new ir.LetPrim(falseConstant) | 2312 thenContinuation.body = new ir.LetPrim(falseConstant) |
| 2297 ..plug(new ir.InvokeContinuation(joinContinuation, [falseConstant])); | 2313 ..plug(new ir.InvokeContinuation(joinContinuation, [falseConstant])); |
| 2298 elseContinuation.body = new ir.LetPrim(trueConstant) | 2314 elseContinuation.body = new ir.LetPrim(trueConstant) |
| 2299 ..plug(new ir.InvokeContinuation(joinContinuation, [trueConstant])); | 2315 ..plug(new ir.InvokeContinuation(joinContinuation, [trueConstant])); |
| 2300 | 2316 |
| 2301 add(new ir.LetCont(joinContinuation, | 2317 add(new ir.LetCont(joinContinuation, |
| 2302 new ir.LetCont.two(thenContinuation, elseContinuation, | 2318 new ir.LetCont.two(thenContinuation, elseContinuation, |
| 2303 new ir.Branch.strict(condition, | 2319 new ir.Branch.strict(condition, |
| 2304 thenContinuation, | 2320 thenContinuation, |
| 2305 elseContinuation)))); | 2321 elseContinuation, |
| 2322 sourceInformation)))); |
| 2306 return resultParameter; | 2323 return resultParameter; |
| 2307 } | 2324 } |
| 2308 | 2325 |
| 2309 /// Create a lazy and/or expression. [leftValue] is the value of the left | 2326 /// Create a lazy and/or expression. [leftValue] is the value of the left |
| 2310 /// operand and [buildRightValue] is called to process the value of the right | 2327 /// operand and [buildRightValue] is called to process the value of the right |
| 2311 /// operand in the context of its own [IrBuilder]. | 2328 /// operand in the context of its own [IrBuilder]. |
| 2312 ir.Primitive buildLogicalOperator( | 2329 ir.Primitive buildLogicalOperator( |
| 2313 ir.Primitive leftValue, | 2330 ir.Primitive leftValue, |
| 2314 ir.Primitive buildRightValue(IrBuilder builder), | 2331 ir.Primitive buildRightValue(IrBuilder builder), |
| 2332 SourceInformation sourceInformation, |
| 2315 {bool isLazyOr: false}) { | 2333 {bool isLazyOr: false}) { |
| 2316 // e0 && e1 is translated as if e0 ? (e1 == true) : false. | 2334 // e0 && e1 is translated as if e0 ? (e1 == true) : false. |
| 2317 // e0 || e1 is translated as if e0 ? true : (e1 == true). | 2335 // e0 || e1 is translated as if e0 ? true : (e1 == true). |
| 2318 // The translation must convert both e0 and e1 to booleans and handle | 2336 // The translation must convert both e0 and e1 to booleans and handle |
| 2319 // local variable assignments in e1. | 2337 // local variable assignments in e1. |
| 2320 IrBuilder rightBuilder = makeDelimitedBuilder(); | 2338 IrBuilder rightBuilder = makeDelimitedBuilder(); |
| 2321 ir.Primitive rightValue = buildRightValue(rightBuilder); | 2339 ir.Primitive rightValue = buildRightValue(rightBuilder); |
| 2322 // A dummy empty target for the branch on the left subexpression branch. | 2340 // A dummy empty target for the branch on the left subexpression branch. |
| 2323 // This enables using the same infrastructure for join-point continuations | 2341 // This enables using the same infrastructure for join-point continuations |
| 2324 // as in visitIf and visitConditional. It will hold a definition of the | 2342 // as in visitIf and visitConditional. It will hold a definition of the |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2355 ir.Continuation leftFalseContinuation = new ir.Continuation([]); | 2373 ir.Continuation leftFalseContinuation = new ir.Continuation([]); |
| 2356 ir.Continuation rightTrueContinuation = new ir.Continuation([]); | 2374 ir.Continuation rightTrueContinuation = new ir.Continuation([]); |
| 2357 ir.Continuation rightFalseContinuation = new ir.Continuation([]); | 2375 ir.Continuation rightFalseContinuation = new ir.Continuation([]); |
| 2358 rightTrueContinuation.body = rightTrueBuilder.root; | 2376 rightTrueContinuation.body = rightTrueBuilder.root; |
| 2359 rightFalseContinuation.body = rightFalseBuilder.root; | 2377 rightFalseContinuation.body = rightFalseBuilder.root; |
| 2360 // The right subexpression has two continuations. | 2378 // The right subexpression has two continuations. |
| 2361 rightBuilder.add( | 2379 rightBuilder.add( |
| 2362 new ir.LetCont.two(rightTrueContinuation, rightFalseContinuation, | 2380 new ir.LetCont.two(rightTrueContinuation, rightFalseContinuation, |
| 2363 new ir.Branch.strict(rightValue, | 2381 new ir.Branch.strict(rightValue, |
| 2364 rightTrueContinuation, | 2382 rightTrueContinuation, |
| 2365 rightFalseContinuation))); | 2383 rightFalseContinuation, |
| 2384 sourceInformation))); |
| 2366 // Depending on the operator, the left subexpression's continuations are | 2385 // Depending on the operator, the left subexpression's continuations are |
| 2367 // either the right subexpression or an invocation of the join-point | 2386 // either the right subexpression or an invocation of the join-point |
| 2368 // continuation. | 2387 // continuation. |
| 2369 if (isLazyOr) { | 2388 if (isLazyOr) { |
| 2370 leftTrueContinuation.body = emptyBuilder.root; | 2389 leftTrueContinuation.body = emptyBuilder.root; |
| 2371 leftFalseContinuation.body = rightBuilder.root; | 2390 leftFalseContinuation.body = rightBuilder.root; |
| 2372 } else { | 2391 } else { |
| 2373 leftTrueContinuation.body = rightBuilder.root; | 2392 leftTrueContinuation.body = rightBuilder.root; |
| 2374 leftFalseContinuation.body = emptyBuilder.root; | 2393 leftFalseContinuation.body = emptyBuilder.root; |
| 2375 } | 2394 } |
| 2376 | 2395 |
| 2377 add(new ir.LetCont(join.continuation, | 2396 add(new ir.LetCont(join.continuation, |
| 2378 new ir.LetCont.two(leftTrueContinuation, leftFalseContinuation, | 2397 new ir.LetCont.two(leftTrueContinuation, leftFalseContinuation, |
| 2379 new ir.Branch.strict(leftValue, | 2398 new ir.Branch.strict(leftValue, |
| 2380 leftTrueContinuation, | 2399 leftTrueContinuation, |
| 2381 leftFalseContinuation)))); | 2400 leftFalseContinuation, |
| 2401 sourceInformation)))); |
| 2382 environment = join.environment; | 2402 environment = join.environment; |
| 2383 return environment.discard(1); | 2403 return environment.discard(1); |
| 2384 } | 2404 } |
| 2385 | 2405 |
| 2386 ir.Primitive buildIdentical(ir.Primitive x, ir.Primitive y, | 2406 ir.Primitive buildIdentical(ir.Primitive x, ir.Primitive y, |
| 2387 {SourceInformation sourceInformation}) { | 2407 {SourceInformation sourceInformation}) { |
| 2388 return addPrimitive(new ir.ApplyBuiltinOperator( | 2408 return addPrimitive(new ir.ApplyBuiltinOperator( |
| 2389 ir.BuiltinOperator.Identical, <ir.Primitive>[x, y], | 2409 ir.BuiltinOperator.Identical, <ir.Primitive>[x, y], |
| 2390 sourceInformation)); | 2410 sourceInformation)); |
| 2391 } | 2411 } |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2848 // For type tests, we must treat specially the rare cases where `null` | 2868 // For type tests, we must treat specially the rare cases where `null` |
| 2849 // satisfies the test (which otherwise never satisfies a type test). | 2869 // satisfies the test (which otherwise never satisfies a type test). |
| 2850 // This is not an optimization: the TypeOperator assumes that `null` | 2870 // This is not an optimization: the TypeOperator assumes that `null` |
| 2851 // cannot satisfy the type test unless the type is a type variable. | 2871 // cannot satisfy the type test unless the type is a type variable. |
| 2852 if (type.isObject || type.isDynamic) { | 2872 if (type.isObject || type.isDynamic) { |
| 2853 // `x is Object` and `x is dynamic` are always true, even if x is null. | 2873 // `x is Object` and `x is dynamic` are always true, even if x is null. |
| 2854 return buildBooleanConstant(true); | 2874 return buildBooleanConstant(true); |
| 2855 } | 2875 } |
| 2856 if (type is InterfaceType && type.element == program.nullClass) { | 2876 if (type is InterfaceType && type.element == program.nullClass) { |
| 2857 // `x is Null` is true if and only if x is null. | 2877 // `x is Null` is true if and only if x is null. |
| 2858 return _buildCheckNull(value); | 2878 return _buildCheckNull(value, sourceInformation); |
| 2859 } | 2879 } |
| 2860 return addPrimitive(new ir.TypeTest(value, type, typeArguments)); | 2880 return addPrimitive(new ir.TypeTest(value, type, typeArguments)); |
| 2861 } else { | 2881 } else { |
| 2862 if (type.isObject || type.isDynamic) { | 2882 if (type.isObject || type.isDynamic) { |
| 2863 // `x as Object` and `x as dynamic` are the same as `x`. | 2883 // `x as Object` and `x as dynamic` are the same as `x`. |
| 2864 return value; | 2884 return value; |
| 2865 } | 2885 } |
| 2866 return addPrimitive(new ir.TypeCast(value, type, typeArguments)); | 2886 return addPrimitive(new ir.TypeCast(value, type, typeArguments)); |
| 2867 } | 2887 } |
| 2868 } | 2888 } |
| 2869 | 2889 |
| 2870 /// Create an if-null expression. This is equivalent to a conditional | 2890 /// Create an if-null expression. This is equivalent to a conditional |
| 2871 /// expression whose result is either [value] if [value] is not null, or | 2891 /// expression whose result is either [value] if [value] is not null, or |
| 2872 /// `right` if [value] is null. Only when [value] is null, [buildRight] is | 2892 /// `right` if [value] is null. Only when [value] is null, [buildRight] is |
| 2873 /// evaluated to produce the `right` value. | 2893 /// evaluated to produce the `right` value. |
| 2874 ir.Primitive buildIfNull(ir.Primitive value, | 2894 ir.Primitive buildIfNull(ir.Primitive value, |
| 2875 ir.Primitive buildRight(IrBuilder builder), | 2895 ir.Primitive buildRight(IrBuilder builder), |
| 2876 {SourceInformation sourceInformation}) { | 2896 SourceInformation sourceInformation) { |
| 2877 ir.Primitive condition = | 2897 ir.Primitive condition = |
| 2878 _buildCheckNull(value, sourceInformation: sourceInformation); | 2898 _buildCheckNull(value, sourceInformation); |
| 2879 return buildConditional(condition, buildRight, (_) => value); | 2899 return buildConditional( |
| 2900 condition, buildRight, (_) => value, sourceInformation); |
| 2880 } | 2901 } |
| 2881 | 2902 |
| 2882 /// Create a conditional send. This is equivalent to a conditional expression | 2903 /// Create a conditional send. This is equivalent to a conditional expression |
| 2883 /// that checks if [receiver] is null, if so, it returns null, otherwise it | 2904 /// that checks if [receiver] is null, if so, it returns null, otherwise it |
| 2884 /// evaluates the [buildSend] expression. | 2905 /// evaluates the [buildSend] expression. |
| 2885 ir.Primitive buildIfNotNullSend(ir.Primitive receiver, | 2906 ir.Primitive buildIfNotNullSend(ir.Primitive receiver, |
| 2886 ir.Primitive buildSend(IrBuilder builder), | 2907 ir.Primitive buildSend(IrBuilder builder), |
| 2887 {SourceInformation sourceInformation}) { | 2908 SourceInformation sourceInformation) { |
| 2888 ir.Primitive condition = | 2909 ir.Primitive condition = |
| 2889 _buildCheckNull(receiver, sourceInformation: sourceInformation); | 2910 _buildCheckNull(receiver, sourceInformation); |
| 2890 return buildConditional(condition, (_) => receiver, buildSend); | 2911 return buildConditional( |
| 2912 condition, (_) => receiver, buildSend, sourceInformation); |
| 2891 } | 2913 } |
| 2892 | 2914 |
| 2893 /// Creates a type test checking whether [value] is null. | 2915 /// Creates a type test checking whether [value] is null. |
| 2894 ir.Primitive _buildCheckNull(ir.Primitive value, | 2916 ir.Primitive _buildCheckNull(ir.Primitive value, |
| 2895 {SourceInformation sourceInformation}) { | 2917 SourceInformation sourceInformation) { |
| 2896 assert(isOpen); | 2918 assert(isOpen); |
| 2897 return buildIdentical(value, buildNullConstant(), | 2919 return buildIdentical(value, buildNullConstant(), |
| 2898 sourceInformation: sourceInformation); | 2920 sourceInformation: sourceInformation); |
| 2899 } | 2921 } |
| 2900 } | 2922 } |
| 2901 | 2923 |
| 2902 /// Location of a variable relative to a given closure. | 2924 /// Location of a variable relative to a given closure. |
| 2903 class ClosureLocation { | 2925 class ClosureLocation { |
| 2904 /// If not `null`, this location is [box].[field]. | 2926 /// If not `null`, this location is [box].[field]. |
| 2905 /// The location of [box] can be obtained separately from an | 2927 /// The location of [box] can be obtained separately from an |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2998 CatchClauseInfo({this.type, | 3020 CatchClauseInfo({this.type, |
| 2999 this.exceptionVariable, | 3021 this.exceptionVariable, |
| 3000 this.stackTraceVariable, | 3022 this.stackTraceVariable, |
| 3001 this.buildCatchBlock, | 3023 this.buildCatchBlock, |
| 3002 this.sourceInformation}); | 3024 this.sourceInformation}); |
| 3003 } | 3025 } |
| 3004 | 3026 |
| 3005 class SwitchCaseInfo { | 3027 class SwitchCaseInfo { |
| 3006 final SubbuildFunction buildCondition; | 3028 final SubbuildFunction buildCondition; |
| 3007 final SubbuildFunction buildBody; | 3029 final SubbuildFunction buildBody; |
| 3030 final SourceInformation sourceInformation; |
| 3008 | 3031 |
| 3009 SwitchCaseInfo(this.buildCondition, this.buildBody); | 3032 SwitchCaseInfo(this.buildCondition, this.buildBody, this.sourceInformation); |
| 3010 } | 3033 } |
| OLD | NEW |