Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 class BailoutException { | 5 class BailoutException { |
| 6 final String reason; | 6 final String reason; |
| 7 | 7 |
| 8 const BailoutException(this.reason); | 8 const BailoutException(this.reason); |
| 9 } | 9 } |
| 10 | 10 |
| 11 class DartBackend extends Backend { | 11 class DartBackend extends Backend { |
| 12 final List<CompilerTask> tasks; | 12 final List<CompilerTask> tasks; |
| 13 final UnparseValidator unparseValidator; | 13 final UnparseValidator unparseValidator; |
| 14 | 14 |
| 15 Map<Element, TreeElements> get resolvedElements() => | 15 Map<Element, TreeElements> get resolvedElements() => |
| 16 compiler.enqueuer.resolution.resolvedElements; | 16 compiler.enqueuer.resolution.resolvedElements; |
| 17 Map<ClassElement, List<Element>> resolvedClasses; | |
|
Anton Muhin
2012/07/10 09:50:12
resolvedClasses doesn't sound correct. That's rat
Anton Muhin
2012/07/10 09:50:12
should it be List<Element> or Set<Element>?
Roman
2012/07/10 10:45:15
renamed to resolvedClassMembers
Roman
2012/07/10 10:45:15
Correct! Changed to set
Anton Muhin
2012/07/10 11:31:40
I'd rather not see word resolved here. It's used
| |
| 17 | 18 |
| 18 DartBackend(Compiler compiler, [bool validateUnparse = false]) | 19 DartBackend(Compiler compiler, [bool validateUnparse = false]) |
| 19 : tasks = <CompilerTask>[], | 20 : tasks = <CompilerTask>[], |
| 20 unparseValidator = new UnparseValidator(compiler, validateUnparse), | 21 unparseValidator = new UnparseValidator(compiler, validateUnparse), |
| 21 super(compiler) { | 22 super(compiler) { |
| 22 tasks.add(unparseValidator); | 23 tasks.add(unparseValidator); |
| 24 resolvedClasses = new HashMap<ClassElement, List<Element>>(); | |
|
Anton Muhin
2012/07/10 09:50:12
no need to make default implementation explicit an
Roman
2012/07/10 10:45:15
Done.
| |
| 23 } | 25 } |
| 24 | 26 |
| 25 void enqueueHelpers(Enqueuer world) { | 27 void enqueueHelpers(Enqueuer world) { |
| 26 // TODO(antonm): Implement this method, if needed. | 28 // TODO(antonm): Implement this method, if needed. |
| 27 } | 29 } |
| 28 | 30 |
| 29 CodeBlock codegen(WorkItem work) { return new CodeBlock(null, null); } | 31 CodeBlock codegen(WorkItem work) { return new CodeBlock(null, null); } |
| 30 | 32 |
| 31 void processNativeClasses(Enqueuer world, | 33 void processNativeClasses(Enqueuer world, |
| 32 Collection<LibraryElement> libraries) { | 34 Collection<LibraryElement> libraries) { |
| 33 } | 35 } |
| 34 | 36 |
| 37 /** | |
| 38 * Adds given class element with its inner element to resolved classes | |
| 39 * collections. | |
| 40 */ | |
| 41 void addResolvedElementForClass(Element element, ClassElement classElement) { | |
| 42 if (element.enclosingElement !== classElement) { | |
|
Anton Muhin
2012/07/10 09:50:12
assert?
Roman
2012/07/10 10:45:15
Done.
| |
| 43 compiler.internalError( | |
| 44 '${element} should have ${classElement} as enclosing'); | |
| 45 } | |
| 46 List<Element> resolvedElementsInClass = resolvedClasses[classElement]; | |
| 47 if (resolvedElementsInClass == null) { | |
|
Anton Muhin
2012/07/10 09:50:12
nit: there is putIfAbsent thing which may encode t
Roman
2012/07/10 10:45:15
Awesome thing, thanks!
| |
| 48 resolvedElementsInClass = new List<Element>(); | |
| 49 resolvedClasses[classElement] = resolvedElementsInClass; | |
| 50 } | |
| 51 resolvedElementsInClass.add(element); | |
| 52 } | |
| 53 | |
| 54 /** | |
| 55 * Resolves enclosing class for given elements and adds to a collection of | |
| 56 * resolved classes, remembering the inner element. | |
| 57 */ | |
| 58 void resolveClass(Element element) { | |
| 59 if (element.isTopLevel()) { | |
|
Anton Muhin
2012/07/10 09:50:12
it rather should be an assert (see below regarding
Roman
2012/07/10 10:45:15
Done.
| |
| 60 compiler.internalError( | |
| 61 'We should not resolve classes for top-level elements'); | |
| 62 } | |
| 63 var enclosingClass = element.enclosingElement; | |
|
Anton Muhin
2012/07/10 09:50:12
it should probably be if (element.isMember())
Roman
2012/07/10 10:45:15
what do you mean by 'it'? This is a check whether
Anton Muhin
2012/07/10 11:31:40
Sorry. If I was to write this code, I would do th
Roman
2012/07/10 11:53:40
Removed processMember(), moved code to assemblePro
| |
| 64 if (!enclosingClass.isClass()) { | |
| 65 bailout('resolve $element with enclosing non-class element'); | |
| 66 } | |
| 67 addResolvedElementForClass(element, enclosingClass); | |
| 68 if (!enclosingClass.isTopLevel()) { | |
|
Anton Muhin
2012/07/10 09:50:12
I'd rather make it assert as classes must be top-l
Roman
2012/07/10 10:45:15
Done.
| |
| 69 bailout('resolve $element with enclosing non-top-level class'); | |
| 70 } | |
| 71 } | |
| 72 | |
| 73 /** | |
| 74 * Outputs given class element with given inner elements to a string buffer. | |
| 75 */ | |
| 76 void outputClass(ClassElement classElement, List<Element> innerElements, | |
| 77 StringBuffer sb) { | |
| 78 // TODO(smok): Very soon properly print out correct class declaration with | |
| 79 // extends, implements, etc. | |
| 80 sb.add('class '); | |
| 81 sb.add(classElement.name.slowToString()); | |
| 82 sb.add('{'); | |
| 83 innerElements.forEach((element) { | |
| 84 // TODO(smok): Filter out default constructors here. | |
| 85 sb.add(element.parseNode(compiler).unparse()); | |
| 86 }); | |
| 87 sb.add('}'); | |
| 88 } | |
| 89 | |
| 35 void assembleProgram() { | 90 void assembleProgram() { |
| 36 resolvedElements.forEach((element, treeElements) { | 91 resolvedElements.forEach((element, treeElements) { |
| 37 unparseValidator.check(element); | 92 unparseValidator.check(element); |
| 38 }); | 93 }); |
| 39 | 94 |
| 40 // TODO(antonm): Eventually bailouts will be proper errors. | 95 // TODO(antonm): Eventually bailouts will be proper errors. |
| 41 void bailout(String reason) { | 96 void bailout(String reason) { |
| 42 throw new BailoutException(reason); | 97 throw new BailoutException(reason); |
| 43 } | 98 } |
| 44 | 99 |
| 45 /** | 100 /** |
| 46 * Tells whether we should output given element. Corelib classes like | 101 * Tells whether we should output given element. Corelib classes like |
| 47 * Object should not be in the resulting code. | 102 * Object should not be in the resulting code. |
| 48 */ | 103 */ |
| 49 bool shouldOutput(Element element) { | 104 bool shouldOutput(Element element) { |
| 50 return element.kind !== ElementKind.VOID | 105 return element.kind !== ElementKind.VOID |
| 51 && element.getLibrary() !== compiler.coreLibrary; | 106 && element.getLibrary() !== compiler.coreLibrary; |
| 52 } | 107 } |
| 53 | 108 |
| 54 try { | 109 try { |
| 55 StringBuffer sb = new StringBuffer(); | 110 StringBuffer sb = new StringBuffer(); |
| 56 resolvedElements.forEach((element, treeElements) { | 111 resolvedElements.forEach((element, treeElements) { |
| 57 if (!shouldOutput(element)) return; | 112 if (!shouldOutput(element)) return; |
| 58 if (!element.isTopLevel()) { | 113 if (!element.isTopLevel()) { |
| 59 bailout('Cannot process non top-level $element'); | 114 resolveClass(element); |
|
Anton Muhin
2012/07/10 09:50:12
I would rather have something like:
if (element.i
Roman
2012/07/10 10:45:15
Done.
| |
| 115 return; | |
| 60 } | 116 } |
| 61 | 117 |
| 62 if (element.isField()) { | 118 if (element.isField()) { |
| 63 // Add modifiers first. | 119 // Add modifiers first. |
| 64 sb.add(element.modifiers.toString()); | 120 sb.add(element.modifiers.toString()); |
| 65 sb.add(' '); | 121 sb.add(' '); |
| 66 // Figure out type. | 122 // Figure out type. |
| 67 if (element is VariableElement) { | 123 if (element is VariableElement) { |
| 68 VariableListElement variables = element.variables; | 124 VariableListElement variables = element.variables; |
| 69 if (variables.type !== null) { | 125 if (variables.type !== null) { |
| 70 sb.add(variables.type); | 126 sb.add(variables.type); |
| 71 sb.add(' '); | 127 sb.add(' '); |
| 72 } | 128 } |
| 73 } | 129 } |
| 74 // TODO(smok): Maybe not rely on node unparsing, | 130 // TODO(smok): Maybe not rely on node unparsing, |
| 75 // but unparse initializer manually. | 131 // but unparse initializer manually. |
| 76 sb.add(element.parseNode(compiler).unparse()); | 132 sb.add(element.parseNode(compiler).unparse()); |
| 77 sb.add(';'); | 133 sb.add(';'); |
| 78 } else { | 134 } else { |
| 79 sb.add(element.parseNode(compiler).unparse()); | 135 sb.add(element.parseNode(compiler).unparse()); |
| 80 } | 136 } |
| 81 }); | 137 }); |
| 138 | |
| 139 // Now output resolved classes with inner elements we met before. | |
| 140 resolvedClasses.forEach((classElement, resolvedElements) { | |
| 141 outputClass(classElement, resolvedElements, sb); | |
|
Anton Muhin
2012/07/10 09:50:12
if you made outputClass a closure, you can have ni
Roman
2012/07/10 10:45:15
I would prefer to leave it this way, if you don't
| |
| 142 }); | |
| 82 compiler.assembledCode = sb.toString(); | 143 compiler.assembledCode = sb.toString(); |
| 83 } catch (BailoutException e) { | 144 } catch (BailoutException e) { |
| 84 compiler.assembledCode = ''' | 145 compiler.assembledCode = ''' |
| 85 main() { | 146 main() { |
| 86 final bailout_reason = "${e.reason}"; | 147 final bailout_reason = "${e.reason}"; |
| 87 } | 148 } |
| 88 '''; | 149 '''; |
| 89 } | 150 } |
| 90 } | 151 } |
| 91 | 152 |
| 92 log(String message) => compiler.log('[DartBackend] $message'); | 153 log(String message) => compiler.log('[DartBackend] $message'); |
| 93 } | 154 } |
| OLD | NEW |