| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
| 4 | 4 |
| 5 library rasta.kernel; | 5 library rasta.kernel; |
| 6 | 6 |
| 7 import 'dart:async' show | 7 import 'dart:async' show |
| 8 Future; | 8 Future; |
| 9 | 9 |
| 10 import 'dart:collection' show | 10 import 'dart:collection' show |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 import 'custom_compiler.dart' show | 46 import 'custom_compiler.dart' show |
| 47 CustomCompiler; | 47 CustomCompiler; |
| 48 | 48 |
| 49 import 'kernel_visitor.dart' show | 49 import 'kernel_visitor.dart' show |
| 50 IrFunction, | 50 IrFunction, |
| 51 KernelVisitor; | 51 KernelVisitor; |
| 52 | 52 |
| 53 import 'package:compiler/src/constants/expressions.dart' show | 53 import 'package:compiler/src/constants/expressions.dart' show |
| 54 TypeConstantExpression; | 54 TypeConstantExpression; |
| 55 | 55 |
| 56 typedef void WorkAction(bool isTargeted); | 56 typedef void WorkAction(); |
| 57 | 57 |
| 58 class WorkItem { | 58 class WorkItem { |
| 59 final Element element; | 59 final Element element; |
| 60 final WorkAction action; | 60 final WorkAction action; |
| 61 | 61 |
| 62 WorkItem(this.element, this.action); | 62 WorkItem(this.element, this.action); |
| 63 } | 63 } |
| 64 | 64 |
| 65 class Kernel { | 65 class Kernel { |
| 66 final CustomCompiler compiler; | 66 final CustomCompiler compiler; |
| 67 | 67 |
| 68 final Map<LibraryElement, ir.Library> libraries = | 68 final Map<LibraryElement, ir.Library> libraries = |
| 69 <LibraryElement, ir.Library>{}; | 69 <LibraryElement, ir.Library>{}; |
| 70 | 70 |
| 71 final Map<ClassElement, ir.Class> classes = <ClassElement, ir.Class>{}; | 71 final Map<ClassElement, ir.Class> classes = <ClassElement, ir.Class>{}; |
| 72 | 72 |
| 73 final Map<FunctionElement, ir.Member> functions = | 73 final Map<FunctionElement, ir.Member> functions = |
| 74 <FunctionElement, ir.Member>{}; | 74 <FunctionElement, ir.Member>{}; |
| 75 | 75 |
| 76 final Map<FieldElement, ir.Field> fields = <FieldElement, ir.Field>{}; | 76 final Map<FieldElement, ir.Field> fields = <FieldElement, ir.Field>{}; |
| 77 | 77 |
| 78 final Map<TypeVariableElement, ir.TypeParameter> typeParameters = | 78 final Map<TypeVariableElement, ir.TypeParameter> typeParameters = |
| 79 <TypeVariableElement, ir.TypeParameter>{}; | 79 <TypeVariableElement, ir.TypeParameter>{}; |
| 80 | 80 |
| 81 final Set<ir.TreeNode> checkedNodes = new Set<ir.TreeNode>(); |
| 82 |
| 81 /// FIFO queue of work that needs to be completed before the returned AST | 83 /// FIFO queue of work that needs to be completed before the returned AST |
| 82 /// nodes are correct. | 84 /// nodes are correct. |
| 83 final Queue<WorkItem> workQueue = new Queue<WorkItem>(); | 85 final Queue<WorkItem> workQueue = new Queue<WorkItem>(); |
| 84 | 86 |
| 85 LibraryElement targetLibrary; | |
| 86 | |
| 87 Kernel(this.compiler); | 87 Kernel(this.compiler); |
| 88 | 88 |
| 89 bool hasMainMethod(Uri uri) { | 89 bool hasMainMethod(Uri uri) { |
| 90 LibraryElement library = compiler.libraryLoader.lookupLibrary(uri); | 90 LibraryElement library = compiler.libraryLoader.lookupLibrary(uri); |
| 91 return library.localLookup("main") != null; | 91 return library.localLookup("main") != null; |
| 92 } | 92 } |
| 93 | 93 |
| 94 bool isTargeted(Element element) { | |
| 95 if (targetLibrary == null) return true; | |
| 96 return element.library.declaration == targetLibrary; | |
| 97 } | |
| 98 | |
| 99 void addWork(Element element, WorkAction action) { | 94 void addWork(Element element, WorkAction action) { |
| 100 workQueue.addLast(new WorkItem(element, action)); | 95 workQueue.addLast(new WorkItem(element, action)); |
| 101 } | 96 } |
| 102 | 97 |
| 103 void checkMember(Element key, ir.TreeNode value) { | 98 void checkMember(Element key, ir.TreeNode value) { |
| 104 if (!isTargeted(key)) return; | 99 if (!checkedNodes.add(value)) return; |
| 105 if (value.parent == null) { | 100 if (value.parent == null) { |
| 106 internalError(key, "Missing parent on IR node."); | 101 internalError(key, "Missing parent on IR node."); |
| 107 } | 102 } |
| 108 try { | 103 try { |
| 109 CheckParentPointers.check(value); | 104 CheckParentPointers.check(value); |
| 110 } catch (e, s) { | 105 } catch (e, s) { |
| 111 internalError(key, "$e\n$s"); | 106 internalError(key, "$e\n$s"); |
| 112 } | 107 } |
| 113 } | 108 } |
| 114 | 109 |
| 115 void processWorkQueue({Uri targetLibrary}) { | 110 void checkLibrary(Element key, ir.Library library) { |
| 116 if (targetLibrary != null) { | 111 if (!checkedNodes.add(library)) return; |
| 117 this.targetLibrary = compiler.libraryLoader.lookupLibrary(targetLibrary); | 112 CheckParentPointers.check(library); |
| 118 assert(this.targetLibrary != null); | 113 } |
| 119 } | 114 |
| 115 void processWorkQueue() { |
| 120 while (workQueue.isNotEmpty) { | 116 while (workQueue.isNotEmpty) { |
| 121 WorkItem work = workQueue.removeFirst(); | 117 WorkItem work = workQueue.removeFirst(); |
| 122 work.action(isTargeted(work.element)); | 118 work.action(); |
| 123 } | 119 } |
| 124 assert(() { | 120 assert(() { |
| 125 libraries.values.forEach(CheckParentPointers.check); | 121 libraries.forEach(checkLibrary); |
| 126 classes.forEach(checkMember); | 122 classes.forEach(checkMember); |
| 127 functions.forEach(checkMember); | 123 functions.forEach(checkMember); |
| 128 fields.forEach(checkMember); | 124 fields.forEach(checkMember); |
| 129 return true; | 125 return true; |
| 130 }); | 126 }); |
| 131 } | 127 } |
| 132 | 128 |
| 133 ir.Name irName(String name, Element element) { | 129 ir.Name irName(String name, Element element) { |
| 134 return new ir.Name(name, libraryToIr(element.library)); | 130 return new ir.Name(name, libraryToIr(element.library)); |
| 135 } | 131 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 146 return libraryToIr(await compiler.libraryLoader.loadLibrary(uri)); | 142 return libraryToIr(await compiler.libraryLoader.loadLibrary(uri)); |
| 147 } | 143 } |
| 148 | 144 |
| 149 ir.Library libraryToIr(LibraryElement library) { | 145 ir.Library libraryToIr(LibraryElement library) { |
| 150 library = library.declaration; | 146 library = library.declaration; |
| 151 return libraries.putIfAbsent(library, () { | 147 return libraries.putIfAbsent(library, () { |
| 152 String name = library.hasLibraryName ? library.libraryName : null; | 148 String name = library.hasLibraryName ? library.libraryName : null; |
| 153 ir.Library libraryNode = new ir.Library( | 149 ir.Library libraryNode = new ir.Library( |
| 154 library.canonicalUri, name: name, classes: null, procedures: null, | 150 library.canonicalUri, name: name, classes: null, procedures: null, |
| 155 fields: null); | 151 fields: null); |
| 156 addWork(library, (bool isTargeted) { | 152 addWork(library, () { |
| 157 Queue<ir.Class> classes = new Queue<ir.Class>(); | 153 Queue<ir.Class> classes = new Queue<ir.Class>(); |
| 158 Queue<ir.Member> members = new Queue<ir.Member>(); | 154 Queue<ir.Member> members = new Queue<ir.Member>(); |
| 159 library.implementation.forEachLocalMember((Element e) { | 155 library.implementation.forEachLocalMember((Element e) { |
| 160 if (e.isClass) { | 156 if (e.isClass) { |
| 161 classes.addFirst(classToIr(e)); | 157 classes.addFirst(classToIr(e)); |
| 162 } else if (e.isFunction || e.isAccessor) { | 158 } else if (e.isFunction || e.isAccessor) { |
| 163 members.addFirst(functionToIr(e)); | 159 members.addFirst(functionToIr(e)); |
| 164 } else if (e.isField) { | 160 } else if (e.isField) { |
| 165 members.addFirst(fieldToIr(e)); | 161 members.addFirst(fieldToIr(e)); |
| 166 } else if (e.isTypedef) { | 162 } else if (e.isTypedef) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 180 | 176 |
| 181 ir.Class classToIr(ClassElement cls) { | 177 ir.Class classToIr(ClassElement cls) { |
| 182 if (cls.isMixinApplication) return mixinApplicationToIr(cls); | 178 if (cls.isMixinApplication) return mixinApplicationToIr(cls); |
| 183 cls = cls.declaration; | 179 cls = cls.declaration; |
| 184 return classes.putIfAbsent(cls, () { | 180 return classes.putIfAbsent(cls, () { |
| 185 cls.ensureResolved(compiler.resolution); | 181 cls.ensureResolved(compiler.resolution); |
| 186 ir.NormalClass classNode = new ir.NormalClass( | 182 ir.NormalClass classNode = new ir.NormalClass( |
| 187 null, name: cls.name, isAbstract: cls.isAbstract, | 183 null, name: cls.name, isAbstract: cls.isAbstract, |
| 188 typeParameters: null, implementedClasses: null, constructors: null, | 184 typeParameters: null, implementedClasses: null, constructors: null, |
| 189 procedures: null, fields: null); | 185 procedures: null, fields: null); |
| 190 addWork(cls, (bool isTargeted) { | 186 addWork(cls, () { |
| 191 if (cls.supertype != null) { | 187 if (cls.supertype != null) { |
| 192 classNode.superType = interfaceTypeToIr(cls.supertype); | 188 classNode.superType = interfaceTypeToIr(cls.supertype); |
| 193 } | 189 } |
| 194 classNode.parent = libraryToIr(cls.library); | 190 classNode.parent = libraryToIr(cls.library); |
| 195 if (cls.isUnnamedMixinApplication) { | 191 if (cls.isUnnamedMixinApplication) { |
| 196 classNode.enclosingLibrary.addClass(classNode); | 192 classNode.enclosingLibrary.addClass(classNode); |
| 197 } | 193 } |
| 198 cls.implementation.forEachMember( | 194 cls.implementation.forEachMember( |
| 199 (ClassElement enclosingClass, Element member) { | 195 (ClassElement enclosingClass, Element member) { |
| 200 if (member.enclosingClass.declaration != cls) { | 196 if (member.enclosingClass.declaration != cls) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 223 cls.ensureResolved(compiler.resolution); | 219 cls.ensureResolved(compiler.resolution); |
| 224 InterfaceType supertype = null; // Computed and set below. | 220 InterfaceType supertype = null; // Computed and set below. |
| 225 InterfaceType mixedInType = null; // Computed and set below. | 221 InterfaceType mixedInType = null; // Computed and set below. |
| 226 String name = cls.isUnnamedMixinApplication ? null : cls.name; | 222 String name = cls.isUnnamedMixinApplication ? null : cls.name; |
| 227 ir.MixinClass classNode = new ir.MixinClass( | 223 ir.MixinClass classNode = new ir.MixinClass( |
| 228 supertype, mixedInType, name: name, | 224 supertype, mixedInType, name: name, |
| 229 isAbstract: cls.isAbstract, | 225 isAbstract: cls.isAbstract, |
| 230 typeParameters: null, | 226 typeParameters: null, |
| 231 implementedClasses: null, | 227 implementedClasses: null, |
| 232 constructors: null); | 228 constructors: null); |
| 233 addWork(cls, (bool isTargeted) { | 229 addWork(cls, () { |
| 234 classNode.parent = libraryToIr(cls.library); | 230 classNode.parent = libraryToIr(cls.library); |
| 235 if (cls.isUnnamedMixinApplication) { | 231 if (cls.isUnnamedMixinApplication) { |
| 236 classNode.enclosingLibrary.addClass(classNode); | 232 classNode.enclosingLibrary.addClass(classNode); |
| 237 } | 233 } |
| 238 if (cls.hasIncompleteHierarchy) { | 234 if (cls.hasIncompleteHierarchy) { |
| 239 ir.InterfaceType objectType = | 235 ir.InterfaceType objectType = |
| 240 interfaceTypeToIr(compiler.coreTypes.objectType); | 236 interfaceTypeToIr(compiler.coreTypes.objectType); |
| 241 classNode.superType = objectType; | 237 classNode.superType = objectType; |
| 242 classNode.mixedInType = objectType; | 238 classNode.mixedInType = objectType; |
| 243 } else { | 239 } else { |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 null, name: name, isConst: function.isConst, | 381 null, name: name, isConst: function.isConst, |
| 386 isExternal: function.isExternal, initializers: null); | 382 isExternal: function.isExternal, initializers: null); |
| 387 } else { | 383 } else { |
| 388 member = procedure = new ir.Procedure( | 384 member = procedure = new ir.Procedure( |
| 389 name, null, null, isAbstract: function.isAbstract, | 385 name, null, null, isAbstract: function.isAbstract, |
| 390 isStatic: function.isStatic || function.isTopLevel | 386 isStatic: function.isStatic || function.isTopLevel |
| 391 || function.isFactoryConstructor, | 387 || function.isFactoryConstructor, |
| 392 isExternal: function.isExternal, | 388 isExternal: function.isExternal, |
| 393 isConst: false); // TODO(ahe): When is this true? | 389 isConst: false); // TODO(ahe): When is this true? |
| 394 } | 390 } |
| 395 addWork(function, (bool isTargeted) { | 391 addWork(function, () { |
| 396 setParent(member, function); | 392 setParent(member, function); |
| 397 if (!isTargeted) return; | |
| 398 KernelVisitor visitor = | 393 KernelVisitor visitor = |
| 399 new KernelVisitor(function, function.treeElements, this); | 394 new KernelVisitor(function, function.treeElements, this); |
| 400 IrFunction irFunction = visitor.buildFunction(); | 395 IrFunction irFunction = visitor.buildFunction(); |
| 401 // TODO(ahe): Add addFunction/set function to [ir.Procedure]. | 396 // TODO(ahe): Add addFunction/set function to [ir.Procedure]. |
| 402 irFunction.node.parent = member; | 397 irFunction.node.parent = member; |
| 403 if (irFunction.isConstructor) { | 398 if (irFunction.isConstructor) { |
| 404 assert(irFunction.kind == null); | 399 assert(irFunction.kind == null); |
| 405 constructor.function = irFunction.node; | 400 constructor.function = irFunction.node; |
| 406 constructor.initializers = irFunction.initializers; | 401 constructor.initializers = irFunction.initializers; |
| 407 // TODO(ahe): Add setInitializers to [ir.Constructor]. | 402 // TODO(ahe): Add setInitializers to [ir.Constructor]. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 427 internalError(field, "Synthetic error field: $field."); | 422 internalError(field, "Synthetic error field: $field."); |
| 428 } | 423 } |
| 429 field = field.declaration; | 424 field = field.declaration; |
| 430 return fields.putIfAbsent(field, () { | 425 return fields.putIfAbsent(field, () { |
| 431 compiler.analyzeElement(field); | 426 compiler.analyzeElement(field); |
| 432 field = field.implementation; | 427 field = field.implementation; |
| 433 ir.Field fieldNode = new ir.Field( | 428 ir.Field fieldNode = new ir.Field( |
| 434 nameToIrName(field.memberName), type: typeToIr(field.type), | 429 nameToIrName(field.memberName), type: typeToIr(field.type), |
| 435 initializer: null, isFinal: field.isFinal, | 430 initializer: null, isFinal: field.isFinal, |
| 436 isStatic: field.isStatic || field.isTopLevel, isConst: field.isConst); | 431 isStatic: field.isStatic || field.isTopLevel, isConst: field.isConst); |
| 437 addWork(field, (bool isTargeted) { | 432 addWork(field, () { |
| 438 setParent(fieldNode, field); | 433 setParent(fieldNode, field); |
| 439 if (!isTargeted) return; | |
| 440 if (!field.isInstanceMember && field.initializer != null) { | 434 if (!field.isInstanceMember && field.initializer != null) { |
| 441 KernelVisitor visitor = | 435 KernelVisitor visitor = |
| 442 new KernelVisitor(field, field.treeElements, this); | 436 new KernelVisitor(field, field.treeElements, this); |
| 443 fieldNode.initializer = visitor.buildInitializer() | 437 fieldNode.initializer = visitor.buildInitializer() |
| 444 ..parent = fieldNode; | 438 ..parent = fieldNode; |
| 445 } | 439 } |
| 446 }); | 440 }); |
| 447 return fieldNode; | 441 return fieldNode; |
| 448 }); | 442 }); |
| 449 } | 443 } |
| 450 | 444 |
| 451 ir.TypeParameter typeVariableToIr(TypeVariableElement variable) { | 445 ir.TypeParameter typeVariableToIr(TypeVariableElement variable) { |
| 452 variable = variable.declaration; | 446 variable = variable.declaration; |
| 453 return typeParameters.putIfAbsent(variable, () { | 447 return typeParameters.putIfAbsent(variable, () { |
| 454 ir.TypeParameter parameter = new ir.TypeParameter(variable.name, null); | 448 ir.TypeParameter parameter = new ir.TypeParameter(variable.name, null); |
| 455 addWork(variable, (bool isTargeted) { | 449 addWork(variable, () { |
| 456 // TODO(ahe): This assignment will probably not be correct when dart2js | 450 // TODO(ahe): This assignment will probably not be correct when dart2js |
| 457 // supports generic methods. | 451 // supports generic methods. |
| 458 ClassElement cls = variable.typeDeclaration; | 452 ClassElement cls = variable.typeDeclaration; |
| 459 cls.ensureResolved(compiler.resolution); | 453 cls.ensureResolved(compiler.resolution); |
| 460 parameter.parent = classToIr(cls); | 454 parameter.parent = classToIr(cls); |
| 461 parameter.bound = typeToIr(variable.bound); | 455 parameter.bound = typeToIr(variable.bound); |
| 462 }); | 456 }); |
| 463 return parameter; | 457 return parameter; |
| 464 }); | 458 }); |
| 465 } | 459 } |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 553 /// method body that is [ir.InvalidStatement]. | 547 /// method body that is [ir.InvalidStatement]. |
| 554 bool isSyntheticError(Element element) { | 548 bool isSyntheticError(Element element) { |
| 555 if (element.isAmbiguous) return true; | 549 if (element.isAmbiguous) return true; |
| 556 if (element.isError) return true; | 550 if (element.isError) return true; |
| 557 if (element.isField && element is ErroneousFieldElementX) { | 551 if (element.isField && element is ErroneousFieldElementX) { |
| 558 return true; | 552 return true; |
| 559 } | 553 } |
| 560 return false; | 554 return false; |
| 561 } | 555 } |
| 562 } | 556 } |
| OLD | NEW |