| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 // TODO(johnniwinther): Remove this library when all constant constructors are | 5 // TODO(johnniwinther): Remove this library when all constant constructors are |
| 6 // computed during resolution. | 6 // computed during resolution. |
| 7 library dart2js.constants.constant_constructors; | 7 library dart2js.constants.constant_constructors; |
| 8 | 8 |
| 9 import '../common.dart'; | 9 import '../common.dart'; |
| 10 import '../dart_types.dart'; | 10 import '../dart_types.dart'; |
| 11 import '../elements/elements.dart'; | 11 import '../elements/elements.dart'; |
| 12 import '../resolution/operators.dart'; | 12 import '../resolution/operators.dart'; |
| 13 import '../resolution/semantic_visitor.dart'; | 13 import '../resolution/semantic_visitor.dart'; |
| 14 import '../resolution/send_resolver.dart' show | 14 import '../resolution/send_resolver.dart' show DeclarationResolverMixin; |
| 15 DeclarationResolverMixin; | |
| 16 import '../resolution/send_structure.dart'; | 15 import '../resolution/send_structure.dart'; |
| 17 import '../resolution/tree_elements.dart' show | 16 import '../resolution/tree_elements.dart' show TreeElements; |
| 18 TreeElements; | |
| 19 import '../tree/tree.dart'; | 17 import '../tree/tree.dart'; |
| 20 import '../universe/call_structure.dart' show | 18 import '../universe/call_structure.dart' show CallStructure; |
| 21 CallStructure; | |
| 22 | 19 |
| 23 import 'constructors.dart'; | 20 import 'constructors.dart'; |
| 24 import 'expressions.dart'; | 21 import 'expressions.dart'; |
| 25 | 22 |
| 26 ConstantConstructor computeConstantConstructor(ResolvedAst resolvedAst) { | 23 ConstantConstructor computeConstantConstructor(ResolvedAst resolvedAst) { |
| 27 ConstantConstructorComputer visitor = | 24 ConstantConstructorComputer visitor = |
| 28 new ConstantConstructorComputer(resolvedAst.elements); | 25 new ConstantConstructorComputer(resolvedAst.elements); |
| 29 return resolvedAst.node.accept(visitor); | 26 return resolvedAst.node.accept(visitor); |
| 30 } | 27 } |
| 31 | 28 |
| 32 class ConstantConstructorComputer extends SemanticVisitor | 29 class ConstantConstructorComputer extends SemanticVisitor |
| 33 with SemanticDeclarationResolvedMixin, | 30 with |
| 34 DeclarationResolverMixin, | 31 SemanticDeclarationResolvedMixin, |
| 35 GetBulkMixin, | 32 DeclarationResolverMixin, |
| 36 SetBulkMixin, | 33 GetBulkMixin, |
| 37 ErrorBulkMixin, | 34 SetBulkMixin, |
| 38 InvokeBulkMixin, | 35 ErrorBulkMixin, |
| 39 IndexSetBulkMixin, | 36 InvokeBulkMixin, |
| 40 CompoundBulkMixin, | 37 IndexSetBulkMixin, |
| 41 SetIfNullBulkMixin, | 38 CompoundBulkMixin, |
| 42 UnaryBulkMixin, | 39 SetIfNullBulkMixin, |
| 43 BaseBulkMixin, | 40 UnaryBulkMixin, |
| 44 BinaryBulkMixin, | 41 BaseBulkMixin, |
| 45 PrefixBulkMixin, | 42 BinaryBulkMixin, |
| 46 PostfixBulkMixin, | 43 PrefixBulkMixin, |
| 47 NewBulkMixin, | 44 PostfixBulkMixin, |
| 48 InitializerBulkMixin, | 45 NewBulkMixin, |
| 49 FunctionBulkMixin, | 46 InitializerBulkMixin, |
| 50 VariableBulkMixin | 47 FunctionBulkMixin, |
| 48 VariableBulkMixin |
| 51 implements SemanticDeclarationVisitor, SemanticSendVisitor { | 49 implements SemanticDeclarationVisitor, SemanticSendVisitor { |
| 52 final Map<FieldElement, ConstantExpression> fieldMap = | 50 final Map<FieldElement, ConstantExpression> fieldMap = |
| 53 <FieldElement, ConstantExpression>{}; | 51 <FieldElement, ConstantExpression>{}; |
| 54 final Map<dynamic/*int|String*/, ConstantExpression> defaultValues = | 52 final Map<dynamic /*int|String*/, ConstantExpression> defaultValues = |
| 55 <dynamic/*int|String*/, ConstantExpression>{}; | 53 <dynamic /*int|String*/, ConstantExpression>{}; |
| 56 | 54 |
| 57 ConstantConstructorComputer(TreeElements elements) | 55 ConstantConstructorComputer(TreeElements elements) : super(elements); |
| 58 : super(elements); | |
| 59 | 56 |
| 60 SemanticDeclarationVisitor get declVisitor => this; | 57 SemanticDeclarationVisitor get declVisitor => this; |
| 61 | 58 |
| 62 SemanticSendVisitor get sendVisitor => this; | 59 SemanticSendVisitor get sendVisitor => this; |
| 63 | 60 |
| 64 ClassElement get currentClass => currentConstructor.enclosingClass; | 61 ClassElement get currentClass => currentConstructor.enclosingClass; |
| 65 | 62 |
| 66 ConstructorElement get currentConstructor => elements.analyzedElement; | 63 ConstructorElement get currentConstructor => elements.analyzedElement; |
| 67 | 64 |
| 68 apply(Node node, [_]) => node.accept(this); | 65 apply(Node node, [_]) => node.accept(this); |
| 69 | 66 |
| 70 visitNode(Node node) { | 67 visitNode(Node node) { |
| 71 internalError(node, 'Unhandled node $node: ${node.toDebugString()}'); | 68 internalError(node, 'Unhandled node $node: ${node.toDebugString()}'); |
| 72 } | 69 } |
| 73 | 70 |
| 74 @override | 71 @override |
| 75 bulkHandleNode(Node node, String template, _) { | 72 bulkHandleNode(Node node, String template, _) { |
| 76 internalError(node, template.replaceFirst('#' , '$node')); | 73 internalError(node, template.replaceFirst('#', '$node')); |
| 77 } | 74 } |
| 78 | 75 |
| 79 internalError(Node node, String message) { | 76 internalError(Node node, String message) { |
| 80 throw new UnsupportedError(message); | 77 throw new UnsupportedError(message); |
| 81 } | 78 } |
| 82 | 79 |
| 83 ConstantConstructor visitGenerativeConstructorDeclaration( | 80 ConstantConstructor visitGenerativeConstructorDeclaration( |
| 84 FunctionExpression node, | 81 FunctionExpression node, |
| 85 ConstructorElement constructor, | 82 ConstructorElement constructor, |
| 86 NodeList parameters, | 83 NodeList parameters, |
| 87 NodeList initializers, | 84 NodeList initializers, |
| 88 Node body, | 85 Node body, |
| 89 _) { | 86 _) { |
| 90 applyParameters(parameters, _); | 87 applyParameters(parameters, _); |
| 91 ConstructedConstantExpression constructorInvocation = | 88 ConstructedConstantExpression constructorInvocation = |
| 92 applyInitializers(node, _); | 89 applyInitializers(node, _); |
| 93 return new GenerativeConstantConstructor( | 90 return new GenerativeConstantConstructor( |
| 94 currentClass.thisType, defaultValues, fieldMap, constructorInvocation); | 91 currentClass.thisType, defaultValues, fieldMap, constructorInvocation); |
| 95 } | 92 } |
| 96 | 93 |
| 97 ConstantConstructor visitRedirectingGenerativeConstructorDeclaration( | 94 ConstantConstructor visitRedirectingGenerativeConstructorDeclaration( |
| 98 FunctionExpression node, | 95 FunctionExpression node, |
| 99 ConstructorElement constructor, | 96 ConstructorElement constructor, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 124 arguments.add(new NamedArgumentReference(name)); | 121 arguments.add(new NamedArgumentReference(name)); |
| 125 } else { | 122 } else { |
| 126 arguments.add(new PositionalArgumentReference(index)); | 123 arguments.add(new PositionalArgumentReference(index)); |
| 127 } | 124 } |
| 128 index++; | 125 index++; |
| 129 } | 126 } |
| 130 CallStructure callStructure = new CallStructure(index, argumentNames); | 127 CallStructure callStructure = new CallStructure(index, argumentNames); |
| 131 | 128 |
| 132 return new RedirectingFactoryConstantConstructor( | 129 return new RedirectingFactoryConstantConstructor( |
| 133 new ConstructedConstantExpression( | 130 new ConstructedConstantExpression( |
| 134 redirectionType, | 131 redirectionType, redirectionTarget, callStructure, arguments)); |
| 135 redirectionTarget, | |
| 136 callStructure, | |
| 137 arguments)); | |
| 138 } | 132 } |
| 139 | 133 |
| 140 @override | 134 @override |
| 141 visitFactoryConstructorDeclaration( | 135 visitFactoryConstructorDeclaration(FunctionExpression node, |
| 142 FunctionExpression node, | 136 ConstructorElement constructor, NodeList parameters, Node body, _) { |
| 143 ConstructorElement constructor, | |
| 144 NodeList parameters, | |
| 145 Node body, _) { | |
| 146 // TODO(johnniwinther): Handle constant constructors with errors. | 137 // TODO(johnniwinther): Handle constant constructors with errors. |
| 147 internalError(node, "Factory constructor cannot be constant: $node."); | 138 internalError(node, "Factory constructor cannot be constant: $node."); |
| 148 } | 139 } |
| 149 | 140 |
| 150 applyParameters(NodeList parameters, _) { | 141 applyParameters(NodeList parameters, _) { |
| 151 computeParameterStructures(parameters).forEach((s) => s.dispatch(this, _)); | 142 computeParameterStructures(parameters).forEach((s) => s.dispatch(this, _)); |
| 152 } | 143 } |
| 153 | 144 |
| 154 visitParameterDeclaration( | 145 visitParameterDeclaration(VariableDefinitions node, Node definition, |
| 155 VariableDefinitions node, | 146 ParameterElement parameter, int index, _) { |
| 156 Node definition, | |
| 157 ParameterElement parameter, | |
| 158 int index, | |
| 159 _) { | |
| 160 // Do nothing. | 147 // Do nothing. |
| 161 } | 148 } |
| 162 | 149 |
| 163 visitOptionalParameterDeclaration( | 150 visitOptionalParameterDeclaration( |
| 164 VariableDefinitions node, | 151 VariableDefinitions node, |
| 165 Node definition, | 152 Node definition, |
| 166 ParameterElement parameter, | 153 ParameterElement parameter, |
| 167 ConstantExpression defaultValue, | 154 ConstantExpression defaultValue, |
| 168 int index, | 155 int index, |
| 169 _) { | 156 _) { |
| 170 assert(invariant(node, defaultValue != null)); | 157 assert(invariant(node, defaultValue != null)); |
| 171 defaultValues[index] = defaultValue; | 158 defaultValues[index] = defaultValue; |
| 172 } | 159 } |
| 173 | 160 |
| 174 visitNamedParameterDeclaration( | 161 visitNamedParameterDeclaration(VariableDefinitions node, Node definition, |
| 175 VariableDefinitions node, | 162 ParameterElement parameter, ConstantExpression defaultValue, _) { |
| 176 Node definition, | |
| 177 ParameterElement parameter, | |
| 178 ConstantExpression defaultValue, | |
| 179 _) { | |
| 180 assert(invariant(node, defaultValue != null)); | 163 assert(invariant(node, defaultValue != null)); |
| 181 String name = parameter.name; | 164 String name = parameter.name; |
| 182 defaultValues[name] = defaultValue; | 165 defaultValues[name] = defaultValue; |
| 183 } | 166 } |
| 184 | 167 |
| 185 visitInitializingFormalDeclaration( | 168 visitInitializingFormalDeclaration(VariableDefinitions node, Node definition, |
| 186 VariableDefinitions node, | 169 InitializingFormalElement parameter, int index, _) { |
| 187 Node definition, | |
| 188 InitializingFormalElement parameter, | |
| 189 int index, | |
| 190 _) { | |
| 191 fieldMap[parameter.fieldElement] = new PositionalArgumentReference(index); | 170 fieldMap[parameter.fieldElement] = new PositionalArgumentReference(index); |
| 192 } | 171 } |
| 193 | 172 |
| 194 visitOptionalInitializingFormalDeclaration( | 173 visitOptionalInitializingFormalDeclaration( |
| 195 VariableDefinitions node, | 174 VariableDefinitions node, |
| 196 Node definition, | 175 Node definition, |
| 197 InitializingFormalElement parameter, | 176 InitializingFormalElement parameter, |
| 198 ConstantExpression defaultValue, | 177 ConstantExpression defaultValue, |
| 199 int index, | 178 int index, |
| 200 _) { | 179 _) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 224 for (InitializerStructure structure in initializers.initializers) { | 203 for (InitializerStructure structure in initializers.initializers) { |
| 225 if (structure.isConstructorInvoke) { | 204 if (structure.isConstructorInvoke) { |
| 226 constructorInvocation = structure.dispatch(this, _); | 205 constructorInvocation = structure.dispatch(this, _); |
| 227 } else { | 206 } else { |
| 228 structure.dispatch(this, _); | 207 structure.dispatch(this, _); |
| 229 } | 208 } |
| 230 } | 209 } |
| 231 return constructorInvocation; | 210 return constructorInvocation; |
| 232 } | 211 } |
| 233 | 212 |
| 234 visitFieldInitializer( | 213 visitFieldInitializer(SendSet node, FieldElement field, Node initializer, _) { |
| 235 SendSet node, | |
| 236 FieldElement field, | |
| 237 Node initializer, | |
| 238 _) { | |
| 239 fieldMap[field] = apply(initializer); | 214 fieldMap[field] = apply(initializer); |
| 240 } | 215 } |
| 241 | 216 |
| 242 visitParameterGet( | 217 visitParameterGet(Send node, ParameterElement parameter, _) { |
| 243 Send node, | |
| 244 ParameterElement parameter, | |
| 245 _) { | |
| 246 if (parameter.isNamed) { | 218 if (parameter.isNamed) { |
| 247 return new NamedArgumentReference(parameter.name); | 219 return new NamedArgumentReference(parameter.name); |
| 248 } else { | 220 } else { |
| 249 return new PositionalArgumentReference( | 221 return new PositionalArgumentReference( |
| 250 parameter.functionDeclaration.parameters.indexOf(parameter)); | 222 parameter.functionDeclaration.parameters.indexOf(parameter)); |
| 251 } | 223 } |
| 252 } | 224 } |
| 253 | 225 |
| 254 ConstructedConstantExpression visitSuperConstructorInvoke( | 226 ConstructedConstantExpression visitSuperConstructorInvoke( |
| 255 Send node, | 227 Send node, |
| 256 ConstructorElement superConstructor, | 228 ConstructorElement superConstructor, |
| 257 InterfaceType type, | 229 InterfaceType type, |
| 258 NodeList arguments, | 230 NodeList arguments, |
| 259 CallStructure callStructure, | 231 CallStructure callStructure, |
| 260 _) { | 232 _) { |
| 261 List<ConstantExpression> argumentExpression = | 233 List<ConstantExpression> argumentExpression = |
| 262 arguments.nodes.map((a) => apply(a)).toList(); | 234 arguments.nodes.map((a) => apply(a)).toList(); |
| 263 return new ConstructedConstantExpression( | 235 return new ConstructedConstantExpression( |
| 264 type, | 236 type, superConstructor, callStructure, argumentExpression); |
| 265 superConstructor, | |
| 266 callStructure, | |
| 267 argumentExpression); | |
| 268 } | 237 } |
| 269 | 238 |
| 270 ConstructedConstantExpression visitImplicitSuperConstructorInvoke( | 239 ConstructedConstantExpression visitImplicitSuperConstructorInvoke( |
| 271 FunctionExpression node, | 240 FunctionExpression node, |
| 272 ConstructorElement superConstructor, | 241 ConstructorElement superConstructor, |
| 273 InterfaceType type, | 242 InterfaceType type, |
| 274 _) { | 243 _) { |
| 275 return new ConstructedConstantExpression( | 244 return new ConstructedConstantExpression(type, superConstructor, |
| 276 type, | 245 CallStructure.NO_ARGS, const <ConstantExpression>[]); |
| 277 superConstructor, | |
| 278 CallStructure.NO_ARGS, | |
| 279 const <ConstantExpression>[]); | |
| 280 } | 246 } |
| 281 | 247 |
| 282 ConstructedConstantExpression visitThisConstructorInvoke( | 248 ConstructedConstantExpression visitThisConstructorInvoke( |
| 283 Send node, | 249 Send node, |
| 284 ConstructorElement thisConstructor, | 250 ConstructorElement thisConstructor, |
| 285 NodeList arguments, | 251 NodeList arguments, |
| 286 CallStructure callStructure, | 252 CallStructure callStructure, |
| 287 _) { | 253 _) { |
| 288 List<ConstantExpression> argumentExpression = | 254 List<ConstantExpression> argumentExpression = |
| 289 arguments.nodes.map((a) => apply(a)).toList(); | 255 arguments.nodes.map((a) => apply(a)).toList(); |
| 290 return new ConstructedConstantExpression( | 256 return new ConstructedConstantExpression(currentClass.thisType, |
| 291 currentClass.thisType, | 257 thisConstructor, callStructure, argumentExpression); |
| 292 thisConstructor, | |
| 293 callStructure, | |
| 294 argumentExpression); | |
| 295 } | 258 } |
| 296 | 259 |
| 297 @override | 260 @override |
| 298 ConstantExpression visitBinary( | 261 ConstantExpression visitBinary( |
| 299 Send node, | 262 Send node, Node left, BinaryOperator operator, Node right, _) { |
| 300 Node left, | 263 return new BinaryConstantExpression(apply(left), operator, apply(right)); |
| 301 BinaryOperator operator, | |
| 302 Node right, | |
| 303 _) { | |
| 304 return new BinaryConstantExpression( | |
| 305 apply(left), operator, apply(right)); | |
| 306 } | 264 } |
| 307 | 265 |
| 308 | |
| 309 @override | 266 @override |
| 310 ConstantExpression visitUnary( | 267 ConstantExpression visitUnary( |
| 311 Send node, | 268 Send node, UnaryOperator operator, Node expression, _) { |
| 312 UnaryOperator operator, | 269 return new UnaryConstantExpression(operator, apply(expression)); |
| 313 Node expression, | |
| 314 _) { | |
| 315 return new UnaryConstantExpression( | |
| 316 operator, apply(expression)); | |
| 317 } | 270 } |
| 318 | 271 |
| 319 @override | 272 @override |
| 320 ConstantExpression visitStaticFieldGet( | 273 ConstantExpression visitStaticFieldGet(Send node, FieldElement field, _) { |
| 321 Send node, | |
| 322 FieldElement field, | |
| 323 _) { | |
| 324 return new VariableConstantExpression(field); | 274 return new VariableConstantExpression(field); |
| 325 } | 275 } |
| 326 | 276 |
| 327 @override | 277 @override |
| 328 ConstantExpression visitTopLevelFieldGet( | 278 ConstantExpression visitTopLevelFieldGet(Send node, FieldElement field, _) { |
| 329 Send node, | |
| 330 FieldElement field, | |
| 331 _) { | |
| 332 return new VariableConstantExpression(field); | 279 return new VariableConstantExpression(field); |
| 333 } | 280 } |
| 334 | 281 |
| 335 @override | 282 @override |
| 336 ConstantExpression visitLiteralInt(LiteralInt node) { | 283 ConstantExpression visitLiteralInt(LiteralInt node) { |
| 337 return new IntConstantExpression(node.value); | 284 return new IntConstantExpression(node.value); |
| 338 } | 285 } |
| 339 | 286 |
| 340 @override | 287 @override |
| 341 ConstantExpression visitLiteralBool(LiteralBool node) { | 288 ConstantExpression visitLiteralBool(LiteralBool node) { |
| 342 return new BoolConstantExpression(node.value); | 289 return new BoolConstantExpression(node.value); |
| 343 } | 290 } |
| 344 | 291 |
| 345 @override | 292 @override |
| 346 ConstantExpression visitLiteralNull(LiteralNull node) { | 293 ConstantExpression visitLiteralNull(LiteralNull node) { |
| 347 return new NullConstantExpression(); | 294 return new NullConstantExpression(); |
| 348 } | 295 } |
| 349 | 296 |
| 350 @override | 297 @override |
| 351 ConstantExpression visitLiteralString(LiteralString node) { | 298 ConstantExpression visitLiteralString(LiteralString node) { |
| 352 return new StringConstantExpression(node.dartString.slowToString()); | 299 return new StringConstantExpression(node.dartString.slowToString()); |
| 353 } | 300 } |
| 354 | 301 |
| 355 @override | 302 @override |
| 356 ConstantExpression visitConditional(Conditional node) { | 303 ConstantExpression visitConditional(Conditional node) { |
| 357 return new ConditionalConstantExpression( | 304 return new ConditionalConstantExpression(apply(node.condition), |
| 358 apply(node.condition), | 305 apply(node.thenExpression), apply(node.elseExpression)); |
| 359 apply(node.thenExpression), | |
| 360 apply(node.elseExpression)); | |
| 361 } | 306 } |
| 362 | 307 |
| 363 @override | 308 @override |
| 364 ConstantExpression visitParenthesizedExpression(ParenthesizedExpression node)
{ | 309 ConstantExpression visitParenthesizedExpression( |
| 310 ParenthesizedExpression node) { |
| 365 return apply(node.expression); | 311 return apply(node.expression); |
| 366 } | 312 } |
| 367 | 313 |
| 368 @override | 314 @override |
| 369 ConstantExpression visitTopLevelFunctionInvoke( | 315 ConstantExpression visitTopLevelFunctionInvoke( |
| 370 Send node, | 316 Send node, |
| 371 MethodElement function, | 317 MethodElement function, |
| 372 NodeList arguments, | 318 NodeList arguments, |
| 373 CallStructure callStructure, | 319 CallStructure callStructure, |
| 374 _) { | 320 _) { |
| 375 if (function.name != 'identical' || !function.library.isDartCore) { | 321 if (function.name != 'identical' || !function.library.isDartCore) { |
| 376 throw new UnsupportedError("Unexpected function call: $function"); | 322 throw new UnsupportedError("Unexpected function call: $function"); |
| 377 } | 323 } |
| 378 return new IdenticalConstantExpression( | 324 return new IdenticalConstantExpression( |
| 379 apply(arguments.nodes.head), apply(arguments.nodes.tail.head)); | 325 apply(arguments.nodes.head), apply(arguments.nodes.tail.head)); |
| 380 } | 326 } |
| 381 | 327 |
| 382 @override | 328 @override |
| 383 ConstantExpression visitNamedArgument(NamedArgument node) { | 329 ConstantExpression visitNamedArgument(NamedArgument node) { |
| 384 return apply(node.expression); | 330 return apply(node.expression); |
| 385 } | 331 } |
| 386 } | 332 } |
| OLD | NEW |