| 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 library dart2js.constants.constructors; | 5 library dart2js.constants.constructors; |
| 6 | 6 |
| 7 import '../elements/resolution_types.dart'; | 7 import '../elements/entities.dart' show FieldEntity; |
| 8 import '../elements/elements.dart' show FieldElement; | 8 import '../elements/types.dart'; |
| 9 import '../universe/call_structure.dart' show CallStructure; | 9 import '../universe/call_structure.dart' show CallStructure; |
| 10 import '../util/util.dart'; | 10 import '../util/util.dart'; |
| 11 import 'evaluation.dart'; | 11 import 'evaluation.dart'; |
| 12 import 'expressions.dart'; | 12 import 'expressions.dart'; |
| 13 | 13 |
| 14 enum ConstantConstructorKind { | 14 enum ConstantConstructorKind { |
| 15 GENERATIVE, | 15 GENERATIVE, |
| 16 REDIRECTING_GENERATIVE, | 16 REDIRECTING_GENERATIVE, |
| 17 REDIRECTING_FACTORY, | 17 REDIRECTING_FACTORY, |
| 18 } | 18 } |
| 19 | 19 |
| 20 /// Definition of a constant constructor. | 20 /// Definition of a constant constructor. |
| 21 abstract class ConstantConstructor { | 21 abstract class ConstantConstructor { |
| 22 ConstantConstructorKind get kind; | 22 ConstantConstructorKind get kind; |
| 23 | 23 |
| 24 /// Computes the type of the instance created in a const constructor | 24 /// Computes the type of the instance created in a const constructor |
| 25 /// invocation with type [newType]. | 25 /// invocation with type [newType]. |
| 26 ResolutionInterfaceType computeInstanceType(ResolutionInterfaceType newType); | 26 InterfaceType computeInstanceType( |
| 27 Environment environment, InterfaceType newType); |
| 27 | 28 |
| 28 /// Computes the constant expressions of the fields of the created instance | 29 /// Computes the constant expressions of the fields of the created instance |
| 29 /// in a const constructor invocation with [arguments]. | 30 /// in a const constructor invocation with [arguments]. |
| 30 Map<FieldElement, ConstantExpression> computeInstanceFields( | 31 Map<FieldEntity, ConstantExpression> computeInstanceFields( |
| 31 List<ConstantExpression> arguments, CallStructure callStructure); | 32 Environment environment, |
| 33 List<ConstantExpression> arguments, |
| 34 CallStructure callStructure); |
| 32 | 35 |
| 33 accept(ConstantConstructorVisitor visitor, arg); | 36 accept(ConstantConstructorVisitor visitor, arg); |
| 34 } | 37 } |
| 35 | 38 |
| 36 abstract class ConstantConstructorVisitor<R, A> { | 39 abstract class ConstantConstructorVisitor<R, A> { |
| 37 const ConstantConstructorVisitor(); | 40 const ConstantConstructorVisitor(); |
| 38 | 41 |
| 39 R visit(ConstantConstructor constantConstructor, A context) { | 42 R visit(ConstantConstructor constantConstructor, A context) { |
| 40 return constantConstructor.accept(this, context); | 43 return constantConstructor.accept(this, context); |
| 41 } | 44 } |
| 42 | 45 |
| 43 R visitGenerative(GenerativeConstantConstructor constructor, A arg); | 46 R visitGenerative(GenerativeConstantConstructor constructor, A arg); |
| 44 R visitRedirectingGenerative( | 47 R visitRedirectingGenerative( |
| 45 RedirectingGenerativeConstantConstructor constructor, A arg); | 48 RedirectingGenerativeConstantConstructor constructor, A arg); |
| 46 R visitRedirectingFactory( | 49 R visitRedirectingFactory( |
| 47 RedirectingFactoryConstantConstructor constructor, A arg); | 50 RedirectingFactoryConstantConstructor constructor, A arg); |
| 48 } | 51 } |
| 49 | 52 |
| 50 /// A generative constant constructor. | 53 /// A generative constant constructor. |
| 51 class GenerativeConstantConstructor implements ConstantConstructor { | 54 class GenerativeConstantConstructor implements ConstantConstructor { |
| 52 final ResolutionInterfaceType type; | 55 final InterfaceType type; |
| 53 final Map<dynamic /*int|String*/, ConstantExpression> defaultValues; | 56 final Map<dynamic /*int|String*/, ConstantExpression> defaultValues; |
| 54 final Map<FieldElement, ConstantExpression> fieldMap; | 57 final Map<FieldEntity, ConstantExpression> fieldMap; |
| 55 final ConstructedConstantExpression superConstructorInvocation; | 58 final ConstructedConstantExpression superConstructorInvocation; |
| 56 | 59 |
| 57 GenerativeConstantConstructor(this.type, this.defaultValues, this.fieldMap, | 60 GenerativeConstantConstructor(this.type, this.defaultValues, this.fieldMap, |
| 58 this.superConstructorInvocation); | 61 this.superConstructorInvocation); |
| 59 | 62 |
| 60 ConstantConstructorKind get kind => ConstantConstructorKind.GENERATIVE; | 63 ConstantConstructorKind get kind => ConstantConstructorKind.GENERATIVE; |
| 61 | 64 |
| 62 ResolutionInterfaceType computeInstanceType(ResolutionInterfaceType newType) { | 65 InterfaceType computeInstanceType( |
| 63 return type.substByContext(newType); | 66 Environment environment, InterfaceType newType) { |
| 67 return environment.substByContext(type, newType); |
| 64 } | 68 } |
| 65 | 69 |
| 66 Map<FieldElement, ConstantExpression> computeInstanceFields( | 70 Map<FieldEntity, ConstantExpression> computeInstanceFields( |
| 67 List<ConstantExpression> arguments, CallStructure callStructure) { | 71 Environment environment, |
| 72 List<ConstantExpression> arguments, |
| 73 CallStructure callStructure) { |
| 68 NormalizedArguments args = | 74 NormalizedArguments args = |
| 69 new NormalizedArguments(defaultValues, callStructure, arguments); | 75 new NormalizedArguments(defaultValues, callStructure, arguments); |
| 70 Map<FieldElement, ConstantExpression> appliedFieldMap = | 76 Map<FieldEntity, ConstantExpression> appliedFieldMap = |
| 71 applyFields(args, superConstructorInvocation); | 77 applyFields(environment, args, superConstructorInvocation); |
| 72 fieldMap.forEach((FieldElement field, ConstantExpression constant) { | 78 fieldMap.forEach((FieldEntity field, ConstantExpression constant) { |
| 73 appliedFieldMap[field] = constant.apply(args); | 79 appliedFieldMap[field] = constant.apply(args); |
| 74 }); | 80 }); |
| 75 return appliedFieldMap; | 81 return appliedFieldMap; |
| 76 } | 82 } |
| 77 | 83 |
| 78 accept(ConstantConstructorVisitor visitor, arg) { | 84 accept(ConstantConstructorVisitor visitor, arg) { |
| 79 return visitor.visitGenerative(this, arg); | 85 return visitor.visitGenerative(this, arg); |
| 80 } | 86 } |
| 81 | 87 |
| 82 int get hashCode { | 88 int get hashCode { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 94 mapEquals(defaultValues, other.defaultValues) && | 100 mapEquals(defaultValues, other.defaultValues) && |
| 95 mapEquals(fieldMap, other.fieldMap); | 101 mapEquals(fieldMap, other.fieldMap); |
| 96 } | 102 } |
| 97 | 103 |
| 98 String toString() { | 104 String toString() { |
| 99 StringBuffer sb = new StringBuffer(); | 105 StringBuffer sb = new StringBuffer(); |
| 100 sb.write("{'type': $type"); | 106 sb.write("{'type': $type"); |
| 101 defaultValues.forEach((key, ConstantExpression expression) { | 107 defaultValues.forEach((key, ConstantExpression expression) { |
| 102 sb.write(",\n 'default:${key}': ${expression.toDartText()}"); | 108 sb.write(",\n 'default:${key}': ${expression.toDartText()}"); |
| 103 }); | 109 }); |
| 104 fieldMap.forEach((FieldElement field, ConstantExpression expression) { | 110 fieldMap.forEach((FieldEntity field, ConstantExpression expression) { |
| 105 sb.write(",\n 'field:${field}': ${expression.toDartText()}"); | 111 sb.write(",\n 'field:${field}': ${expression.toDartText()}"); |
| 106 }); | 112 }); |
| 107 if (superConstructorInvocation != null) { | 113 if (superConstructorInvocation != null) { |
| 108 sb.write(",\n 'constructor: ${superConstructorInvocation.toDartText()}"); | 114 sb.write(",\n 'constructor: ${superConstructorInvocation.toDartText()}"); |
| 109 } | 115 } |
| 110 sb.write("}"); | 116 sb.write("}"); |
| 111 return sb.toString(); | 117 return sb.toString(); |
| 112 } | 118 } |
| 113 | 119 |
| 114 static bool mapEquals(Map map1, Map map2) { | 120 static bool mapEquals(Map map1, Map map2) { |
| 115 if (map1.length != map1.length) return false; | 121 if (map1.length != map1.length) return false; |
| 116 for (var key in map1.keys) { | 122 for (var key in map1.keys) { |
| 117 if (map1[key] != map2[key]) { | 123 if (map1[key] != map2[key]) { |
| 118 return false; | 124 return false; |
| 119 } | 125 } |
| 120 } | 126 } |
| 121 return true; | 127 return true; |
| 122 } | 128 } |
| 123 | 129 |
| 124 /// Creates the field-to-constant map from applying [args] to | 130 /// Creates the field-to-constant map from applying [args] to |
| 125 /// [constructorInvocation]. If [constructorInvocation] is `null`, an empty | 131 /// [constructorInvocation]. If [constructorInvocation] is `null`, an empty |
| 126 /// map is created. | 132 /// map is created. |
| 127 static Map<FieldElement, ConstantExpression> applyFields( | 133 static Map<FieldEntity, ConstantExpression> applyFields( |
| 134 Environment environment, |
| 128 NormalizedArguments args, | 135 NormalizedArguments args, |
| 129 ConstructedConstantExpression constructorInvocation) { | 136 ConstructedConstantExpression constructorInvocation) { |
| 130 Map<FieldElement, ConstantExpression> appliedFieldMap = | 137 Map<FieldEntity, ConstantExpression> appliedFieldMap = |
| 131 <FieldElement, ConstantExpression>{}; | 138 <FieldEntity, ConstantExpression>{}; |
| 132 if (constructorInvocation != null) { | 139 if (constructorInvocation != null) { |
| 133 Map<FieldElement, ConstantExpression> fieldMap = | 140 Map<FieldEntity, ConstantExpression> fieldMap = |
| 134 constructorInvocation.computeInstanceFields(); | 141 constructorInvocation.computeInstanceFields(environment); |
| 135 fieldMap.forEach((FieldElement field, ConstantExpression constant) { | 142 fieldMap.forEach((FieldEntity field, ConstantExpression constant) { |
| 136 appliedFieldMap[field] = constant.apply(args); | 143 appliedFieldMap[field] = constant.apply(args); |
| 137 }); | 144 }); |
| 138 } | 145 } |
| 139 return appliedFieldMap; | 146 return appliedFieldMap; |
| 140 } | 147 } |
| 141 } | 148 } |
| 142 | 149 |
| 143 /// A redirecting generative constant constructor. | 150 /// A redirecting generative constant constructor. |
| 144 class RedirectingGenerativeConstantConstructor implements ConstantConstructor { | 151 class RedirectingGenerativeConstantConstructor implements ConstantConstructor { |
| 145 final Map<dynamic /*int|String*/, ConstantExpression> defaultValues; | 152 final Map<dynamic /*int|String*/, ConstantExpression> defaultValues; |
| 146 final ConstructedConstantExpression thisConstructorInvocation; | 153 final ConstructedConstantExpression thisConstructorInvocation; |
| 147 | 154 |
| 148 RedirectingGenerativeConstantConstructor( | 155 RedirectingGenerativeConstantConstructor( |
| 149 this.defaultValues, this.thisConstructorInvocation); | 156 this.defaultValues, this.thisConstructorInvocation); |
| 150 | 157 |
| 151 ConstantConstructorKind get kind { | 158 ConstantConstructorKind get kind { |
| 152 return ConstantConstructorKind.REDIRECTING_GENERATIVE; | 159 return ConstantConstructorKind.REDIRECTING_GENERATIVE; |
| 153 } | 160 } |
| 154 | 161 |
| 155 ResolutionInterfaceType computeInstanceType(ResolutionInterfaceType newType) { | 162 InterfaceType computeInstanceType( |
| 156 return thisConstructorInvocation | 163 Environment environment, InterfaceType newType) { |
| 157 .computeInstanceType() | 164 return environment.substByContext( |
| 158 .substByContext(newType); | 165 thisConstructorInvocation.computeInstanceType(environment), newType); |
| 159 } | 166 } |
| 160 | 167 |
| 161 Map<FieldElement, ConstantExpression> computeInstanceFields( | 168 Map<FieldEntity, ConstantExpression> computeInstanceFields( |
| 162 List<ConstantExpression> arguments, CallStructure callStructure) { | 169 Environment environment, |
| 170 List<ConstantExpression> arguments, |
| 171 CallStructure callStructure) { |
| 163 NormalizedArguments args = | 172 NormalizedArguments args = |
| 164 new NormalizedArguments(defaultValues, callStructure, arguments); | 173 new NormalizedArguments(defaultValues, callStructure, arguments); |
| 165 Map<FieldElement, ConstantExpression> appliedFieldMap = | 174 Map<FieldEntity, ConstantExpression> appliedFieldMap = |
| 166 GenerativeConstantConstructor.applyFields( | 175 GenerativeConstantConstructor.applyFields( |
| 167 args, thisConstructorInvocation); | 176 environment, args, thisConstructorInvocation); |
| 168 return appliedFieldMap; | 177 return appliedFieldMap; |
| 169 } | 178 } |
| 170 | 179 |
| 171 accept(ConstantConstructorVisitor visitor, arg) { | 180 accept(ConstantConstructorVisitor visitor, arg) { |
| 172 return visitor.visitRedirectingGenerative(this, arg); | 181 return visitor.visitRedirectingGenerative(this, arg); |
| 173 } | 182 } |
| 174 | 183 |
| 175 int get hashCode { | 184 int get hashCode { |
| 176 int hash = Hashing.objectHash(thisConstructorInvocation); | 185 int hash = Hashing.objectHash(thisConstructorInvocation); |
| 177 return Hashing.mapHash(defaultValues, hash); | 186 return Hashing.mapHash(defaultValues, hash); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 200 /// A redirecting factory constant constructor. | 209 /// A redirecting factory constant constructor. |
| 201 class RedirectingFactoryConstantConstructor implements ConstantConstructor { | 210 class RedirectingFactoryConstantConstructor implements ConstantConstructor { |
| 202 final ConstructedConstantExpression targetConstructorInvocation; | 211 final ConstructedConstantExpression targetConstructorInvocation; |
| 203 | 212 |
| 204 RedirectingFactoryConstantConstructor(this.targetConstructorInvocation); | 213 RedirectingFactoryConstantConstructor(this.targetConstructorInvocation); |
| 205 | 214 |
| 206 ConstantConstructorKind get kind { | 215 ConstantConstructorKind get kind { |
| 207 return ConstantConstructorKind.REDIRECTING_FACTORY; | 216 return ConstantConstructorKind.REDIRECTING_FACTORY; |
| 208 } | 217 } |
| 209 | 218 |
| 210 ResolutionInterfaceType computeInstanceType(ResolutionInterfaceType newType) { | 219 InterfaceType computeInstanceType( |
| 211 return targetConstructorInvocation | 220 Environment environment, InterfaceType newType) { |
| 212 .computeInstanceType() | 221 return environment.substByContext( |
| 213 .substByContext(newType); | 222 targetConstructorInvocation.computeInstanceType(environment), newType); |
| 214 } | 223 } |
| 215 | 224 |
| 216 Map<FieldElement, ConstantExpression> computeInstanceFields( | 225 Map<FieldEntity, ConstantExpression> computeInstanceFields( |
| 217 List<ConstantExpression> arguments, CallStructure callStructure) { | 226 Environment environment, |
| 227 List<ConstantExpression> arguments, |
| 228 CallStructure callStructure) { |
| 218 ConstantConstructor constantConstructor = | 229 ConstantConstructor constantConstructor = |
| 219 targetConstructorInvocation.target.constantConstructor; | 230 environment.getConstructorConstant(targetConstructorInvocation.target); |
| 220 return constantConstructor.computeInstanceFields(arguments, callStructure); | 231 return constantConstructor.computeInstanceFields( |
| 232 environment, arguments, callStructure); |
| 221 } | 233 } |
| 222 | 234 |
| 223 accept(ConstantConstructorVisitor visitor, arg) { | 235 accept(ConstantConstructorVisitor visitor, arg) { |
| 224 return visitor.visitRedirectingFactory(this, arg); | 236 return visitor.visitRedirectingFactory(this, arg); |
| 225 } | 237 } |
| 226 | 238 |
| 227 int get hashCode { | 239 int get hashCode { |
| 228 return Hashing.objectHash(targetConstructorInvocation); | 240 return Hashing.objectHash(targetConstructorInvocation); |
| 229 } | 241 } |
| 230 | 242 |
| 231 bool operator ==(other) { | 243 bool operator ==(other) { |
| 232 if (identical(this, other)) return true; | 244 if (identical(this, other)) return true; |
| 233 if (other is! RedirectingFactoryConstantConstructor) return false; | 245 if (other is! RedirectingFactoryConstantConstructor) return false; |
| 234 return targetConstructorInvocation == other.targetConstructorInvocation; | 246 return targetConstructorInvocation == other.targetConstructorInvocation; |
| 235 } | 247 } |
| 236 | 248 |
| 237 String toString() { | 249 String toString() { |
| 238 StringBuffer sb = new StringBuffer(); | 250 StringBuffer sb = new StringBuffer(); |
| 239 sb.write("{"); | 251 sb.write("{"); |
| 240 sb.write("'constructor': ${targetConstructorInvocation.toDartText()}"); | 252 sb.write("'constructor': ${targetConstructorInvocation.toDartText()}"); |
| 241 sb.write("}"); | 253 sb.write("}"); |
| 242 return sb.toString(); | 254 return sb.toString(); |
| 243 } | 255 } |
| 244 } | 256 } |
| OLD | NEW |