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