Chromium Code Reviews| 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 import 'package:kernel/ast.dart' as ir; | |
| 6 | |
| 7 import '../common.dart'; | |
| 8 import '../common/names.dart'; | |
| 9 import '../core_types.dart'; | |
| 10 import '../elements/elements.dart'; | |
| 11 import '../elements/entities.dart'; | |
| 12 import '../elements/types.dart'; | |
| 13 import '../native/native.dart' as native; | |
| 14 import 'element_adapter.dart'; | |
| 15 import 'elements.dart'; | |
| 16 | |
| 17 /// World builder used for creating elements and types corresponding to Kernel | |
| 18 /// IR nodes. | |
| 19 // TODO(johnniwinther): Implement [ResolutionWorldBuilder]. | |
| 20 class KernelWorldBuilder extends KernelElementAdapterMixin { | |
| 21 CommonElements _commonElements; | |
| 22 final DiagnosticReporter reporter; | |
| 23 | |
| 24 DartTypeConverter _typeConverter; | |
| 25 | |
| 26 /// Library environment. Used for fast lookup. | |
| 27 KEnv _env; | |
|
Siggi Cherem (dart-lang)
2017/01/30 20:31:36
Asger has a change that will be adding canonical n
Johnni Winther
2017/01/31 09:27:25
We need more. The CL provides `lookupLibrary(Uri)`
| |
| 28 | |
| 29 /// List of library environments by `KLibrary.libraryIndex`. This is used for | |
| 30 /// fast lookup into library classes and members. | |
| 31 List<KLibraryEnv> _libraryEnvs = <KLibraryEnv>[]; | |
| 32 | |
| 33 Map<ir.Library, KLibrary> _libraryMap = <ir.Library, KLibrary>{}; | |
| 34 Map<ir.Class, KClass> _classMap = <ir.Class, KClass>{}; | |
| 35 Map<ir.TypeParameter, KTypeVariable> _typeVariableMap = | |
| 36 <ir.TypeParameter, KTypeVariable>{}; | |
| 37 Map<ir.Member, KConstructor> _constructorMap = <ir.Member, KConstructor>{}; | |
| 38 Map<ir.Procedure, KFunction> _methodMap = <ir.Procedure, KFunction>{}; | |
| 39 Map<ir.Field, KField> _fieldMap = <ir.Field, KField>{}; | |
| 40 Map<ir.TreeNode, KLocalFunction> _localFunctionMap = | |
| 41 <ir.TreeNode, KLocalFunction>{}; | |
| 42 | |
| 43 KernelWorldBuilder(this.reporter, ir.Program program) | |
| 44 : _env = new KEnv(program) { | |
| 45 _commonElements = new KernelCommonElements(this); | |
| 46 _typeConverter = new DartTypeConverter(this); | |
| 47 } | |
| 48 | |
| 49 CommonElements get commonElements => _commonElements; | |
| 50 | |
| 51 LibraryEntity lookupLibrary(Uri uri) { | |
| 52 KLibraryEnv libraryEnv = _env.lookupLibrary(uri); | |
| 53 return _getLibrary(libraryEnv.library, libraryEnv); | |
| 54 } | |
| 55 | |
| 56 KLibrary _getLibrary(ir.Library node, [KLibraryEnv libraryEnv]) { | |
| 57 return _libraryMap.putIfAbsent(node, () { | |
| 58 _libraryEnvs.add(libraryEnv ?? _env.lookupLibrary(node.importUri)); | |
| 59 return new KLibrary(_libraryMap.length, node.name, node.fileUri); | |
| 60 }); | |
| 61 } | |
| 62 | |
| 63 ClassEntity lookupClass(KLibrary library, String name) { | |
| 64 KLibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; | |
| 65 KClassEnv classEnv = libraryEnv.lookupClass(name); | |
| 66 return _getClass(classEnv.cls, classEnv); | |
| 67 } | |
| 68 | |
| 69 KClass _getClass(ir.Class node, [KClassEnv classEnv]) { | |
| 70 return _classMap.putIfAbsent(node, () { | |
| 71 return new KClass(node.name); | |
| 72 }); | |
| 73 } | |
| 74 | |
| 75 KTypeVariable _getTypeVariable(ir.TypeParameter node) { | |
| 76 return _typeVariableMap.putIfAbsent(node, () { | |
| 77 if (node.parent is ir.Class) { | |
| 78 ir.Class cls = node.parent; | |
| 79 int index = cls.typeParameters.indexOf(node); | |
| 80 return new KTypeVariable(_getClass(cls), node.name, index); | |
| 81 } else if (node.parent is ir.FunctionNode) { | |
|
Siggi Cherem (dart-lang)
2017/01/30 20:31:36
nit: since there is a return above, remove else he
Johnni Winther
2017/01/31 09:27:25
Done.
| |
| 82 ir.FunctionNode func = node.parent; | |
| 83 int index = func.typeParameters.indexOf(node); | |
| 84 if (func.parent is ir.Constructor) { | |
| 85 ir.Constructor constructor = func.parent; | |
| 86 ir.Class cls = constructor.enclosingClass; | |
| 87 return _getTypeVariable(cls.typeParameters[index]); | |
| 88 } else if (func.parent is ir.Procedure) { | |
|
Siggi Cherem (dart-lang)
2017/01/30 20:31:36
same here
Johnni Winther
2017/01/31 09:27:25
Done.
| |
| 89 ir.Procedure procedure = func.parent; | |
| 90 if (procedure.kind == ir.ProcedureKind.Factory) { | |
| 91 ir.Class cls = procedure.enclosingClass; | |
| 92 return _getTypeVariable(cls.typeParameters[index]); | |
| 93 } else { | |
| 94 return new KTypeVariable(_getMethod(procedure), node.name, index); | |
| 95 } | |
| 96 } | |
| 97 } | |
| 98 throw new UnsupportedError('Unsupported type parameter type node $node.'); | |
| 99 }); | |
| 100 } | |
| 101 | |
| 102 KConstructor _getConstructor(ir.Member node) { | |
| 103 return _constructorMap.putIfAbsent(node, () { | |
| 104 if (node is ir.Constructor) { | |
| 105 return new KGenerativeConstructor( | |
| 106 _getClass(node.enclosingClass), getName(node.name)); | |
| 107 } else { | |
| 108 return new KFactoryConstructor( | |
| 109 _getClass(node.enclosingClass), getName(node.name)); | |
| 110 } | |
| 111 }); | |
| 112 } | |
| 113 | |
| 114 KFunction _getMethod(ir.Procedure node) { | |
| 115 return _methodMap.putIfAbsent(node, () { | |
| 116 KClass enclosingClass = | |
| 117 node.enclosingClass != null ? _getClass(node.enclosingClass) : null; | |
| 118 Name name = getName(node.name); | |
| 119 bool isStatic = node.isStatic; | |
| 120 switch (node.kind) { | |
| 121 case ir.ProcedureKind.Factory: | |
| 122 throw new UnsupportedError("Cannot create method from factory."); | |
| 123 case ir.ProcedureKind.Getter: | |
| 124 return new KGetter(enclosingClass, name, isStatic: isStatic); | |
| 125 case ir.ProcedureKind.Method: | |
| 126 case ir.ProcedureKind.Operator: | |
| 127 return new KMethod(enclosingClass, name, isStatic: isStatic); | |
| 128 case ir.ProcedureKind.Setter: | |
| 129 return new KSetter(enclosingClass, getName(node.name).setter, | |
| 130 isStatic: isStatic); | |
| 131 } | |
| 132 }); | |
| 133 } | |
| 134 | |
| 135 KField _getField(ir.Field node) { | |
| 136 return _fieldMap.putIfAbsent(node, () { | |
| 137 KClass enclosingClass = | |
| 138 node.enclosingClass != null ? _getClass(node.enclosingClass) : null; | |
| 139 Name name = getName(node.name); | |
| 140 bool isStatic = node.isStatic; | |
| 141 return new KField(enclosingClass, name, | |
| 142 isStatic: isStatic, isAssignable: node.isMutable); | |
| 143 }); | |
| 144 } | |
| 145 | |
| 146 KLocalFunction _getLocal(ir.TreeNode node) { | |
| 147 return _localFunctionMap.putIfAbsent(node, () { | |
| 148 MemberEntity memberContext; | |
| 149 Entity executableContext; | |
| 150 ir.TreeNode parent = node.parent; | |
| 151 while (parent != null) { | |
| 152 if (parent is ir.Member) { | |
| 153 executableContext = memberContext = getMember(parent); | |
| 154 break; | |
| 155 } | |
| 156 if (parent is ir.FunctionDeclaration || | |
| 157 parent is ir.FunctionExpression) { | |
| 158 KLocalFunction localFunction = _getLocal(parent); | |
| 159 executableContext = localFunction; | |
| 160 memberContext = localFunction.memberContext; | |
| 161 break; | |
| 162 } | |
| 163 parent = parent.parent; | |
| 164 } | |
| 165 String name; | |
| 166 if (node is ir.FunctionDeclaration) { | |
| 167 name = node.variable.name; | |
| 168 } | |
| 169 return new KLocalFunction(name, memberContext, executableContext); | |
| 170 }); | |
| 171 } | |
| 172 | |
| 173 @override | |
| 174 DartType getDartType(ir.DartType type) => _typeConverter.convert(type); | |
| 175 | |
| 176 @override | |
| 177 InterfaceType createInterfaceType( | |
| 178 ir.Class cls, List<ir.DartType> typeArguments) { | |
| 179 return new InterfaceType(getClass(cls), getDartTypes(typeArguments)); | |
| 180 } | |
| 181 | |
| 182 @override | |
| 183 InterfaceType getInterfaceType(ir.InterfaceType type) => | |
| 184 _typeConverter.convert(type); | |
| 185 | |
| 186 @override | |
| 187 List<DartType> getDartTypes(List<ir.DartType> types) { | |
| 188 // TODO(johnniwinther): Add the type argument to the list literal when we | |
| 189 // no longer use resolution types. | |
|
Siggi Cherem (dart-lang)
2017/01/30 20:31:36
why is it not allowed today? aren't resolution typ
Johnni Winther
2017/01/31 09:27:25
[ResolutionDartType] is a subtype of [DartType] bu
| |
| 190 List<DartType> list = /*<DartType>*/ []; | |
| 191 types.forEach((ir.DartType type) { | |
| 192 list.add(getDartType(type)); | |
| 193 }); | |
| 194 return list; | |
| 195 } | |
| 196 | |
| 197 @override | |
| 198 InterfaceType getThisType(ClassEntity cls) { | |
| 199 throw new UnimplementedError('KernelWorldBuilder.getThisType'); | |
| 200 } | |
| 201 | |
| 202 @override | |
| 203 InterfaceType getRawType(ClassEntity cls) { | |
| 204 throw new UnimplementedError('KernelWorldBuilder.getRawType'); | |
| 205 } | |
| 206 | |
| 207 @override | |
| 208 InterfaceType getInterfaceTypeForJsInterceptorCall(ir.StaticInvocation node) { | |
| 209 throw new UnimplementedError('KernelWorldBuilder.getDartType'); | |
| 210 } | |
| 211 | |
| 212 @override | |
| 213 native.NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall( | |
| 214 ir.StaticInvocation node) { | |
| 215 throw new UnimplementedError('KernelWorldBuilder.getDartType'); | |
| 216 } | |
| 217 | |
| 218 @override | |
| 219 native.NativeBehavior getNativeBehaviorForJsBuiltinCall( | |
| 220 ir.StaticInvocation node) { | |
| 221 throw new UnimplementedError('KernelWorldBuilder.getDartType'); | |
| 222 } | |
| 223 | |
| 224 @override | |
| 225 native.NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) { | |
| 226 throw new UnimplementedError('KernelWorldBuilder.getDartType'); | |
| 227 } | |
| 228 | |
| 229 @override | |
| 230 native.NativeBehavior getNativeBehaviorForMethod(ir.Procedure procedure) { | |
| 231 throw new UnimplementedError('KernelWorldBuilder.getDartType'); | |
| 232 } | |
| 233 | |
| 234 @override | |
| 235 native.NativeBehavior getNativeBehaviorForFieldStore(ir.Field field) { | |
| 236 throw new UnimplementedError('KernelWorldBuilder.getDartType'); | |
| 237 } | |
| 238 | |
| 239 @override | |
| 240 native.NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field) { | |
| 241 throw new UnimplementedError('KernelWorldBuilder.getDartType'); | |
| 242 } | |
| 243 | |
| 244 LibraryEntity getLibrary(ir.Library node) => _getLibrary(node); | |
| 245 | |
| 246 @override | |
| 247 Local getLocalFunction(ir.TreeNode node) => _getLocal(node); | |
| 248 | |
| 249 @override | |
| 250 ClassEntity getClass(ir.Class node) => _getClass(node); | |
| 251 | |
| 252 @override | |
| 253 FieldEntity getField(ir.Field node) => _getField(node); | |
| 254 | |
| 255 TypeVariableEntity getTypeVariable(ir.TypeParameter node) => | |
| 256 _getTypeVariable(node); | |
| 257 | |
| 258 @override | |
| 259 FunctionEntity getMethod(ir.Procedure node) => _getMethod(node); | |
| 260 | |
| 261 @override | |
| 262 MemberEntity getMember(ir.Member node) { | |
| 263 if (node is ir.Field) { | |
| 264 return _getField(node); | |
| 265 } else if (node is ir.Constructor) { | |
| 266 return _getConstructor(node); | |
| 267 } else if (node is ir.Procedure) { | |
| 268 if (node.kind == ir.ProcedureKind.Factory) { | |
| 269 return _getConstructor(node); | |
| 270 } else { | |
| 271 return _getMethod(node); | |
| 272 } | |
| 273 } | |
| 274 throw new UnsupportedError("Unexpected member: $node"); | |
| 275 } | |
| 276 | |
| 277 @override | |
| 278 FunctionEntity getConstructor(ir.Member node) => _getConstructor(node); | |
| 279 } | |
| 280 | |
| 281 /// Environment for fast lookup of program libraries. | |
| 282 class KEnv { | |
| 283 final ir.Program program; | |
| 284 | |
| 285 Map<Uri, KLibraryEnv> _libraryMap; | |
| 286 | |
| 287 KEnv(this.program); | |
| 288 | |
| 289 /// Return the [KLibraryEnv] for the library with the canonical [uri]. | |
| 290 KLibraryEnv lookupLibrary(Uri uri) { | |
| 291 if (_libraryMap == null) { | |
| 292 _libraryMap = <Uri, KLibraryEnv>{}; | |
| 293 for (ir.Library library in program.libraries) { | |
| 294 _libraryMap[library.importUri] = new KLibraryEnv(library); | |
| 295 } | |
| 296 } | |
| 297 return _libraryMap[uri]; | |
| 298 } | |
| 299 } | |
| 300 | |
| 301 /// Environment for fast lookup of library classes and members. | |
| 302 // TODO(johnniwinther): Add member lookup. | |
| 303 class KLibraryEnv { | |
| 304 final ir.Library library; | |
| 305 | |
| 306 Map<String, KClassEnv> _classMap; | |
| 307 | |
| 308 KLibraryEnv(this.library); | |
| 309 | |
| 310 /// Return the [KClassEnv] for the class [name] in [library]. | |
| 311 KClassEnv lookupClass(String name) { | |
| 312 if (_classMap == null) { | |
| 313 _classMap = <String, KClassEnv>{}; | |
| 314 for (ir.Class cls in library.classes) { | |
| 315 _classMap[cls.name] = new KClassEnv(cls); | |
| 316 } | |
| 317 } | |
| 318 return _classMap[name]; | |
| 319 } | |
| 320 } | |
| 321 | |
| 322 /// Environment for fast lookup of class members. | |
| 323 // TODO(johnniwinther): Add member lookup. | |
| 324 class KClassEnv { | |
| 325 final ir.Class cls; | |
| 326 | |
| 327 KClassEnv(this.cls); | |
| 328 } | |
| 329 | |
| 330 /// [CommonElements] implementation based on [KernelWorldBuilder]. | |
| 331 class KernelCommonElements extends CommonElementsMixin { | |
| 332 final KernelWorldBuilder worldBuilder; | |
| 333 | |
| 334 KernelCommonElements(this.worldBuilder); | |
| 335 | |
| 336 @override | |
| 337 LibraryEntity get coreLibrary { | |
| 338 return worldBuilder.lookupLibrary(Uris.dart_core); | |
| 339 } | |
| 340 | |
| 341 @override | |
| 342 InterfaceType createInterfaceType( | |
| 343 ClassEntity cls, List<DartType> typeArguments) { | |
| 344 return new InterfaceType(cls, typeArguments); | |
| 345 } | |
| 346 | |
| 347 @override | |
| 348 InterfaceType getRawType(ClassEntity cls) { | |
| 349 throw new UnimplementedError('KernelCommonElements.getRawType'); | |
| 350 } | |
| 351 | |
| 352 @override | |
| 353 FunctionEntity findConstructor(ClassEntity cls, String name, | |
| 354 {bool required: true}) { | |
| 355 throw new UnimplementedError('KernelCommonElements.findConstructor'); | |
| 356 } | |
| 357 | |
| 358 @override | |
| 359 MemberEntity findClassMember(ClassEntity cls, String name, | |
| 360 {bool required: true}) { | |
| 361 throw new UnimplementedError('KernelCommonElements.findClassMember'); | |
| 362 } | |
| 363 | |
| 364 @override | |
| 365 MemberEntity findLibraryMember(LibraryEntity library, String name, | |
| 366 {bool required: true}) { | |
| 367 throw new UnimplementedError('KernelCommonElements.findLibraryMember'); | |
| 368 } | |
| 369 | |
| 370 @override | |
| 371 ClassEntity findClass(LibraryEntity library, String name, | |
| 372 {bool required: true}) { | |
| 373 return worldBuilder.lookupClass(library, name); | |
| 374 } | |
| 375 | |
| 376 @override | |
| 377 DynamicType get dynamicType => const DynamicType(); | |
| 378 | |
| 379 @override | |
| 380 ClassEntity get nativeAnnotationClass { | |
| 381 throw new UnimplementedError('KernelCommonElements.nativeAnnotationClass'); | |
| 382 } | |
| 383 | |
| 384 @override | |
| 385 ClassEntity get patchAnnotationClass { | |
| 386 throw new UnimplementedError('KernelCommonElements.patchAnnotationClass'); | |
| 387 } | |
| 388 | |
| 389 @override | |
| 390 LibraryEntity get typedDataLibrary { | |
| 391 throw new UnimplementedError('KernelCommonElements.typedDataLibrary'); | |
| 392 } | |
| 393 | |
| 394 @override | |
| 395 LibraryEntity get mirrorsLibrary { | |
| 396 throw new UnimplementedError('KernelCommonElements.mirrorsLibrary'); | |
| 397 } | |
| 398 | |
| 399 @override | |
| 400 LibraryEntity get asyncLibrary { | |
| 401 throw new UnimplementedError('KernelCommonElements.asyncLibrary'); | |
| 402 } | |
| 403 } | |
| 404 | |
| 405 /// Visitor that converts kernel dart types into [DartType]. | |
| 406 class DartTypeConverter extends ir.DartTypeVisitor<DartType> { | |
| 407 final KernelWorldBuilder elementAdapter; | |
| 408 bool topLevel = true; | |
| 409 | |
| 410 DartTypeConverter(this.elementAdapter); | |
| 411 | |
| 412 DartType convert(ir.DartType type) { | |
| 413 topLevel = true; | |
| 414 return type.accept(this); | |
| 415 } | |
| 416 | |
| 417 /// Visit a inner type. | |
| 418 DartType visitType(ir.DartType type) { | |
| 419 topLevel = false; | |
| 420 return type.accept(this); | |
| 421 } | |
| 422 | |
| 423 List<DartType> visitTypes(List<ir.DartType> types) { | |
| 424 topLevel = false; | |
| 425 return new List.generate( | |
| 426 types.length, (int index) => types[index].accept(this)); | |
| 427 } | |
| 428 | |
| 429 @override | |
| 430 DartType visitTypeParameterType(ir.TypeParameterType node) { | |
| 431 return new TypeVariableType(elementAdapter.getTypeVariable(node.parameter)); | |
| 432 } | |
| 433 | |
| 434 @override | |
| 435 DartType visitFunctionType(ir.FunctionType node) { | |
| 436 return new FunctionType( | |
| 437 visitType(node.returnType), | |
| 438 visitTypes(node.positionalParameters | |
| 439 .take(node.requiredParameterCount) | |
| 440 .toList()), | |
| 441 visitTypes(node.positionalParameters | |
| 442 .skip(node.requiredParameterCount) | |
| 443 .toList()), | |
| 444 node.namedParameters.map((n) => n.name).toList(), | |
| 445 node.namedParameters.map((n) => visitType(n.type)).toList()); | |
| 446 } | |
| 447 | |
| 448 @override | |
| 449 DartType visitInterfaceType(ir.InterfaceType node) { | |
| 450 ClassEntity cls = elementAdapter.getClass(node.classNode); | |
| 451 return new InterfaceType(cls, visitTypes(node.typeArguments)); | |
| 452 } | |
| 453 | |
| 454 @override | |
| 455 DartType visitVoidType(ir.VoidType node) { | |
| 456 return const VoidType(); | |
| 457 } | |
| 458 | |
| 459 @override | |
| 460 DartType visitDynamicType(ir.DynamicType node) { | |
| 461 return const DynamicType(); | |
| 462 } | |
| 463 | |
| 464 @override | |
| 465 DartType visitInvalidType(ir.InvalidType node) { | |
| 466 if (topLevel) { | |
| 467 throw new UnimplementedError( | |
| 468 "Outermost invalid types not currently supported"); | |
| 469 } | |
| 470 // Nested invalid types are treated as `dynamic`. | |
| 471 return const DynamicType(); | |
| 472 } | |
| 473 } | |
| OLD | NEW |