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 file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 library kernel.ast_to_binary; | 4 library kernel.ast_to_binary; |
5 | 5 |
6 import '../ast.dart'; | 6 import '../ast.dart'; |
7 import '../import_table.dart'; | 7 import '../import_table.dart'; |
8 import 'tag.dart'; | 8 import 'tag.dart'; |
9 import 'dart:convert'; | 9 import 'dart:convert'; |
10 import 'dart:typed_data'; | 10 import 'dart:typed_data'; |
11 import 'dart:collection'; | 11 import 'dart:collection'; |
12 | 12 |
13 /// Writes to a binary file. | 13 /// Writes to a binary file. |
14 /// | 14 /// |
15 /// A [BinaryPrinter] can be used to write one file and must then be | 15 /// A [BinaryPrinter] can be used to write one file and must then be |
16 /// discarded. | 16 /// discarded. |
17 class BinaryPrinter extends Visitor { | 17 class BinaryPrinter extends Visitor { |
18 ImportTable _importTable; | 18 ImportTable _importTable; |
19 | 19 |
20 VariableIndexer _variableIndexer; | 20 VariableIndexer _variableIndexer; |
21 LabelIndexer _labelIndexer; | 21 LabelIndexer _labelIndexer; |
22 SwitchCaseIndexer _switchCaseIndexer; | 22 SwitchCaseIndexer _switchCaseIndexer; |
23 final TypeParameterIndexer _typeParameterIndexer = new TypeParameterIndexer(); | 23 final TypeParameterIndexer _typeParameterIndexer = new TypeParameterIndexer(); |
24 final GlobalIndexer _globalIndexer; | 24 final GlobalIndexer _globalIndexer; |
25 final StringIndexer _stringIndexer = new StringIndexer(); | 25 final StringIndexer _stringIndexer = new StringIndexer(); |
26 final StringIndexer _sourceUriIndexer = new StringIndexer(); | 26 final StringIndexer _sourceUriIndexer = new StringIndexer(); |
| 27 Map<DeferredImport, int> _deferredImportIndexer = <DeferredImport, int>{}; |
27 | 28 |
28 final BufferedSink _sink; | 29 final BufferedSink _sink; |
29 | 30 |
30 /// Create a printer that writes to the given [sink]. | 31 /// Create a printer that writes to the given [sink]. |
31 /// | 32 /// |
32 /// The BinaryPrinter will use its own buffer, so the [sink] does not need | 33 /// The BinaryPrinter will use its own buffer, so the [sink] does not need |
33 /// one. | 34 /// one. |
34 /// | 35 /// |
35 /// If multiple binaries are to be written based on the same IR, a shared | 36 /// If multiple binaries are to be written based on the same IR, a shared |
36 /// [globalIndexer] may be passed in to avoid rebuilding the same indices | 37 /// [globalIndexer] may be passed in to avoid rebuilding the same indices |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 } | 169 } |
169 | 170 |
170 void writeLibraryReference(Library node) { | 171 void writeLibraryReference(Library node) { |
171 int index = _importTable.getImportIndex(node); | 172 int index = _importTable.getImportIndex(node); |
172 if (index == -1) { | 173 if (index == -1) { |
173 throw 'Missing import for library: ${node.importUri}'; | 174 throw 'Missing import for library: ${node.importUri}'; |
174 } | 175 } |
175 writeUInt30(index); | 176 writeUInt30(index); |
176 } | 177 } |
177 | 178 |
| 179 void writeDeferredImportReference(DeferredImport node) { |
| 180 int index = _deferredImportIndexer[node]; |
| 181 if (index == null) { |
| 182 throw 'Reference to deferred import $node out of scope'; |
| 183 } |
| 184 writeUInt30(index); |
| 185 } |
| 186 |
178 void writeClassIndex(Class node) { | 187 void writeClassIndex(Class node) { |
179 writeUInt30(_globalIndexer[node]); | 188 writeUInt30(_globalIndexer[node]); |
180 } | 189 } |
181 | 190 |
182 void writeClassReference(Class node, {bool allowNull: false}) { | 191 void writeClassReference(Class node, {bool allowNull: false}) { |
183 if (node == null) { | 192 if (node == null) { |
184 if (allowNull) { | 193 if (allowNull) { |
185 writeByte(Tag.NullReference); | 194 writeByte(Tag.NullReference); |
186 } else { | 195 } else { |
187 throw 'Expected a class reference to be valid but was `null`.'; | 196 throw 'Expected a class reference to be valid but was `null`.'; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 | 271 |
263 bool insideExternalLibrary = false; | 272 bool insideExternalLibrary = false; |
264 | 273 |
265 visitLibrary(Library node) { | 274 visitLibrary(Library node) { |
266 insideExternalLibrary = node.isExternal; | 275 insideExternalLibrary = node.isExternal; |
267 writeByte(insideExternalLibrary ? 1 : 0); | 276 writeByte(insideExternalLibrary ? 1 : 0); |
268 writeStringReference(node.name ?? ''); | 277 writeStringReference(node.name ?? ''); |
269 writeStringReference('${node.importUri}'); | 278 writeStringReference('${node.importUri}'); |
270 // TODO(jensj): We save (almost) the same URI twice. | 279 // TODO(jensj): We save (almost) the same URI twice. |
271 writeUriReference(node.fileUri ?? ''); | 280 writeUriReference(node.fileUri ?? ''); |
| 281 writeDeferredImports(node); |
272 writeNodeList(node.classes); | 282 writeNodeList(node.classes); |
273 writeNodeList(node.fields); | 283 writeNodeList(node.fields); |
274 writeNodeList(node.procedures); | 284 writeNodeList(node.procedures); |
275 } | 285 } |
276 | 286 |
| 287 void writeDeferredImports(Library library) { |
| 288 _deferredImportIndexer = library.deferredImports.isEmpty |
| 289 ? const <DeferredImport, int>{} |
| 290 : <DeferredImport, int>{}; |
| 291 writeUInt30(library.deferredImports.length); |
| 292 for (int i = 0; i < library.deferredImports.length; ++i) { |
| 293 var importNode = library.deferredImports[i]; |
| 294 _deferredImportIndexer[importNode] = i; |
| 295 writeDeferredImport(importNode); |
| 296 } |
| 297 } |
| 298 |
| 299 void writeDeferredImport(DeferredImport node) { |
| 300 writeLibraryReference(node.importedLibrary); |
| 301 writeStringReference(node.name); |
| 302 } |
| 303 |
277 void writeAnnotation(Expression annotation) { | 304 void writeAnnotation(Expression annotation) { |
278 _variableIndexer ??= new VariableIndexer(); | 305 _variableIndexer ??= new VariableIndexer(); |
279 writeNode(annotation); | 306 writeNode(annotation); |
280 } | 307 } |
281 | 308 |
282 void writeAnnotationList(List<Expression> annotations) { | 309 void writeAnnotationList(List<Expression> annotations) { |
283 writeList(annotations, writeAnnotation); | 310 writeList(annotations, writeAnnotation); |
284 } | 311 } |
285 | 312 |
286 visitClass(Class node) { | 313 visitClass(Class node) { |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 writeNode(node.function); | 732 writeNode(node.function); |
706 } | 733 } |
707 | 734 |
708 visitLet(Let node) { | 735 visitLet(Let node) { |
709 writeByte(Tag.Let); | 736 writeByte(Tag.Let); |
710 writeVariableDeclaration(node.variable); | 737 writeVariableDeclaration(node.variable); |
711 writeNode(node.body); | 738 writeNode(node.body); |
712 --_variableIndexer.stackHeight; | 739 --_variableIndexer.stackHeight; |
713 } | 740 } |
714 | 741 |
| 742 visitLoadLibrary(LoadLibrary node) { |
| 743 writeByte(Tag.LoadLibrary); |
| 744 writeDeferredImportReference(node.import); |
| 745 } |
| 746 |
| 747 visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) { |
| 748 writeByte(Tag.CheckLibraryIsLoaded); |
| 749 writeDeferredImportReference(node.import); |
| 750 } |
| 751 |
715 writeStatementOrEmpty(Statement node) { | 752 writeStatementOrEmpty(Statement node) { |
716 if (node == null) { | 753 if (node == null) { |
717 writeByte(Tag.EmptyStatement); | 754 writeByte(Tag.EmptyStatement); |
718 } else { | 755 } else { |
719 writeNode(node); | 756 writeNode(node); |
720 } | 757 } |
721 } | 758 } |
722 | 759 |
723 visitInvalidStatement(InvalidStatement node) { | 760 visitInvalidStatement(InvalidStatement node) { |
724 writeByte(Tag.InvalidStatement); | 761 writeByte(Tag.InvalidStatement); |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1091 visitName(Name node) { | 1128 visitName(Name node) { |
1092 put(node.name); | 1129 put(node.name); |
1093 } | 1130 } |
1094 | 1131 |
1095 visitLibrary(Library node) { | 1132 visitLibrary(Library node) { |
1096 putOptional(node.name); | 1133 putOptional(node.name); |
1097 put('${node.importUri}'); | 1134 put('${node.importUri}'); |
1098 node.visitChildren(this); | 1135 node.visitChildren(this); |
1099 } | 1136 } |
1100 | 1137 |
| 1138 visitDeferredImport(DeferredImport node) { |
| 1139 put(node.name); |
| 1140 } |
| 1141 |
1101 visitClass(Class node) { | 1142 visitClass(Class node) { |
1102 putOptional(node.name); | 1143 putOptional(node.name); |
1103 node.visitChildren(this); | 1144 node.visitChildren(this); |
1104 } | 1145 } |
1105 | 1146 |
1106 visitNamedExpression(NamedExpression node) { | 1147 visitNamedExpression(NamedExpression node) { |
1107 put(node.name); | 1148 put(node.name); |
1108 node.visitChildren(this); | 1149 node.visitChildren(this); |
1109 } | 1150 } |
1110 | 1151 |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1241 void flush() { | 1282 void flush() { |
1242 _sink.add(_buffer.sublist(0, length)); | 1283 _sink.add(_buffer.sublist(0, length)); |
1243 _buffer = new Uint8List(SIZE); | 1284 _buffer = new Uint8List(SIZE); |
1244 length = 0; | 1285 length = 0; |
1245 } | 1286 } |
1246 | 1287 |
1247 void flushAndDestroy() { | 1288 void flushAndDestroy() { |
1248 _sink.add(_buffer.sublist(0, length)); | 1289 _sink.add(_buffer.sublist(0, length)); |
1249 } | 1290 } |
1250 } | 1291 } |
OLD | NEW |