| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2017, 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.kernel.world_builder; | |
| 6 | |
| 7 import 'package:kernel/ast.dart' as ir; | |
| 8 | |
| 9 import '../common.dart'; | |
| 10 import '../common/resolution.dart'; | |
| 11 import '../compile_time_constants.dart'; | |
| 12 import '../constants/constant_system.dart'; | |
| 13 import '../constants/constructors.dart'; | |
| 14 import '../constants/evaluation.dart'; | |
| 15 import '../constants/expressions.dart'; | |
| 16 import '../constants/values.dart'; | |
| 17 import '../common_elements.dart'; | |
| 18 import '../elements/elements.dart'; | |
| 19 import '../elements/entities.dart'; | |
| 20 import '../elements/types.dart'; | |
| 21 import '../js_backend/constant_system_javascript.dart'; | |
| 22 import '../js_backend/native_data.dart' show NativeData; | |
| 23 import '../js_backend/no_such_method_registry.dart'; | |
| 24 import '../native/native.dart' as native; | |
| 25 import '../native/resolver.dart'; | |
| 26 import '../ssa/kernel_impact.dart'; | |
| 27 import '../universe/call_structure.dart'; | |
| 28 import 'element_adapter.dart'; | |
| 29 import 'elements.dart'; | |
| 30 | |
| 31 part 'native_class_resolver.dart'; | |
| 32 part 'no_such_method_resolver.dart'; | |
| 33 | |
| 34 /// World builder used for creating elements and types corresponding to Kernel | |
| 35 /// IR nodes. | |
| 36 // TODO(johnniwinther): Implement [ResolutionWorldBuilder]. | |
| 37 class KernelWorldBuilder extends KernelElementAdapterMixin { | |
| 38 CommonElements _commonElements; | |
| 39 native.BehaviorBuilder _nativeBehaviorBuilder; | |
| 40 final DiagnosticReporter reporter; | |
| 41 ElementEnvironment _elementEnvironment; | |
| 42 DartTypeConverter _typeConverter; | |
| 43 | |
| 44 /// Library environment. Used for fast lookup. | |
| 45 KEnv _env; | |
| 46 | |
| 47 /// List of library environments by `KLibrary.libraryIndex`. This is used for | |
| 48 /// fast lookup into library classes and members. | |
| 49 List<KLibraryEnv> _libraryEnvs = <KLibraryEnv>[]; | |
| 50 | |
| 51 /// List of class environments by `KClass.classIndex`. This is used for | |
| 52 /// fast lookup into class members. | |
| 53 List<KClassEnv> _classEnvs = <KClassEnv>[]; | |
| 54 | |
| 55 Map<ir.Library, KLibrary> _libraryMap = <ir.Library, KLibrary>{}; | |
| 56 Map<ir.Class, KClass> _classMap = <ir.Class, KClass>{}; | |
| 57 Map<ir.TypeParameter, KTypeVariable> _typeVariableMap = | |
| 58 <ir.TypeParameter, KTypeVariable>{}; | |
| 59 | |
| 60 // TODO(johnniwinther): Change this to a list of 'KMemberData' class if we | |
| 61 // need more data for members. | |
| 62 List<ir.Member> _memberList = <ir.Member>[]; | |
| 63 | |
| 64 Map<ir.Member, KConstructor> _constructorMap = <ir.Member, KConstructor>{}; | |
| 65 Map<KConstructor, ConstantConstructor> _constructorConstantMap = | |
| 66 <KConstructor, ConstantConstructor>{}; | |
| 67 | |
| 68 Map<ir.Procedure, KFunction> _methodMap = <ir.Procedure, KFunction>{}; | |
| 69 | |
| 70 Map<ir.Field, KField> _fieldMap = <ir.Field, KField>{}; | |
| 71 Map<KField, ConstantExpression> _fieldConstantMap = | |
| 72 <KField, ConstantExpression>{}; | |
| 73 | |
| 74 Map<ir.TreeNode, KLocalFunction> _localFunctionMap = | |
| 75 <ir.TreeNode, KLocalFunction>{}; | |
| 76 | |
| 77 KernelWorldBuilder(this.reporter, ir.Program program) | |
| 78 : _env = new KEnv(program) { | |
| 79 _elementEnvironment = new KernelElementEnvironment(this); | |
| 80 _commonElements = new CommonElements(_elementEnvironment); | |
| 81 ConstantEnvironment constants = new KernelConstantEnvironment(this); | |
| 82 _nativeBehaviorBuilder = | |
| 83 new KernelBehaviorBuilder(_commonElements, constants); | |
| 84 _typeConverter = new DartTypeConverter(this); | |
| 85 } | |
| 86 | |
| 87 KMethod get _mainFunction { | |
| 88 return _env.program.mainMethod != null | |
| 89 ? _getMethod(_env.program.mainMethod) | |
| 90 : null; | |
| 91 } | |
| 92 | |
| 93 KLibrary get _mainLibrary { | |
| 94 return _env.program.mainMethod != null | |
| 95 ? _getLibrary(_env.program.mainMethod.enclosingLibrary) | |
| 96 : null; | |
| 97 } | |
| 98 | |
| 99 @override | |
| 100 CommonElements get commonElements => _commonElements; | |
| 101 | |
| 102 @override | |
| 103 ElementEnvironment get elementEnvironment => _elementEnvironment; | |
| 104 | |
| 105 @override | |
| 106 native.BehaviorBuilder get nativeBehaviorBuilder => _nativeBehaviorBuilder; | |
| 107 | |
| 108 LibraryEntity lookupLibrary(Uri uri) { | |
| 109 KLibraryEnv libraryEnv = _env.lookupLibrary(uri); | |
| 110 return _getLibrary(libraryEnv.library, libraryEnv); | |
| 111 } | |
| 112 | |
| 113 KLibrary _getLibrary(ir.Library node, [KLibraryEnv libraryEnv]) { | |
| 114 return _libraryMap.putIfAbsent(node, () { | |
| 115 Uri canonicalUri = node.importUri; | |
| 116 _libraryEnvs.add(libraryEnv ?? _env.lookupLibrary(canonicalUri)); | |
| 117 String name = node.name; | |
| 118 if (name == null) { | |
| 119 // Use the file name as script name. | |
| 120 String path = canonicalUri.path; | |
| 121 name = path.substring(path.lastIndexOf('/') + 1); | |
| 122 } | |
| 123 return new KLibrary(_libraryMap.length, name, canonicalUri); | |
| 124 }); | |
| 125 } | |
| 126 | |
| 127 MemberEntity lookupLibraryMember(KLibrary library, String name, | |
| 128 {bool setter: false}) { | |
| 129 KLibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; | |
| 130 ir.Member member = libraryEnv.lookupMember(name, setter: setter); | |
| 131 return member != null ? getMember(member) : null; | |
| 132 } | |
| 133 | |
| 134 ClassEntity lookupClass(KLibrary library, String name) { | |
| 135 KLibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; | |
| 136 KClassEnv classEnv = libraryEnv.lookupClass(name); | |
| 137 if (classEnv != null) { | |
| 138 return _getClass(classEnv.cls, classEnv); | |
| 139 } | |
| 140 return null; | |
| 141 } | |
| 142 | |
| 143 MemberEntity lookupClassMember(KClass cls, String name, | |
| 144 {bool setter: false}) { | |
| 145 KClassEnv classEnv = _classEnvs[cls.classIndex]; | |
| 146 ir.Member member = classEnv.lookupMember(name, setter: setter); | |
| 147 return member != null ? getMember(member) : null; | |
| 148 } | |
| 149 | |
| 150 ConstructorEntity lookupConstructor(KClass cls, String name) { | |
| 151 KClassEnv classEnv = _classEnvs[cls.classIndex]; | |
| 152 ir.Member member = classEnv.lookupConstructor(name); | |
| 153 return member != null ? getConstructor(member) : null; | |
| 154 } | |
| 155 | |
| 156 KClass _getClass(ir.Class node, [KClassEnv classEnv]) { | |
| 157 return _classMap.putIfAbsent(node, () { | |
| 158 KLibrary library = _getLibrary(node.enclosingLibrary); | |
| 159 if (classEnv == null) { | |
| 160 classEnv = _libraryEnvs[library.libraryIndex].lookupClass(node.name); | |
| 161 } | |
| 162 _classEnvs.add(classEnv); | |
| 163 return new KClass(library, _classMap.length, node.name, | |
| 164 isAbstract: node.isAbstract); | |
| 165 }); | |
| 166 } | |
| 167 | |
| 168 KTypeVariable _getTypeVariable(ir.TypeParameter node) { | |
| 169 return _typeVariableMap.putIfAbsent(node, () { | |
| 170 if (node.parent is ir.Class) { | |
| 171 ir.Class cls = node.parent; | |
| 172 int index = cls.typeParameters.indexOf(node); | |
| 173 return new KTypeVariable(_getClass(cls), node.name, index); | |
| 174 } | |
| 175 if (node.parent is ir.FunctionNode) { | |
| 176 ir.FunctionNode func = node.parent; | |
| 177 int index = func.typeParameters.indexOf(node); | |
| 178 if (func.parent is ir.Constructor) { | |
| 179 ir.Constructor constructor = func.parent; | |
| 180 ir.Class cls = constructor.enclosingClass; | |
| 181 return _getTypeVariable(cls.typeParameters[index]); | |
| 182 } | |
| 183 if (func.parent is ir.Procedure) { | |
| 184 ir.Procedure procedure = func.parent; | |
| 185 if (procedure.kind == ir.ProcedureKind.Factory) { | |
| 186 ir.Class cls = procedure.enclosingClass; | |
| 187 return _getTypeVariable(cls.typeParameters[index]); | |
| 188 } else { | |
| 189 return new KTypeVariable(_getMethod(procedure), node.name, index); | |
| 190 } | |
| 191 } | |
| 192 } | |
| 193 throw new UnsupportedError('Unsupported type parameter type node $node.'); | |
| 194 }); | |
| 195 } | |
| 196 | |
| 197 ParameterStructure _getParameterStructure(ir.FunctionNode node) { | |
| 198 // TODO(johnniwinther): Cache the computed function type. | |
| 199 int requiredParameters = node.requiredParameterCount; | |
| 200 int positionalParameters = node.positionalParameters.length; | |
| 201 List<String> namedParameters = | |
| 202 node.namedParameters.map((p) => p.name).toList()..sort(); | |
| 203 return new ParameterStructure( | |
| 204 requiredParameters, positionalParameters, namedParameters); | |
| 205 } | |
| 206 | |
| 207 KConstructor _getConstructor(ir.Member node) { | |
| 208 return _constructorMap.putIfAbsent(node, () { | |
| 209 int memberIndex = _memberList.length; | |
| 210 KConstructor constructor; | |
| 211 KClass enclosingClass = _getClass(node.enclosingClass); | |
| 212 Name name = getName(node.name); | |
| 213 bool isExternal = node.isExternal; | |
| 214 | |
| 215 if (node is ir.Constructor) { | |
| 216 constructor = new KGenerativeConstructor(memberIndex, enclosingClass, | |
| 217 name, _getParameterStructure(node.function), | |
| 218 isExternal: isExternal, isConst: node.isConst); | |
| 219 } else if (node is ir.Procedure) { | |
| 220 constructor = new KFactoryConstructor(memberIndex, enclosingClass, name, | |
| 221 _getParameterStructure(node.function), | |
| 222 isExternal: isExternal, isConst: node.isConst); | |
| 223 } else { | |
| 224 // TODO(johnniwinther): Convert `node.location` to a [SourceSpan]. | |
| 225 throw new SpannableAssertionFailure( | |
| 226 NO_LOCATION_SPANNABLE, "Unexpected constructor node: ${node}."); | |
| 227 } | |
| 228 _memberList.add(node); | |
| 229 return constructor; | |
| 230 }); | |
| 231 } | |
| 232 | |
| 233 KFunction _getMethod(ir.Procedure node) { | |
| 234 return _methodMap.putIfAbsent(node, () { | |
| 235 int memberIndex = _memberList.length; | |
| 236 KLibrary library; | |
| 237 KClass enclosingClass; | |
| 238 if (node.enclosingClass != null) { | |
| 239 enclosingClass = _getClass(node.enclosingClass); | |
| 240 library = enclosingClass.library; | |
| 241 } else { | |
| 242 library = _getLibrary(node.enclosingLibrary); | |
| 243 } | |
| 244 Name name = getName(node.name); | |
| 245 bool isStatic = node.isStatic; | |
| 246 bool isExternal = node.isExternal; | |
| 247 bool isAbstract = node.isAbstract; | |
| 248 KFunction function; | |
| 249 switch (node.kind) { | |
| 250 case ir.ProcedureKind.Factory: | |
| 251 throw new UnsupportedError("Cannot create method from factory."); | |
| 252 case ir.ProcedureKind.Getter: | |
| 253 function = new KGetter(memberIndex, library, enclosingClass, name, | |
| 254 isStatic: isStatic, | |
| 255 isExternal: isExternal, | |
| 256 isAbstract: isAbstract); | |
| 257 break; | |
| 258 case ir.ProcedureKind.Method: | |
| 259 case ir.ProcedureKind.Operator: | |
| 260 function = new KMethod(memberIndex, library, enclosingClass, name, | |
| 261 _getParameterStructure(node.function), | |
| 262 isStatic: isStatic, | |
| 263 isExternal: isExternal, | |
| 264 isAbstract: isAbstract); | |
| 265 break; | |
| 266 case ir.ProcedureKind.Setter: | |
| 267 function = new KSetter( | |
| 268 memberIndex, library, enclosingClass, getName(node.name).setter, | |
| 269 isStatic: isStatic, | |
| 270 isExternal: isExternal, | |
| 271 isAbstract: isAbstract); | |
| 272 break; | |
| 273 } | |
| 274 _memberList.add(node); | |
| 275 return function; | |
| 276 }); | |
| 277 } | |
| 278 | |
| 279 KField _getField(ir.Field node) { | |
| 280 return _fieldMap.putIfAbsent(node, () { | |
| 281 int memberIndex = _memberList.length; | |
| 282 KLibrary library; | |
| 283 KClass enclosingClass; | |
| 284 if (node.enclosingClass != null) { | |
| 285 enclosingClass = _getClass(node.enclosingClass); | |
| 286 library = enclosingClass.library; | |
| 287 } else { | |
| 288 library = _getLibrary(node.enclosingLibrary); | |
| 289 } | |
| 290 Name name = getName(node.name); | |
| 291 bool isStatic = node.isStatic; | |
| 292 _memberList.add(node); | |
| 293 return new KField(memberIndex, library, enclosingClass, name, | |
| 294 isStatic: isStatic, | |
| 295 isAssignable: node.isMutable, | |
| 296 isConst: node.isConst); | |
| 297 }); | |
| 298 } | |
| 299 | |
| 300 KLocalFunction _getLocal(ir.TreeNode node) { | |
| 301 return _localFunctionMap.putIfAbsent(node, () { | |
| 302 MemberEntity memberContext; | |
| 303 Entity executableContext; | |
| 304 ir.TreeNode parent = node.parent; | |
| 305 while (parent != null) { | |
| 306 if (parent is ir.Member) { | |
| 307 executableContext = memberContext = getMember(parent); | |
| 308 break; | |
| 309 } | |
| 310 if (parent is ir.FunctionDeclaration || | |
| 311 parent is ir.FunctionExpression) { | |
| 312 KLocalFunction localFunction = _getLocal(parent); | |
| 313 executableContext = localFunction; | |
| 314 memberContext = localFunction.memberContext; | |
| 315 break; | |
| 316 } | |
| 317 parent = parent.parent; | |
| 318 } | |
| 319 String name; | |
| 320 FunctionType functionType; | |
| 321 if (node is ir.FunctionDeclaration) { | |
| 322 name = node.variable.name; | |
| 323 functionType = getFunctionType(node.function); | |
| 324 } else if (node is ir.FunctionExpression) { | |
| 325 functionType = getFunctionType(node.function); | |
| 326 } | |
| 327 return new KLocalFunction( | |
| 328 name, memberContext, executableContext, functionType); | |
| 329 }); | |
| 330 } | |
| 331 | |
| 332 @override | |
| 333 DartType getDartType(ir.DartType type) => _typeConverter.convert(type); | |
| 334 | |
| 335 @override | |
| 336 InterfaceType createInterfaceType( | |
| 337 ir.Class cls, List<ir.DartType> typeArguments) { | |
| 338 return new InterfaceType(getClass(cls), getDartTypes(typeArguments)); | |
| 339 } | |
| 340 | |
| 341 @override | |
| 342 InterfaceType getInterfaceType(ir.InterfaceType type) => | |
| 343 _typeConverter.convert(type); | |
| 344 | |
| 345 @override | |
| 346 List<DartType> getDartTypes(List<ir.DartType> types) { | |
| 347 // TODO(johnniwinther): Add the type argument to the list literal when we | |
| 348 // no longer use resolution types. | |
| 349 List<DartType> list = /*<DartType>*/ []; | |
| 350 types.forEach((ir.DartType type) { | |
| 351 list.add(getDartType(type)); | |
| 352 }); | |
| 353 return list; | |
| 354 } | |
| 355 | |
| 356 void _ensureThisAndRawType(KClass cls, KClassEnv env) { | |
| 357 if (env.thisType == null) { | |
| 358 ir.Class node = env.cls; | |
| 359 // TODO(johnniwinther): Add the type argument to the list literal when we | |
| 360 // no longer use resolution types. | |
| 361 if (node.typeParameters.isEmpty) { | |
| 362 env.thisType = | |
| 363 env.rawType = new InterfaceType(cls, const/*<DartType>*/ []); | |
| 364 } else { | |
| 365 env.thisType = new InterfaceType( | |
| 366 cls, | |
| 367 new List/*<DartType>*/ .generate(node.typeParameters.length, | |
| 368 (int index) { | |
| 369 return new TypeVariableType( | |
| 370 _getTypeVariable(node.typeParameters[index])); | |
| 371 })); | |
| 372 env.rawType = new InterfaceType( | |
| 373 cls, | |
| 374 new List/*<DartType>*/ .filled( | |
| 375 node.typeParameters.length, const DynamicType())); | |
| 376 } | |
| 377 } | |
| 378 } | |
| 379 | |
| 380 InterfaceType _getThisType(KClass cls) { | |
| 381 KClassEnv env = _classEnvs[cls.classIndex]; | |
| 382 _ensureThisAndRawType(cls, env); | |
| 383 return env.thisType; | |
| 384 } | |
| 385 | |
| 386 InterfaceType _getRawType(KClass cls) { | |
| 387 KClassEnv env = _classEnvs[cls.classIndex]; | |
| 388 _ensureThisAndRawType(cls, env); | |
| 389 return env.rawType; | |
| 390 } | |
| 391 | |
| 392 void _ensureSupertypes(KClass cls, KClassEnv env) { | |
| 393 if (env.supertypes == null) { | |
| 394 _ensureThisAndRawType(cls, env); | |
| 395 | |
| 396 ir.Class node = env.cls; | |
| 397 | |
| 398 Set<InterfaceType> supertypes = new Set<InterfaceType>(); | |
| 399 | |
| 400 InterfaceType addSupertype(ir.Supertype node) { | |
| 401 if (node == null) return null; | |
| 402 InterfaceType type = _typeConverter.visitSupertype(node); | |
| 403 KClass superclass = type.element; | |
| 404 KClassEnv env = _classEnvs[superclass.classIndex]; | |
| 405 _ensureSupertypes(superclass, env); | |
| 406 for (InterfaceType supertype in env.supertypes) { | |
| 407 supertypes.add( | |
| 408 supertype.subst(type.typeArguments, env.thisType.typeArguments)); | |
| 409 } | |
| 410 return type; | |
| 411 } | |
| 412 | |
| 413 env.supertype = addSupertype(node.supertype); | |
| 414 addSupertype(node.mixedInType); | |
| 415 node.implementedTypes.forEach(addSupertype); | |
| 416 | |
| 417 env.supertypes = supertypes.toList(); | |
| 418 } | |
| 419 } | |
| 420 | |
| 421 InterfaceType _getSuperType(KClass cls) { | |
| 422 KClassEnv env = _classEnvs[cls.classIndex]; | |
| 423 _ensureSupertypes(cls, env); | |
| 424 return env.supertype; | |
| 425 } | |
| 426 | |
| 427 void _forEachSupertype(KClass cls, void f(InterfaceType supertype)) { | |
| 428 KClassEnv env = _classEnvs[cls.classIndex]; | |
| 429 _ensureSupertypes(cls, env); | |
| 430 env.supertypes.forEach(f); | |
| 431 } | |
| 432 | |
| 433 @override | |
| 434 FunctionType getFunctionType(ir.FunctionNode node) { | |
| 435 DartType returnType = getDartType(node.returnType); | |
| 436 List<DartType> parameterTypes = /*<DartType>*/ []; | |
| 437 List<DartType> optionalParameterTypes = /*<DartType>*/ []; | |
| 438 for (ir.VariableDeclaration variable in node.positionalParameters) { | |
| 439 if (parameterTypes.length == node.requiredParameterCount) { | |
| 440 optionalParameterTypes.add(getDartType(variable.type)); | |
| 441 } else { | |
| 442 parameterTypes.add(getDartType(variable.type)); | |
| 443 } | |
| 444 } | |
| 445 List<String> namedParameters = <String>[]; | |
| 446 List<DartType> namedParameterTypes = /*<DartType>*/ []; | |
| 447 List<ir.VariableDeclaration> sortedNamedParameters = | |
| 448 node.namedParameters.toList()..sort((a, b) => a.name.compareTo(b.name)); | |
| 449 for (ir.VariableDeclaration variable in sortedNamedParameters) { | |
| 450 namedParameters.add(variable.name); | |
| 451 namedParameterTypes.add(getDartType(variable.type)); | |
| 452 } | |
| 453 return new FunctionType(returnType, parameterTypes, optionalParameterTypes, | |
| 454 namedParameters, namedParameterTypes); | |
| 455 } | |
| 456 | |
| 457 LibraryEntity getLibrary(ir.Library node) => _getLibrary(node); | |
| 458 | |
| 459 ir.Library getKernelLibrary(KLibrary entity) => | |
| 460 _libraryEnvs[entity.libraryIndex].library; | |
| 461 | |
| 462 ir.Class getKernelClass(KClass entity) => _classEnvs[entity.classIndex].cls; | |
| 463 | |
| 464 @override | |
| 465 Local getLocalFunction(ir.TreeNode node) => _getLocal(node); | |
| 466 | |
| 467 @override | |
| 468 ClassEntity getClass(ir.Class node) => _getClass(node); | |
| 469 | |
| 470 @override | |
| 471 FieldEntity getField(ir.Field node) => _getField(node); | |
| 472 | |
| 473 TypeVariableEntity getTypeVariable(ir.TypeParameter node) => | |
| 474 _getTypeVariable(node); | |
| 475 | |
| 476 @override | |
| 477 FunctionEntity getMethod(ir.Procedure node) => _getMethod(node); | |
| 478 | |
| 479 @override | |
| 480 MemberEntity getMember(ir.Member node) { | |
| 481 if (node is ir.Field) { | |
| 482 return _getField(node); | |
| 483 } else if (node is ir.Constructor) { | |
| 484 return _getConstructor(node); | |
| 485 } else if (node is ir.Procedure) { | |
| 486 if (node.kind == ir.ProcedureKind.Factory) { | |
| 487 return _getConstructor(node); | |
| 488 } else { | |
| 489 return _getMethod(node); | |
| 490 } | |
| 491 } | |
| 492 throw new UnsupportedError("Unexpected member: $node"); | |
| 493 } | |
| 494 | |
| 495 @override | |
| 496 FunctionEntity getConstructor(ir.Member node) => _getConstructor(node); | |
| 497 | |
| 498 ConstantConstructor _getConstructorConstant(KConstructor constructor) { | |
| 499 return _constructorConstantMap.putIfAbsent(constructor, () { | |
| 500 ir.Member node = _memberList[constructor.memberIndex]; | |
| 501 if (node is ir.Constructor && node.isConst) { | |
| 502 return new Constantifier(this).computeConstantConstructor(node); | |
| 503 } | |
| 504 throw new SpannableAssertionFailure( | |
| 505 constructor, | |
| 506 "Unexpected constructor $constructor in " | |
| 507 "KernelWorldBuilder._getConstructorConstant"); | |
| 508 }); | |
| 509 } | |
| 510 | |
| 511 ConstantExpression _getFieldConstant(KField field) { | |
| 512 return _fieldConstantMap.putIfAbsent(field, () { | |
| 513 ir.Field node = _memberList[field.memberIndex]; | |
| 514 if (node.isConst) { | |
| 515 return new Constantifier(this).visit(node.initializer); | |
| 516 } | |
| 517 throw new SpannableAssertionFailure( | |
| 518 field, | |
| 519 "Unexpected field $field in " | |
| 520 "KernelWorldBuilder._getConstructorConstant"); | |
| 521 }); | |
| 522 } | |
| 523 | |
| 524 ResolutionImpact computeWorldImpact(KMember member) { | |
| 525 ir.Member node = _memberList[member.memberIndex]; | |
| 526 return buildKernelImpact(node, this); | |
| 527 } | |
| 528 } | |
| 529 | |
| 530 /// Environment for fast lookup of program libraries. | |
| 531 class KEnv { | |
| 532 final ir.Program program; | |
| 533 | |
| 534 Map<Uri, KLibraryEnv> _libraryMap; | |
| 535 | |
| 536 KEnv(this.program); | |
| 537 | |
| 538 /// Return the [KLibraryEnv] for the library with the canonical [uri]. | |
| 539 KLibraryEnv lookupLibrary(Uri uri) { | |
| 540 if (_libraryMap == null) { | |
| 541 _libraryMap = <Uri, KLibraryEnv>{}; | |
| 542 for (ir.Library library in program.libraries) { | |
| 543 _libraryMap[library.importUri] = new KLibraryEnv(library); | |
| 544 } | |
| 545 } | |
| 546 return _libraryMap[uri]; | |
| 547 } | |
| 548 } | |
| 549 | |
| 550 /// Environment for fast lookup of library classes and members. | |
| 551 // TODO(johnniwinther): Add member lookup. | |
| 552 class KLibraryEnv { | |
| 553 final ir.Library library; | |
| 554 | |
| 555 Map<String, KClassEnv> _classMap; | |
| 556 Map<String, ir.Member> _memberMap; | |
| 557 | |
| 558 KLibraryEnv(this.library); | |
| 559 | |
| 560 /// Return the [KClassEnv] for the class [name] in [library]. | |
| 561 KClassEnv lookupClass(String name) { | |
| 562 if (_classMap == null) { | |
| 563 _classMap = <String, KClassEnv>{}; | |
| 564 for (ir.Class cls in library.classes) { | |
| 565 _classMap[cls.name] = new KClassEnv(cls); | |
| 566 } | |
| 567 } | |
| 568 return _classMap[name]; | |
| 569 } | |
| 570 | |
| 571 /// Return the [ir.Member] for the member [name] in [library]. | |
| 572 ir.Member lookupMember(String name, {bool setter: false}) { | |
| 573 if (_memberMap == null) { | |
| 574 _memberMap = <String, ir.Member>{}; | |
| 575 for (ir.Member member in library.members) { | |
| 576 // TODO(johnniwinther): Support setter vs. getter. | |
| 577 _memberMap[member.name.name] = member; | |
| 578 } | |
| 579 } | |
| 580 return _memberMap[name]; | |
| 581 } | |
| 582 } | |
| 583 | |
| 584 /// Environment for fast lookup of class members. | |
| 585 // TODO(johnniwinther): Add member lookup. | |
| 586 class KClassEnv { | |
| 587 final ir.Class cls; | |
| 588 | |
| 589 InterfaceType thisType; | |
| 590 InterfaceType rawType; | |
| 591 InterfaceType supertype; | |
| 592 List<InterfaceType> supertypes; | |
| 593 | |
| 594 Map<String, ir.Member> _constructorMap; | |
| 595 Map<String, ir.Member> _memberMap; | |
| 596 | |
| 597 KClassEnv(this.cls); | |
| 598 | |
| 599 void _ensureMaps() { | |
| 600 if (_memberMap == null) { | |
| 601 _memberMap = <String, ir.Member>{}; | |
| 602 _constructorMap = <String, ir.Member>{}; | |
| 603 for (ir.Member member in cls.members) { | |
| 604 if (member is ir.Procedure && member.kind == ir.ProcedureKind.Factory) { | |
| 605 _constructorMap[member.name.name] = member; | |
| 606 } else { | |
| 607 // TODO(johnniwinther): Support setter vs. getter. | |
| 608 _memberMap[member.name.name] = member; | |
| 609 } | |
| 610 } | |
| 611 for (ir.Member member in cls.constructors) { | |
| 612 _constructorMap[member.name.name] = member; | |
| 613 } | |
| 614 } | |
| 615 } | |
| 616 | |
| 617 /// Return the [ir.Member] for the member [name] in [library]. | |
| 618 ir.Member lookupMember(String name, {bool setter: false}) { | |
| 619 _ensureMaps(); | |
| 620 return _memberMap[name]; | |
| 621 } | |
| 622 | |
| 623 /// Return the [ir.Member] for the member [name] in [library]. | |
| 624 ir.Member lookupConstructor(String name, {bool setter: false}) { | |
| 625 _ensureMaps(); | |
| 626 return _constructorMap[name]; | |
| 627 } | |
| 628 } | |
| 629 | |
| 630 class KernelElementEnvironment implements ElementEnvironment { | |
| 631 final KernelWorldBuilder worldBuilder; | |
| 632 | |
| 633 KernelElementEnvironment(this.worldBuilder); | |
| 634 | |
| 635 @override | |
| 636 DartType get dynamicType => const DynamicType(); | |
| 637 | |
| 638 @override | |
| 639 LibraryEntity get mainLibrary => worldBuilder._mainLibrary; | |
| 640 | |
| 641 @override | |
| 642 FunctionEntity get mainFunction => worldBuilder._mainFunction; | |
| 643 | |
| 644 @override | |
| 645 Iterable<LibraryEntity> get libraries => worldBuilder._libraryMap.values; | |
| 646 | |
| 647 @override | |
| 648 InterfaceType getThisType(ClassEntity cls) { | |
| 649 return worldBuilder._getThisType(cls); | |
| 650 } | |
| 651 | |
| 652 @override | |
| 653 InterfaceType getRawType(ClassEntity cls) { | |
| 654 return worldBuilder._getRawType(cls); | |
| 655 } | |
| 656 | |
| 657 @override | |
| 658 DartType getTypeVariableBound(TypeVariableEntity typeVariable) { | |
| 659 throw new UnimplementedError( | |
| 660 'KernelElementEnvironment.getTypeVariableBound'); | |
| 661 } | |
| 662 | |
| 663 @override | |
| 664 InterfaceType createInterfaceType( | |
| 665 ClassEntity cls, List<DartType> typeArguments) { | |
| 666 return new InterfaceType(cls, typeArguments); | |
| 667 } | |
| 668 | |
| 669 @override | |
| 670 bool isSubtype(DartType a, DartType b) { | |
| 671 // TODO(johnniwinther): Implement this. | |
| 672 return false; | |
| 673 } | |
| 674 | |
| 675 @override | |
| 676 FunctionType getFunctionType(KFunction function) { | |
| 677 throw new UnimplementedError('KernelElementEnvironment.getFunctionType'); | |
| 678 } | |
| 679 | |
| 680 @override | |
| 681 FunctionType getLocalFunctionType(KLocalFunction function) { | |
| 682 return function.functionType; | |
| 683 } | |
| 684 | |
| 685 @override | |
| 686 DartType getUnaliasedType(DartType type) => type; | |
| 687 | |
| 688 @override | |
| 689 ConstructorEntity lookupConstructor(ClassEntity cls, String name, | |
| 690 {bool required: false}) { | |
| 691 ConstructorEntity constructor = worldBuilder.lookupConstructor(cls, name); | |
| 692 if (constructor == null && required) { | |
| 693 throw new SpannableAssertionFailure( | |
| 694 CURRENT_ELEMENT_SPANNABLE, | |
| 695 "The constructor '$name' was not found in class '${cls.name}' " | |
| 696 "in library ${cls.library.canonicalUri}."); | |
| 697 } | |
| 698 return constructor; | |
| 699 } | |
| 700 | |
| 701 @override | |
| 702 MemberEntity lookupClassMember(ClassEntity cls, String name, | |
| 703 {bool setter: false, bool required: false}) { | |
| 704 MemberEntity member = | |
| 705 worldBuilder.lookupClassMember(cls, name, setter: setter); | |
| 706 if (member == null && required) { | |
| 707 throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE, | |
| 708 "The member '$name' was not found in ${cls.name}."); | |
| 709 } | |
| 710 return member; | |
| 711 } | |
| 712 | |
| 713 @override | |
| 714 ClassEntity getSuperClass(ClassEntity cls) { | |
| 715 return worldBuilder._getSuperType(cls)?.element; | |
| 716 } | |
| 717 | |
| 718 @override | |
| 719 void forEachSupertype(ClassEntity cls, void f(InterfaceType supertype)) { | |
| 720 worldBuilder._forEachSupertype(cls, f); | |
| 721 } | |
| 722 | |
| 723 @override | |
| 724 void forEachMixin(ClassEntity cls, void f(ClassEntity mixin)) { | |
| 725 throw new UnimplementedError('KernelElementEnvironment.forEachMixin'); | |
| 726 } | |
| 727 | |
| 728 @override | |
| 729 void forEachClassMember( | |
| 730 ClassEntity cls, void f(ClassEntity declarer, MemberEntity member)) { | |
| 731 // TODO(johnniwinther): Implement this. | |
| 732 } | |
| 733 | |
| 734 @override | |
| 735 MemberEntity lookupLibraryMember(LibraryEntity library, String name, | |
| 736 {bool setter: false, bool required: false}) { | |
| 737 MemberEntity member = | |
| 738 worldBuilder.lookupLibraryMember(library, name, setter: setter); | |
| 739 if (member == null && required) { | |
| 740 throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE, | |
| 741 "The member '${name}' was not found in library '${library.name}'."); | |
| 742 } | |
| 743 return member; | |
| 744 } | |
| 745 | |
| 746 @override | |
| 747 ClassEntity lookupClass(LibraryEntity library, String name, | |
| 748 {bool required: false}) { | |
| 749 ClassEntity cls = worldBuilder.lookupClass(library, name); | |
| 750 if (cls == null && required) { | |
| 751 throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE, | |
| 752 "The class '$name' was not found in library '${library.name}'."); | |
| 753 } | |
| 754 return cls; | |
| 755 } | |
| 756 | |
| 757 @override | |
| 758 LibraryEntity lookupLibrary(Uri uri, {bool required: false}) { | |
| 759 LibraryEntity library = worldBuilder.lookupLibrary(uri); | |
| 760 if (library == null && required) { | |
| 761 throw new SpannableAssertionFailure( | |
| 762 CURRENT_ELEMENT_SPANNABLE, "The library '$uri' was not found."); | |
| 763 } | |
| 764 return library; | |
| 765 } | |
| 766 | |
| 767 @override | |
| 768 CallStructure getCallStructure(KFunction function) { | |
| 769 ir.Member member = worldBuilder._memberList[function.memberIndex]; | |
| 770 ir.FunctionNode functionNode; | |
| 771 if (member is ir.Procedure) { | |
| 772 functionNode = member.function; | |
| 773 } else if (member is ir.Constructor) { | |
| 774 functionNode = member.function; | |
| 775 } else { | |
| 776 throw new SpannableAssertionFailure( | |
| 777 function, "Unexpected function node ${member} for $function."); | |
| 778 } | |
| 779 return new CallStructure( | |
| 780 functionNode.positionalParameters.length + | |
| 781 functionNode.namedParameters.length, | |
| 782 functionNode.namedParameters.map((d) => d.name).toList()); | |
| 783 } | |
| 784 | |
| 785 @override | |
| 786 bool isDeferredLoadLibraryGetter(KMember member) { | |
| 787 // TODO(johnniwinther): Support these. | |
| 788 return false; | |
| 789 } | |
| 790 } | |
| 791 | |
| 792 /// Visitor that converts kernel dart types into [DartType]. | |
| 793 class DartTypeConverter extends ir.DartTypeVisitor<DartType> { | |
| 794 final KernelWorldBuilder elementAdapter; | |
| 795 bool topLevel = true; | |
| 796 | |
| 797 DartTypeConverter(this.elementAdapter); | |
| 798 | |
| 799 DartType convert(ir.DartType type) { | |
| 800 topLevel = true; | |
| 801 return type.accept(this); | |
| 802 } | |
| 803 | |
| 804 /// Visit a inner type. | |
| 805 DartType visitType(ir.DartType type) { | |
| 806 topLevel = false; | |
| 807 return type.accept(this); | |
| 808 } | |
| 809 | |
| 810 InterfaceType visitSupertype(ir.Supertype node) { | |
| 811 ClassEntity cls = elementAdapter.getClass(node.classNode); | |
| 812 return new InterfaceType(cls, visitTypes(node.typeArguments)); | |
| 813 } | |
| 814 | |
| 815 List<DartType> visitTypes(List<ir.DartType> types) { | |
| 816 topLevel = false; | |
| 817 return new List.generate( | |
| 818 types.length, (int index) => types[index].accept(this)); | |
| 819 } | |
| 820 | |
| 821 @override | |
| 822 DartType visitTypeParameterType(ir.TypeParameterType node) { | |
| 823 return new TypeVariableType(elementAdapter.getTypeVariable(node.parameter)); | |
| 824 } | |
| 825 | |
| 826 @override | |
| 827 DartType visitFunctionType(ir.FunctionType node) { | |
| 828 return new FunctionType( | |
| 829 visitType(node.returnType), | |
| 830 visitTypes(node.positionalParameters | |
| 831 .take(node.requiredParameterCount) | |
| 832 .toList()), | |
| 833 visitTypes(node.positionalParameters | |
| 834 .skip(node.requiredParameterCount) | |
| 835 .toList()), | |
| 836 node.namedParameters.map((n) => n.name).toList(), | |
| 837 node.namedParameters.map((n) => visitType(n.type)).toList()); | |
| 838 } | |
| 839 | |
| 840 @override | |
| 841 DartType visitInterfaceType(ir.InterfaceType node) { | |
| 842 ClassEntity cls = elementAdapter.getClass(node.classNode); | |
| 843 return new InterfaceType(cls, visitTypes(node.typeArguments)); | |
| 844 } | |
| 845 | |
| 846 @override | |
| 847 DartType visitVoidType(ir.VoidType node) { | |
| 848 return const VoidType(); | |
| 849 } | |
| 850 | |
| 851 @override | |
| 852 DartType visitDynamicType(ir.DynamicType node) { | |
| 853 return const DynamicType(); | |
| 854 } | |
| 855 | |
| 856 @override | |
| 857 DartType visitInvalidType(ir.InvalidType node) { | |
| 858 if (topLevel) { | |
| 859 throw new UnimplementedError( | |
| 860 "Outermost invalid types not currently supported"); | |
| 861 } | |
| 862 // Nested invalid types are treated as `dynamic`. | |
| 863 return const DynamicType(); | |
| 864 } | |
| 865 } | |
| 866 | |
| 867 /// [native.BehaviorBuilder] for kernel based elements. | |
| 868 class KernelBehaviorBuilder extends native.BehaviorBuilder { | |
| 869 final CommonElements commonElements; | |
| 870 final ConstantEnvironment constants; | |
| 871 | |
| 872 KernelBehaviorBuilder( | |
| 873 this.commonElements, | |
| 874 this.constants, | |
| 875 ); | |
| 876 | |
| 877 @override | |
| 878 bool get trustJSInteropTypeAnnotations { | |
| 879 throw new UnimplementedError( | |
| 880 "KernelNativeBehaviorComputer.trustJSInteropTypeAnnotations"); | |
| 881 } | |
| 882 | |
| 883 @override | |
| 884 DiagnosticReporter get reporter { | |
| 885 throw new UnimplementedError("KernelNativeBehaviorComputer.reporter"); | |
| 886 } | |
| 887 | |
| 888 @override | |
| 889 NativeData get nativeData { | |
| 890 throw new UnimplementedError("KernelNativeBehaviorComputer.nativeData"); | |
| 891 } | |
| 892 } | |
| 893 | |
| 894 /// Constant environment mapping [ConstantExpression]s to [ConstantValue]s using | |
| 895 /// [_EvaluationEnvironment] for the evaluation. | |
| 896 class KernelConstantEnvironment implements ConstantEnvironment { | |
| 897 KernelWorldBuilder _worldBuilder; | |
| 898 Map<ConstantExpression, ConstantValue> _valueMap = | |
| 899 <ConstantExpression, ConstantValue>{}; | |
| 900 | |
| 901 KernelConstantEnvironment(this._worldBuilder); | |
| 902 | |
| 903 @override | |
| 904 ConstantSystem get constantSystem => const JavaScriptConstantSystem(); | |
| 905 | |
| 906 @override | |
| 907 ConstantValue getConstantValueForVariable(VariableElement element) { | |
| 908 throw new UnimplementedError( | |
| 909 "KernelConstantEnvironment.getConstantValueForVariable"); | |
| 910 } | |
| 911 | |
| 912 @override | |
| 913 ConstantValue getConstantValue(ConstantExpression expression) { | |
| 914 return _valueMap.putIfAbsent(expression, () { | |
| 915 return expression.evaluate( | |
| 916 new _EvaluationEnvironment(_worldBuilder), constantSystem); | |
| 917 }); | |
| 918 } | |
| 919 | |
| 920 @override | |
| 921 bool hasConstantValue(ConstantExpression expression) { | |
| 922 throw new UnimplementedError("KernelConstantEnvironment.hasConstantValue"); | |
| 923 } | |
| 924 } | |
| 925 | |
| 926 /// Evaluation environment used for computing [ConstantValue]s for | |
| 927 /// kernel based [ConstantExpression]s. | |
| 928 class _EvaluationEnvironment implements Environment { | |
| 929 final KernelWorldBuilder _worldBuilder; | |
| 930 | |
| 931 _EvaluationEnvironment(this._worldBuilder); | |
| 932 | |
| 933 @override | |
| 934 CommonElements get commonElements { | |
| 935 throw new UnimplementedError("_EvaluationEnvironment.commonElements"); | |
| 936 } | |
| 937 | |
| 938 @override | |
| 939 InterfaceType substByContext(InterfaceType base, InterfaceType target) { | |
| 940 if (base.typeArguments.isNotEmpty) { | |
| 941 throw new UnimplementedError("_EvaluationEnvironment.substByContext"); | |
| 942 } | |
| 943 return base; | |
| 944 } | |
| 945 | |
| 946 @override | |
| 947 ConstantConstructor getConstructorConstant(ConstructorEntity constructor) { | |
| 948 return _worldBuilder._getConstructorConstant(constructor); | |
| 949 } | |
| 950 | |
| 951 @override | |
| 952 ConstantExpression getFieldConstant(FieldEntity field) { | |
| 953 return _worldBuilder._getFieldConstant(field); | |
| 954 } | |
| 955 | |
| 956 @override | |
| 957 ConstantExpression getLocalConstant(Local local) { | |
| 958 throw new UnimplementedError("_EvaluationEnvironment.getLocalConstant"); | |
| 959 } | |
| 960 | |
| 961 @override | |
| 962 String readFromEnvironment(String name) { | |
| 963 throw new UnimplementedError("_EvaluationEnvironment.readFromEnvironment"); | |
| 964 } | |
| 965 } | |
| 966 | |
| 967 // Interface for testing equivalence of Kernel-based entities. | |
| 968 class WorldDeconstructionForTesting { | |
| 969 final KernelWorldBuilder builder; | |
| 970 | |
| 971 WorldDeconstructionForTesting(this.builder); | |
| 972 | |
| 973 Uri getLibraryUri(KLibrary library) { | |
| 974 return builder._libraryEnvs[library.libraryIndex].library.importUri; | |
| 975 } | |
| 976 | |
| 977 KLibrary getLibraryForClass(KClass cls) { | |
| 978 KClassEnv env = builder._classEnvs[cls.classIndex]; | |
| 979 return builder.getLibrary(env.cls.enclosingLibrary); | |
| 980 } | |
| 981 | |
| 982 KLibrary _getLibrary<E>(E member, Map<ir.Member, E> map) { | |
| 983 ir.Library library; | |
| 984 map.forEach((ir.Member node, E other) { | |
| 985 if (library == null && member == other) { | |
| 986 library = node.enclosingLibrary; | |
| 987 } | |
| 988 }); | |
| 989 if (library == null) { | |
| 990 throw new ArgumentError("No library found for $member"); | |
| 991 } | |
| 992 return builder._getLibrary(library); | |
| 993 } | |
| 994 | |
| 995 KLibrary getLibraryForFunction(KFunction function) => | |
| 996 _getLibrary(function, builder._methodMap); | |
| 997 | |
| 998 KLibrary getLibraryForField(KField field) => | |
| 999 _getLibrary(field, builder._fieldMap); | |
| 1000 | |
| 1001 KClass getSuperclassForClass(KClass cls) { | |
| 1002 KClassEnv env = builder._classEnvs[cls.classIndex]; | |
| 1003 ir.Supertype supertype = env.cls.supertype; | |
| 1004 if (supertype == null) return null; | |
| 1005 return builder.getClass(supertype.classNode); | |
| 1006 } | |
| 1007 | |
| 1008 InterfaceType getMixinTypeForClass(KClass cls) { | |
| 1009 KClassEnv env = builder._classEnvs[cls.classIndex]; | |
| 1010 ir.Supertype mixedInType = env.cls.mixedInType; | |
| 1011 if (mixedInType == null) return null; | |
| 1012 return builder.createInterfaceType( | |
| 1013 mixedInType.classNode, mixedInType.typeArguments); | |
| 1014 } | |
| 1015 } | |
| OLD | NEW |