OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
4 | 4 |
5 import 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
6 import 'package:kernel/frontend/accessors.dart' | 6 import 'package:kernel/frontend/accessors.dart' |
7 show | 7 show |
8 Accessor, | 8 Accessor, |
9 IndexAccessor, | 9 IndexAccessor, |
10 NullAwarePropertyAccessor, | 10 NullAwarePropertyAccessor, |
11 PropertyAccessor, | 11 PropertyAccessor, |
12 ReadOnlyAccessor, | 12 ReadOnlyAccessor, |
13 StaticAccessor, | 13 StaticAccessor, |
14 SuperIndexAccessor, | 14 SuperIndexAccessor, |
15 SuperPropertyAccessor, | 15 SuperPropertyAccessor, |
16 ThisPropertyAccessor, | 16 ThisPropertyAccessor, |
17 VariableAccessor, | 17 VariableAccessor, |
18 buildIsNull, | 18 buildIsNull, |
19 makeBinary, | 19 makeBinary, |
20 makeLet, | 20 makeLet, |
21 makeOrReuseVariable; | 21 makeOrReuseVariable; |
22 import 'package:kernel/transformations/flags.dart'; | 22 import 'package:kernel/transformations/flags.dart'; |
23 | 23 |
24 import '../common.dart'; | 24 import '../common.dart'; |
| 25 import '../common/names.dart'; |
25 import '../constants/expressions.dart' | 26 import '../constants/expressions.dart' |
26 show | 27 show |
27 BoolFromEnvironmentConstantExpression, | 28 BoolFromEnvironmentConstantExpression, |
28 ConstantExpression, | 29 ConstantExpression, |
29 ConstructedConstantExpression, | 30 ConstructedConstantExpression, |
30 IntFromEnvironmentConstantExpression, | 31 IntFromEnvironmentConstantExpression, |
31 StringFromEnvironmentConstantExpression, | 32 StringFromEnvironmentConstantExpression, |
32 TypeConstantExpression; | 33 TypeConstantExpression; |
33 import '../dart_types.dart' show DartType, InterfaceType; | 34 import '../dart_types.dart' show DartType, InterfaceType; |
34 import '../diagnostics/spannable.dart' show Spannable; | 35 import '../diagnostics/spannable.dart' show Spannable; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 TryStatement, | 139 TryStatement, |
139 TypeAnnotation, | 140 TypeAnnotation, |
140 TypeVariable, | 141 TypeVariable, |
141 VariableDefinitions, | 142 VariableDefinitions, |
142 While, | 143 While, |
143 Yield; | 144 Yield; |
144 import '../universe/call_structure.dart' show CallStructure; | 145 import '../universe/call_structure.dart' show CallStructure; |
145 import '../universe/selector.dart' show Selector; | 146 import '../universe/selector.dart' show Selector; |
146 import '../util/util.dart' show Link; | 147 import '../util/util.dart' show Link; |
147 import 'error.dart' show KernelError; | 148 import 'error.dart' show KernelError; |
148 import 'fall_through_visitor.dart' show fallsThrough; | |
149 import 'kernel.dart' show ConstructorTarget, Kernel; | 149 import 'kernel.dart' show ConstructorTarget, Kernel; |
150 import 'unavailable.dart' show UnavailableVisitor; | 150 import 'unavailable.dart' show UnavailableVisitor; |
151 import 'unresolved.dart' show UnresolvedVisitor; | 151 import 'unresolved.dart' show UnresolvedVisitor; |
152 | 152 |
153 /// Translates dart2js AST nodes [Node] into Kernel IR [ir.TreeNode]. | 153 /// Translates dart2js AST nodes [Node] into Kernel IR [ir.TreeNode]. |
154 /// | 154 /// |
155 /// Most methods in this class have a prefix that follows these conventions: | 155 /// Most methods in this class have a prefix that follows these conventions: |
156 /// | 156 /// |
157 /// * `visit` for overridden visitor methods. | 157 /// * `visit` for overridden visitor methods. |
158 /// * `handle` for methods that implement common behavior for several `visit` | 158 /// * `handle` for methods that implement common behavior for several `visit` |
(...skipping 829 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
988 // [Label]. We ignore cases, as any users have been resolved to use the | 988 // [Label]. We ignore cases, as any users have been resolved to use the |
989 // case directly. | 989 // case directly. |
990 assert(labelOrCase.asLabel() != null); | 990 assert(labelOrCase.asLabel() != null); |
991 } | 991 } |
992 } | 992 } |
993 // We ignore the node's statements here, they're generated below in | 993 // We ignore the node's statements here, they're generated below in |
994 // [visitSwitchStatement] once we've set up all the jump targets. | 994 // [visitSwitchStatement] once we've set up all the jump targets. |
995 return new ir.SwitchCase(expressions, null, isDefault: node.isDefaultCase); | 995 return new ir.SwitchCase(expressions, null, isDefault: node.isDefaultCase); |
996 } | 996 } |
997 | 997 |
| 998 /// Returns true if [node] would let execution reach the next node (aka |
| 999 /// fall-through in switch cases). |
| 1000 bool fallsThrough(ir.Statement node) { |
| 1001 return !(node is ir.BreakStatement || |
| 1002 node is ir.ReturnStatement || |
| 1003 node is ir.ContinueSwitchStatement || |
| 1004 (node is ir.ExpressionStatement && node.expression is ir.Throw)); |
| 1005 } |
| 1006 |
998 @override | 1007 @override |
999 ir.Statement visitSwitchStatement(SwitchStatement node) { | 1008 ir.Statement visitSwitchStatement(SwitchStatement node) { |
1000 ir.Expression expression = visitForValue(node.expression); | 1009 ir.Expression expression = visitForValue(node.expression); |
1001 List<ir.SwitchCase> cases = <ir.SwitchCase>[]; | 1010 List<ir.SwitchCase> cases = <ir.SwitchCase>[]; |
1002 for (SwitchCase caseNode in node.cases.nodes) { | 1011 for (SwitchCase caseNode in node.cases.nodes) { |
1003 cases.add(caseNode.accept(this)); | 1012 cases.add(caseNode.accept(this)); |
1004 JumpTarget jumpTarget = elements.getTargetDefinition(caseNode); | 1013 JumpTarget jumpTarget = elements.getTargetDefinition(caseNode); |
1005 if (jumpTarget != null) { | 1014 if (jumpTarget != null) { |
1006 assert(jumpTarget.isContinueTarget); | 1015 assert(jumpTarget.isContinueTarget); |
1007 assert(!continueSwitchTargets.containsKey(jumpTarget)); | 1016 assert(!continueSwitchTargets.containsKey(jumpTarget)); |
(...skipping 11 matching lines...) Expand all Loading... |
1019 internalError(caseNode, "case node mismatch"); | 1028 internalError(caseNode, "case node mismatch"); |
1020 } | 1029 } |
1021 ir.SwitchCase irCase = casesIterator.current; | 1030 ir.SwitchCase irCase = casesIterator.current; |
1022 List<ir.Statement> statements = <ir.Statement>[]; | 1031 List<ir.Statement> statements = <ir.Statement>[]; |
1023 bool hasVariableDeclaration = false; | 1032 bool hasVariableDeclaration = false; |
1024 for (Statement statement in caseNode.statements.nodes) { | 1033 for (Statement statement in caseNode.statements.nodes) { |
1025 if (buildStatement(statement, statements)) { | 1034 if (buildStatement(statement, statements)) { |
1026 hasVariableDeclaration = true; | 1035 hasVariableDeclaration = true; |
1027 } | 1036 } |
1028 } | 1037 } |
1029 if (!isLastCase && | 1038 if (statements.isEmpty || fallsThrough(statements.last)) { |
1030 (statements.isEmpty || fallsThrough(statements.last))) { | 1039 if (isLastCase) { |
1031 statements.add(new ir.ExpressionStatement(new ir.Throw( | 1040 statements.add(new ir.BreakStatement( |
1032 new ir.StaticInvocation(kernel.getFallThroughErrorBuilder(), | 1041 getBreakTarget(elements.getTargetDefinition(node)))); |
1033 new ir.Arguments.empty())))); | 1042 } else { |
| 1043 statements.add(new ir.ExpressionStatement(new ir.Throw( |
| 1044 new ir.ConstructorInvocation( |
| 1045 kernel.getFallThroughErrorConstructor(), |
| 1046 new ir.Arguments.empty())))); |
| 1047 } |
1034 } | 1048 } |
1035 ir.Statement body; | 1049 ir.Statement body = new ir.Block(statements); |
1036 if (!hasVariableDeclaration && statements.length == 1) { | |
1037 body = statements.single; | |
1038 } else { | |
1039 body = new ir.Block(statements); | |
1040 } | |
1041 irCase.body = body; | 1050 irCase.body = body; |
1042 body.parent = irCase; | 1051 body.parent = irCase; |
1043 } | 1052 } |
1044 assert(!casesIterator.moveNext()); | 1053 assert(!casesIterator.moveNext()); |
1045 | 1054 |
1046 return buildBreakTarget(new ir.SwitchStatement(expression, cases), node, | 1055 return buildBreakTarget(new ir.SwitchStatement(expression, cases), node, |
1047 elements.getTargetDefinition(node)); | 1056 elements.getTargetDefinition(node)); |
1048 } | 1057 } |
1049 | 1058 |
1050 @override | 1059 @override |
(...skipping 984 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2035 function, "Unknown async maker: ${function.asyncMarker}"); | 2044 function, "Unknown async maker: ${function.asyncMarker}"); |
2036 break; | 2045 break; |
2037 } | 2046 } |
2038 } | 2047 } |
2039 ir.Statement body; | 2048 ir.Statement body; |
2040 if (function.isExternal) { | 2049 if (function.isExternal) { |
2041 // [body] must be `null`. | 2050 // [body] must be `null`. |
2042 } else if (function.isConstructor) { | 2051 } else if (function.isConstructor) { |
2043 // TODO(johnniwinther): Clean this up pending kernel issue #28. | 2052 // TODO(johnniwinther): Clean this up pending kernel issue #28. |
2044 ConstructorElement constructor = function; | 2053 ConstructorElement constructor = function; |
2045 if (constructor.isDefaultConstructor) { | 2054 if (bodyNode == null || bodyNode.asEmptyStatement() != null) { |
2046 body = new ir.EmptyStatement(); | 2055 body = new ir.EmptyStatement(); |
2047 } else if (bodyNode != null && bodyNode.asEmptyStatement() == null) { | 2056 } else { |
2048 body = buildStatementInBlock(bodyNode); | 2057 body = buildStatementInBlock(bodyNode); |
2049 } | 2058 } |
2050 } else if (bodyNode != null) { | 2059 } else if (bodyNode != null) { |
2051 body = buildStatementInBlock(bodyNode); | 2060 Return returnStatement = bodyNode.asReturn(); |
| 2061 if ((function.isSetter || function.name == Names.INDEX_SET_NAME.text) && |
| 2062 returnStatement != null) { |
| 2063 // Avoid encoding the implicit return of setters with arrow body: |
| 2064 // set setter(value) => this.value = value; |
| 2065 // operator []=(index, value) => this[index] = value; |
| 2066 body = new ir.ExpressionStatement( |
| 2067 visitForEffect(returnStatement.expression)); |
| 2068 } else { |
| 2069 body = buildStatementInBlock(bodyNode); |
| 2070 } |
2052 } | 2071 } |
2053 return associateElement( | 2072 return associateElement( |
2054 new ir.FunctionNode(body, | 2073 new ir.FunctionNode(body, |
2055 asyncMarker: asyncMarker, | 2074 asyncMarker: asyncMarker, |
2056 returnType: returnType, | 2075 returnType: returnType, |
2057 typeParameters: typeParameters, | 2076 typeParameters: typeParameters, |
2058 positionalParameters: positionalParameters, | 2077 positionalParameters: positionalParameters, |
2059 namedParameters: namedParameters, | 2078 namedParameters: namedParameters, |
2060 requiredParameterCount: requiredParameterCount), | 2079 requiredParameterCount: requiredParameterCount), |
2061 function); | 2080 function); |
(...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2776 : this(null, true, node, initializers); | 2795 : this(null, true, node, initializers); |
2777 | 2796 |
2778 accept(ir.Visitor v) => throw "unsupported"; | 2797 accept(ir.Visitor v) => throw "unsupported"; |
2779 | 2798 |
2780 visitChildren(ir.Visitor v) => throw "unsupported"; | 2799 visitChildren(ir.Visitor v) => throw "unsupported"; |
2781 | 2800 |
2782 String toString() { | 2801 String toString() { |
2783 return "IrFunction($kind, $isConstructor, $node, $initializers)"; | 2802 return "IrFunction($kind, $isConstructor, $node, $initializers)"; |
2784 } | 2803 } |
2785 } | 2804 } |
OLD | NEW |