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_from_binary; | 4 library kernel.ast_from_binary; |
5 | 5 |
6 import 'dart:convert'; | |
7 | |
6 import '../ast.dart'; | 8 import '../ast.dart'; |
9 import '../transformations/flags.dart'; | |
7 import 'tag.dart'; | 10 import 'tag.dart'; |
8 import 'loader.dart'; | |
9 import 'dart:convert'; | |
10 import 'package:kernel/transformations/flags.dart'; | |
11 | 11 |
12 class ParseError { | 12 class ParseError { |
13 String filename; | 13 String filename; |
14 int byteIndex; | 14 int byteIndex; |
15 String message; | 15 String message; |
16 String path; | 16 String path; |
17 | 17 |
18 ParseError(this.message, {this.filename, this.byteIndex, this.path}); | 18 ParseError(this.message, {this.filename, this.byteIndex, this.path}); |
19 | 19 |
20 String toString() => '$filename:$byteIndex: $message at $path'; | 20 String toString() => '$filename:$byteIndex: $message at $path'; |
21 } | 21 } |
22 | 22 |
23 class BinaryBuilder { | 23 class BinaryBuilder { |
24 final BinaryReferenceLoader loader; | |
25 final List<Library> importTable = <Library>[]; | |
26 final List<VariableDeclaration> variableStack = <VariableDeclaration>[]; | 24 final List<VariableDeclaration> variableStack = <VariableDeclaration>[]; |
27 final List<LabeledStatement> labelStack = <LabeledStatement>[]; | 25 final List<LabeledStatement> labelStack = <LabeledStatement>[]; |
28 int labelStackBase = 0; | 26 int labelStackBase = 0; |
29 final List<SwitchCase> switchCaseStack = <SwitchCase>[]; | 27 final List<SwitchCase> switchCaseStack = <SwitchCase>[]; |
30 final List<TypeParameter> typeParameterStack = <TypeParameter>[]; | 28 final List<TypeParameter> typeParameterStack = <TypeParameter>[]; |
31 final String filename; | 29 final String filename; |
32 final List<int> _bytes; | 30 final List<int> _bytes; |
33 int _byteIndex = 0; | 31 int _byteIndex = 0; |
34 Library _currentLibrary; | |
35 List<String> _stringTable; | 32 List<String> _stringTable; |
36 List<String> _sourceUriTable; | 33 List<String> _sourceUriTable; |
34 List<CanonicalName> _linkTable; | |
37 int _transformerFlags = 0; | 35 int _transformerFlags = 0; |
36 Library _currentLibrary; | |
38 | 37 |
39 // If something goes wrong, this list should indicate what library, | 38 // If something goes wrong, this list should indicate what library, |
40 // class, and member was being built. | 39 // class, and member was being built. |
41 List<String> debugPath = <String>[]; | 40 List<String> debugPath = <String>[]; |
42 | 41 |
43 BinaryBuilder(this.loader, this._bytes, [this.filename]); | 42 bool _isReadingLibraryImplementation = false; |
43 | |
44 BinaryBuilder(this._bytes, [this.filename]); | |
44 | 45 |
45 fail(String message) { | 46 fail(String message) { |
46 throw new ParseError(message, | 47 throw new ParseError(message, |
47 byteIndex: _byteIndex, filename: filename, path: debugPath.join('::')); | 48 byteIndex: _byteIndex, filename: filename, path: debugPath.join('::')); |
48 } | 49 } |
49 | 50 |
50 int readByte() => _bytes[_byteIndex++]; | 51 int readByte() => _bytes[_byteIndex++]; |
51 | 52 |
52 int readUInt() { | 53 int readUInt() { |
53 var byte = readByte(); | 54 var byte = readByte(); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
119 return _stringTable[readUInt()]; | 120 return _stringTable[readUInt()]; |
120 } | 121 } |
121 | 122 |
122 String readStringOrNullIfEmpty() { | 123 String readStringOrNullIfEmpty() { |
123 var string = readStringReference(); | 124 var string = readStringReference(); |
124 return string.isEmpty ? null : string; | 125 return string.isEmpty ? null : string; |
125 } | 126 } |
126 | 127 |
127 InferredValue readOptionalInferredValue() { | 128 InferredValue readOptionalInferredValue() { |
128 if (readAndCheckOptionTag()) { | 129 if (readAndCheckOptionTag()) { |
129 Class baseClass = readClassReference(allowNull: true); | 130 LinkedNodeBox baseClass = readClassReference(allowNull: true); |
130 BaseClassKind baseClassKind = BaseClassKind.values[readByte()]; | 131 BaseClassKind baseClassKind = BaseClassKind.values[readByte()]; |
131 int valueBits = readByte(); | 132 int valueBits = readByte(); |
132 return new InferredValue(baseClass, baseClassKind, valueBits); | 133 return new InferredValue.byBox(baseClass, baseClassKind, valueBits); |
133 } | 134 } |
134 return null; | 135 return null; |
135 } | 136 } |
136 | 137 |
137 bool readAndCheckOptionTag() { | 138 bool readAndCheckOptionTag() { |
138 int tag = readByte(); | 139 int tag = readByte(); |
139 if (tag == Tag.Nothing) { | 140 if (tag == Tag.Nothing) { |
140 return false; | 141 return false; |
141 } else if (tag == Tag.Something) { | 142 } else if (tag == Tag.Something) { |
142 return true; | 143 return true; |
(...skipping 20 matching lines...) Expand all Loading... | |
163 } | 164 } |
164 } | 165 } |
165 | 166 |
166 void _fillNonTreeNodeList(List<Node> list, Node buildObject()) { | 167 void _fillNonTreeNodeList(List<Node> list, Node buildObject()) { |
167 list.length = readUInt(); | 168 list.length = readUInt(); |
168 for (int i = 0; i < list.length; ++i) { | 169 for (int i = 0; i < list.length; ++i) { |
169 list[i] = buildObject(); | 170 list[i] = buildObject(); |
170 } | 171 } |
171 } | 172 } |
172 | 173 |
173 Program readProgramFile() { | 174 /// Reads a list of linked nodes, reusing any existing objects already in the |
175 /// linking tree. The nodes are merged into [list], and if reading the library | |
176 /// implementation, the order is corrected. | |
177 /// | |
178 /// [readObject] should read the object definition and its canonical name. | |
179 /// If an existing object is bound to the canonical name, the existing object | |
180 /// must be reused and returned. | |
181 void _mergeLinkedNodeList( | |
182 List<LinkedNode> list, LinkedNode readObject(), TreeNode parent) { | |
183 if (_isReadingLibraryImplementation) { | |
184 // When reading the library implementation, overwrite the whole list | |
185 // with the new one. | |
186 _fillTreeNodeList(list, readObject, parent); | |
187 } else { | |
188 // When reading an external library, the results should either be: | |
189 // - merged with the existing external library definition (if any) | |
190 // - ignored if the library implementation is already in memory | |
191 int numberOfNodes = readUInt(); | |
192 for (int i = 0; i < numberOfNodes; ++i) { | |
193 var value = readObject(); | |
194 // We use the parent pointer of a node to determine if it already is in | |
195 // the AST and hence should not be added again. | |
196 if (value.parent == null) { | |
197 list.add(value..parent = parent); | |
198 } | |
199 } | |
200 } | |
201 } | |
202 | |
203 void readLinkTable(CanonicalName linkRoot) { | |
204 int length = readUInt(); | |
205 _linkTable = new List<CanonicalName>(length); | |
206 for (int i = 0; i < length; ++i) { | |
207 int biasedParentIndex = readUInt(); | |
208 String name = readStringReference(); | |
209 var parent = | |
210 biasedParentIndex == 0 ? linkRoot : _linkTable[biasedParentIndex - 1]; | |
211 _linkTable[i] = parent.getChild(name); | |
212 } | |
213 } | |
214 | |
215 /// Deserializes a kernel program and stores it in [program]. | |
216 /// | |
217 /// When linking with a non-empty program, canonical names must have been | |
218 /// computed ahead of time. | |
219 /// | |
220 /// The input bytes may contain multiple files concatenated. | |
221 void readProgram(Program program) { | |
222 while (_byteIndex < _bytes.length) { | |
223 _readProgram(program); | |
224 } | |
225 } | |
226 | |
227 /// Reads a single program file from the input and loads it into [program], | |
228 /// overwriting and reusing any existing data in the program. | |
229 /// | |
230 /// When linking with a non-empty program, canonical names must have been | |
231 /// computed ahead of time. | |
232 /// | |
233 /// This should *only* be used when there is a reason to not allow | |
234 /// concatenated files. | |
235 void readSingleFileProgram(Program program) { | |
236 _readProgram(program); | |
237 if (_byteIndex < _bytes.length) { | |
238 if (_byteIndex + 3 < _bytes.length) { | |
239 int magic = readMagicWord(); | |
240 if (magic == Tag.ProgramFile) { | |
241 throw 'Concatenated program file given when a single program ' | |
242 'was expected.'; | |
243 } | |
244 } | |
245 throw 'Unrecognized bytes following program data'; | |
246 } | |
247 } | |
248 | |
249 void _readProgram(Program program) { | |
Kevin Millikin (Google)
2017/02/22 09:09:30
_readOneProgram?
asgerf
2017/02/22 10:06:54
Done.
| |
174 int magic = readMagicWord(); | 250 int magic = readMagicWord(); |
175 if (magic != Tag.ProgramFile) { | 251 if (magic != Tag.ProgramFile) { |
176 throw fail('This is not a binary dart file. ' | 252 throw fail('This is not a binary dart file. ' |
177 'Magic number was: ${magic.toRadixString(16)}'); | 253 'Magic number was: ${magic.toRadixString(16)}'); |
178 } | 254 } |
179 readStringTable(); | 255 readStringTable(); |
180 Map<String, Source> uriToSource = readUriToSource(); | 256 Map<String, Source> uriToSource = readUriToSource(); |
181 importTable.length = readUInt(); | 257 program.uriToSource.addAll(uriToSource); |
182 for (int i = 0; i < importTable.length; ++i) { | 258 readLinkTable(program.root); |
183 importTable[i] = new Library(null); | 259 int numberOfLibraries = readUInt(); |
184 } | 260 List<Library> libraries = new List<Library>(numberOfLibraries); |
185 for (int i = 0; i < importTable.length; ++i) { | 261 for (int i = 0; i < numberOfLibraries; ++i) { |
186 _currentLibrary = importTable[i]; | 262 libraries[i] = readLibrary(program); |
187 readLibrary(); | |
188 } | 263 } |
189 var mainMethod = readMemberReference(allowNull: true); | 264 var mainMethod = readMemberReference(allowNull: true); |
190 return new Program(importTable, uriToSource)..mainMethod = mainMethod; | 265 program.mainMethodName ??= mainMethod; |
191 } | 266 } |
192 | 267 |
193 Map<String, Source> readUriToSource() { | 268 Map<String, Source> readUriToSource() { |
194 readSourceUriTable(); | 269 readSourceUriTable(); |
195 int length = _sourceUriTable.length; | 270 int length = _sourceUriTable.length; |
196 Map<String, Source> uriToLineStarts = <String, Source>{}; | 271 Map<String, Source> uriToSource = <String, Source>{}; |
197 for (int i = 0; i < length; ++i) { | 272 for (int i = 0; i < length; ++i) { |
198 String uri = _sourceUriTable[i]; | 273 String uri = _sourceUriTable[i]; |
199 String sourceCode = readStringEntry(); | 274 String sourceCode = readStringEntry(); |
200 int lineCount = readUInt(); | 275 int lineCount = readUInt(); |
201 List<int> lineStarts = new List<int>(lineCount); | 276 List<int> lineStarts = new List<int>(lineCount); |
202 int previousLineStart = 0; | 277 int previousLineStart = 0; |
203 for (int j = 0; j < lineCount; ++j) { | 278 for (int j = 0; j < lineCount; ++j) { |
204 int lineStart = readUInt() + previousLineStart; | 279 int lineStart = readUInt() + previousLineStart; |
205 lineStarts[j] = lineStart; | 280 lineStarts[j] = lineStart; |
206 previousLineStart = lineStart; | 281 previousLineStart = lineStart; |
207 } | 282 } |
208 uriToLineStarts[uri] = new Source(lineStarts, sourceCode); | 283 uriToSource[uri] = new Source(lineStarts, sourceCode); |
209 } | 284 } |
210 return uriToLineStarts; | 285 return uriToSource; |
211 } | 286 } |
212 | 287 |
213 void _fillLazilyLoadedList( | 288 CanonicalName readCanonicalNameReference() { |
214 List<TreeNode> list, void buildObject(int tag, int index)) { | 289 var index = readUInt(); |
215 int length = readUInt(); | 290 if (index == 0) return null; |
216 list.length = length; | 291 return _linkTable[index - 1]; |
217 for (int i = 0; i < length; ++i) { | |
218 int tag = readByte(); | |
219 buildObject(tag, i); | |
220 } | |
221 } | 292 } |
222 | 293 |
223 Library readLibraryReference() { | 294 LinkedNodeBox readLibraryReference() { |
224 int index = readUInt(); | 295 return readCanonicalNameReference().getBox(); |
225 return importTable[index]; | |
226 } | 296 } |
227 | 297 |
228 DeferredImport readDeferredImportReference() { | 298 DeferredImport readDeferredImportReference() { |
229 int index = readUInt(); | 299 int index = readUInt(); |
230 return _currentLibrary.deferredImports[index]; | 300 return _currentLibrary.deferredImports[index]; |
231 } | 301 } |
232 | 302 |
233 Class readClassReference({bool allowNull: false}) { | 303 LinkedNodeBox readClassReference({bool allowNull: false}) { |
234 int tag = readByte(); | 304 var name = readCanonicalNameReference(); |
235 if (tag == Tag.NullReference) { | 305 if (name == null && !allowNull) { |
236 if (!allowNull) { | 306 throw 'Expected a class reference to be valid but was `null`.'; |
237 throw 'Expected a class reference to be valid but was `null`.'; | |
238 } | |
239 return null; | |
240 } else { | |
241 var library = readLibraryReference(); | |
242 int index = readUInt(); | |
243 return loader.getClassReference(library, tag, index); | |
244 } | 307 } |
308 return name?.getBox(); | |
245 } | 309 } |
246 | 310 |
247 Member readMemberReference({bool allowNull: false}) { | 311 LinkedNodeBox readMemberReference({bool allowNull: false}) { |
248 int tag = readByte(); | 312 var name = readCanonicalNameReference(); |
249 switch (tag) { | 313 if (name == null && !allowNull) { |
250 case Tag.LibraryFieldReference: | 314 throw 'Expected a member reference to be valid but was `null`.'; |
251 case Tag.LibraryProcedureReference: | |
252 var library = readLibraryReference(); | |
253 var index = readUInt(); | |
254 return loader.getLibraryMemberReference(library, tag, index); | |
255 | |
256 case Tag.ClassFieldReference: | |
257 case Tag.ClassConstructorReference: | |
258 case Tag.ClassProcedureReference: | |
259 var classNode = readClassReference(); | |
260 var index = readUInt(); | |
261 return loader.getClassMemberReference(classNode, tag, index); | |
262 | |
263 case Tag.NullReference: | |
264 if (!allowNull) { | |
265 throw 'Expected a member reference to be valid but was `null`.'; | |
266 } | |
267 return null; | |
268 | |
269 default: | |
270 throw fail('Invalid member reference tag: $tag'); | |
271 } | 315 } |
316 return name?.getBox(); | |
272 } | 317 } |
273 | 318 |
274 Name readName() { | 319 Name readName() { |
275 String text = readStringReference(); | 320 String text = readStringReference(); |
276 if (text.isNotEmpty && text[0] == '_') { | 321 if (text.isNotEmpty && text[0] == '_') { |
277 return new Name(text, readLibraryReference()); | 322 return new Name.byReference(text, readLibraryReference()); |
278 } else { | 323 } else { |
279 return new Name(text); | 324 return new Name(text); |
280 } | 325 } |
281 } | 326 } |
282 | 327 |
283 Uri readImportUri() { | 328 Library readLibrary(Program program) { |
284 return Uri.parse(readStringReference()); | 329 int flags = readByte(); |
285 } | 330 bool isExternal = (flags & 0x1) != 0; |
331 _isReadingLibraryImplementation = !isExternal; | |
332 var canonicalName = readCanonicalNameReference(); | |
333 LinkedNodeBox box = canonicalName.getBox(); | |
334 Library library = box.node; | |
335 bool shouldWriteData = library == null || _isReadingLibraryImplementation; | |
336 if (library == null) { | |
337 library = new Library(Uri.parse(canonicalName.name), box: box); | |
338 program.libraries.add(library..parent = program); | |
339 } | |
340 _currentLibrary = library; | |
341 String name = readStringOrNullIfEmpty(); | |
342 // TODO(jensj): We currently save (almost the same) uri twice. | |
343 String fileUri = readUriReference(); | |
286 | 344 |
287 void readLibrary() { | 345 if (shouldWriteData) { |
288 int flags = readByte(); | 346 library.isExternal = isExternal; |
289 _currentLibrary.isExternal = (flags & 0x1) != 0; | 347 library.name = name; |
290 _currentLibrary.name = readStringOrNullIfEmpty(); | 348 library.fileUri = fileUri; |
291 _currentLibrary.importUri = readImportUri(); | 349 } |
292 debugPath.add(_currentLibrary.name ?? | |
293 _currentLibrary.importUri?.toString() ?? | |
294 'library'); | |
295 | 350 |
296 // TODO(jensj): We currently save (almost the same) uri twice. | 351 _readDeferredImports(library); |
297 _currentLibrary.fileUri = readUriReference(); | |
298 | 352 |
299 _readDeferredImports(_currentLibrary); | 353 debugPath.add(library.name ?? library.importUri?.toString() ?? 'library'); |
300 _fillLazilyLoadedList(_currentLibrary.classes, (int tag, int index) { | 354 |
301 readClass(loader.getClassReference(_currentLibrary, tag, index), tag); | 355 _mergeLinkedNodeList(library.classes, readClass, library); |
302 }); | 356 _mergeLinkedNodeList(library.fields, readField, library); |
303 _fillLazilyLoadedList(_currentLibrary.fields, (int tag, int index) { | 357 _mergeLinkedNodeList(library.procedures, readProcedure, library); |
304 readField( | 358 |
305 loader.getLibraryMemberReference(_currentLibrary, tag, index), tag); | |
306 }); | |
307 _fillLazilyLoadedList(_currentLibrary.procedures, (int tag, int index) { | |
308 readProcedure( | |
309 loader.getLibraryMemberReference(_currentLibrary, tag, index), tag); | |
310 }); | |
311 debugPath.removeLast(); | 359 debugPath.removeLast(); |
360 _currentLibrary = null; | |
361 return library; | |
312 } | 362 } |
313 | 363 |
314 void _readDeferredImports(Library library) { | 364 void _readDeferredImports(Library library) { |
315 int count = readUInt(); | 365 int length = readUInt(); |
316 library.deferredImports.length = count; | 366 if (library.isExternal) { |
317 for (int i = 0; i < count; ++i) { | 367 assert(length == 0); |
318 var importNode = _readDeferredImport(); | 368 return; |
319 library.deferredImports.add(importNode..parent = library); | 369 } |
370 library.deferredImports.length = length; | |
371 for (int i = 0; i < length; ++i) { | |
372 library.deferredImports[i] = new DeferredImport.byBox( | |
373 readLibraryReference(), readStringReference())..parent = library; | |
320 } | 374 } |
321 } | 375 } |
322 | 376 |
323 DeferredImport _readDeferredImport() { | 377 Class readClass() { |
324 return new DeferredImport(readLibraryReference(), readStringReference()); | 378 int tag = readByte(); |
325 } | 379 assert(tag == Tag.Class); |
326 | 380 var canonicalName = readCanonicalNameReference(); |
327 void readClass(Class node, int tag) { | 381 var box = canonicalName.getBox(); |
328 assert(node != null); | 382 Class node = box.node; |
329 switch (tag) { | 383 bool shouldWriteData = node == null || _isReadingLibraryImplementation; |
330 case Tag.NormalClass: | 384 if (node == null) { |
331 readNormalClass(node); | 385 node = new Class(box: box)..level = ClassLevel.Temporary; |
332 break; | |
333 case Tag.MixinClass: | |
334 readMixinClass(node); | |
335 break; | |
336 default: | |
337 throw fail('Invalid class tag: $tag'); | |
338 } | 386 } |
339 } | |
340 | |
341 void readNormalClass(Class node) { | |
342 node.fileOffset = readOffset(); | 387 node.fileOffset = readOffset(); |
343 int flags = readByte(); | 388 int flags = readByte(); |
344 node.isAbstract = flags & 0x1 != 0; | 389 node.isAbstract = flags & 0x1 != 0; |
345 int levelIndex = (flags >> 1) & 0x3; | 390 int levelIndex = (flags >> 1) & 0x3; |
346 node.level = ClassLevel.values[levelIndex + 1]; | 391 var level = ClassLevel.values[levelIndex + 1]; |
347 node.name = readStringOrNullIfEmpty(); | 392 if (level.index >= node.level.index) { |
348 node.fileUri = readUriReference(); | 393 node.level = level; |
349 node.annotations = readAnnotationList(node); | 394 } |
395 var name = readStringOrNullIfEmpty(); | |
396 var fileUri = readUriReference(); | |
397 var annotations = readAnnotationList(node); | |
350 debugPath.add(node.name ?? 'normal-class'); | 398 debugPath.add(node.name ?? 'normal-class'); |
351 readAndPushTypeParameterList(node.typeParameters, node); | 399 readAndPushTypeParameterList(node.typeParameters, node); |
352 node.supertype = readSupertypeOption(); | 400 var supertype = readSupertypeOption(); |
401 var mixedInType = readSupertypeOption(); | |
353 _fillNonTreeNodeList(node.implementedTypes, readSupertype); | 402 _fillNonTreeNodeList(node.implementedTypes, readSupertype); |
354 _fillLazilyLoadedList(node.fields, (int tag, int index) { | 403 _mergeLinkedNodeList(node.fields, readField, node); |
355 readField(loader.getClassMemberReference(node, tag, index), tag); | 404 _mergeLinkedNodeList(node.constructors, readConstructor, node); |
356 }); | 405 _mergeLinkedNodeList(node.procedures, readProcedure, node); |
357 _fillLazilyLoadedList(node.constructors, (int tag, int index) { | |
358 readConstructor(loader.getClassMemberReference(node, tag, index), tag); | |
359 }); | |
360 _fillLazilyLoadedList(node.procedures, (int tag, int index) { | |
361 readProcedure(loader.getClassMemberReference(node, tag, index), tag); | |
362 }); | |
363 typeParameterStack.length = 0; | 406 typeParameterStack.length = 0; |
364 debugPath.removeLast(); | 407 debugPath.removeLast(); |
365 } | 408 if (shouldWriteData) { |
366 | 409 node.name = name; |
367 void readMixinClass(Class node) { | 410 node.fileUri = fileUri; |
368 node.fileOffset = readOffset(); | 411 node.annotations = annotations; |
369 int flags = readByte(); | 412 node.supertype = supertype; |
370 node.isAbstract = flags & 0x1 != 0; | 413 node.mixedInType = mixedInType; |
371 int levelIndex = (flags >> 1) & 0x3; | 414 } |
372 node.level = ClassLevel.values[levelIndex]; | 415 return node; |
373 node.name = readStringOrNullIfEmpty(); | |
374 node.fileUri = readUriReference(); | |
375 node.annotations = readAnnotationList(node); | |
376 debugPath.add(node.name ?? 'mixin-class'); | |
377 readAndPushTypeParameterList(node.typeParameters, node); | |
378 node.supertype = readSupertype(); | |
379 node.mixedInType = readSupertype(); | |
380 _fillNonTreeNodeList(node.implementedTypes, readDartType); | |
381 _fillLazilyLoadedList(node.constructors, (int tag, int index) { | |
382 readConstructor(loader.getClassMemberReference(node, tag, index), tag); | |
383 }); | |
384 typeParameterStack.length = 0; | |
385 debugPath.removeLast(); | |
386 } | 416 } |
387 | 417 |
388 int getAndResetTransformerFlags() { | 418 int getAndResetTransformerFlags() { |
389 int flags = _transformerFlags; | 419 int flags = _transformerFlags; |
390 _transformerFlags = 0; | 420 _transformerFlags = 0; |
391 return flags; | 421 return flags; |
392 } | 422 } |
393 | 423 |
394 /// Adds the given flag to the current [Member.transformerFlags]. | 424 /// Adds the given flag to the current [Member.transformerFlags]. |
395 void addTransformerFlag(int flags) { | 425 void addTransformerFlag(int flags) { |
396 _transformerFlags |= flags; | 426 _transformerFlags |= flags; |
397 } | 427 } |
398 | 428 |
399 void readField(Field node, int tag) { | 429 Field readField() { |
400 // Note: as with readProcedure and readConstructor, the tag parameter | 430 int tag = readByte(); |
401 // is unused, but we pass it in to clarify that the tag has already been | |
402 // consumed from the input. | |
403 assert(tag == Tag.Field); | 431 assert(tag == Tag.Field); |
404 node.fileOffset = readOffset(); | 432 var canonicalName = readCanonicalNameReference(); |
405 node.fileEndOffset = readOffset(); | 433 var box = canonicalName.getBox(); |
406 node.flags = readByte(); | 434 Field node = box.node; |
407 node.name = readName(); | 435 bool shouldWriteData = node == null || _isReadingLibraryImplementation; |
408 node.fileUri = readUriReference(); | 436 if (node == null) { |
409 node.annotations = readAnnotationList(node); | 437 node = new Field(null, box: box); |
438 } | |
439 int fileOffset = readOffset(); | |
440 int fileEndOffset = readOffset(); | |
441 int flags = readByte(); | |
442 var name = readName(); | |
443 var fileUri = readUriReference(); | |
444 var annotations = readAnnotationList(node); | |
410 debugPath.add(node.name?.name ?? 'field'); | 445 debugPath.add(node.name?.name ?? 'field'); |
411 node.type = readDartType(); | 446 var type = readDartType(); |
412 node.inferredValue = readOptionalInferredValue(); | 447 var inferredValue = readOptionalInferredValue(); |
413 node.initializer = readExpressionOption(); | 448 var initializer = readExpressionOption(); |
414 node.initializer?.parent = node; | 449 int transformerFlags = getAndResetTransformerFlags(); |
415 node.transformerFlags = getAndResetTransformerFlags(); | |
416 debugPath.removeLast(); | 450 debugPath.removeLast(); |
451 if (shouldWriteData) { | |
452 node.fileOffset = fileOffset; | |
453 node.fileEndOffset = fileEndOffset; | |
454 node.flags = flags; | |
455 node.name = name; | |
456 node.fileUri = fileUri; | |
457 node.annotations = annotations; | |
458 node.type = type; | |
459 node.inferredValue = inferredValue; | |
460 node.initializer = initializer; | |
461 node.initializer?.parent = node; | |
462 node.transformerFlags = transformerFlags; | |
463 } | |
464 return node; | |
417 } | 465 } |
418 | 466 |
419 void readConstructor(Constructor node, int tag) { | 467 Constructor readConstructor() { |
468 int tag = readByte(); | |
420 assert(tag == Tag.Constructor); | 469 assert(tag == Tag.Constructor); |
421 node.fileOffset = readOffset(); | 470 var canonicalName = readCanonicalNameReference(); |
422 node.fileEndOffset = readOffset(); | 471 var box = canonicalName.getBox(); |
423 node.flags = readByte(); | 472 Constructor node = box.node; |
424 node.name = readName(); | 473 bool shouldWriteData = node == null || _isReadingLibraryImplementation; |
425 node.annotations = readAnnotationList(node); | 474 if (node == null) { |
475 node = new Constructor(null, box: box); | |
476 } | |
477 var fileOffset = readOffset(); | |
478 var fileEndOffset = readOffset(); | |
479 var flags = readByte(); | |
480 var name = readName(); | |
481 var annotations = readAnnotationList(node); | |
426 debugPath.add(node.name?.name ?? 'constructor'); | 482 debugPath.add(node.name?.name ?? 'constructor'); |
427 node.function = readFunctionNode()..parent = node; | 483 var function = readFunctionNode(); |
428 pushVariableDeclarations(node.function.positionalParameters); | 484 pushVariableDeclarations(function.positionalParameters); |
429 pushVariableDeclarations(node.function.namedParameters); | 485 pushVariableDeclarations(function.namedParameters); |
430 _fillTreeNodeList(node.initializers, readInitializer, node); | 486 _fillTreeNodeList(node.initializers, readInitializer, node); |
431 variableStack.length = 0; | 487 variableStack.length = 0; |
432 node.transformerFlags = getAndResetTransformerFlags(); | 488 var transformerFlags = getAndResetTransformerFlags(); |
433 debugPath.removeLast(); | 489 debugPath.removeLast(); |
490 if (shouldWriteData) { | |
491 node.fileOffset = fileOffset; | |
492 node.fileEndOffset = fileEndOffset; | |
493 node.flags = flags; | |
494 node.name = name; | |
495 node.annotations = annotations; | |
496 node.function = function..parent = node; | |
497 node.transformerFlags = transformerFlags; | |
498 } | |
499 return node; | |
434 } | 500 } |
435 | 501 |
436 void readProcedure(Procedure node, int tag) { | 502 Procedure readProcedure() { |
503 int tag = readByte(); | |
437 assert(tag == Tag.Procedure); | 504 assert(tag == Tag.Procedure); |
438 node.fileOffset = readOffset(); | 505 var canonicalName = readCanonicalNameReference(); |
439 node.fileEndOffset = readOffset(); | 506 var box = canonicalName.getBox(); |
507 Procedure node = box.node; | |
508 bool shouldWriteData = node == null || _isReadingLibraryImplementation; | |
509 if (node == null) { | |
510 node = new Procedure(null, null, null, box: box); | |
511 } | |
512 var fileOffset = readOffset(); | |
513 var fileEndOffset = readOffset(); | |
440 int kindIndex = readByte(); | 514 int kindIndex = readByte(); |
441 node.kind = ProcedureKind.values[kindIndex]; | 515 var kind = ProcedureKind.values[kindIndex]; |
442 node.flags = readByte(); | 516 var flags = readByte(); |
443 node.name = readName(); | 517 var name = readName(); |
444 node.fileUri = readUriReference(); | 518 var fileUri = readUriReference(); |
445 node.annotations = readAnnotationList(node); | 519 var annotations = readAnnotationList(node); |
446 debugPath.add(node.name?.name ?? 'procedure'); | 520 debugPath.add(node.name?.name ?? 'procedure'); |
447 node.function = readFunctionNodeOption(); | 521 var function = readFunctionNodeOption(); |
448 node.function?.parent = node; | 522 var transformerFlags = getAndResetTransformerFlags(); |
449 node.transformerFlags = getAndResetTransformerFlags(); | |
450 debugPath.removeLast(); | 523 debugPath.removeLast(); |
524 if (shouldWriteData) { | |
525 node.fileOffset = fileOffset; | |
526 node.fileEndOffset = fileEndOffset; | |
527 node.kind = kind; | |
528 node.flags = flags; | |
529 node.name = name; | |
530 node.fileUri = fileUri; | |
531 node.annotations = annotations; | |
532 node.function = function; | |
533 node.function?.parent = node; | |
534 node.transformerFlags = transformerFlags; | |
535 } | |
536 return node; | |
451 } | 537 } |
452 | 538 |
453 Initializer readInitializer() { | 539 Initializer readInitializer() { |
454 int tag = readByte(); | 540 int tag = readByte(); |
455 switch (tag) { | 541 switch (tag) { |
456 case Tag.InvalidInitializer: | 542 case Tag.InvalidInitializer: |
457 return new InvalidInitializer(); | 543 return new InvalidInitializer(); |
458 case Tag.FieldInitializer: | 544 case Tag.FieldInitializer: |
459 return new FieldInitializer(readMemberReference(), readExpression()); | 545 return new FieldInitializer.byBox( |
546 readMemberReference(), readExpression()); | |
460 case Tag.SuperInitializer: | 547 case Tag.SuperInitializer: |
461 return new SuperInitializer(readMemberReference(), readArguments()); | 548 return new SuperInitializer.byBox( |
549 readMemberReference(), readArguments()); | |
462 case Tag.RedirectingInitializer: | 550 case Tag.RedirectingInitializer: |
463 return new RedirectingInitializer( | 551 return new RedirectingInitializer.byBox( |
464 readMemberReference(), readArguments()); | 552 readMemberReference(), readArguments()); |
465 case Tag.LocalInitializer: | 553 case Tag.LocalInitializer: |
466 return new LocalInitializer(readAndPushVariableDeclaration()); | 554 return new LocalInitializer(readAndPushVariableDeclaration()); |
467 default: | 555 default: |
468 throw fail('Invalid initializer tag: $tag'); | 556 throw fail('Invalid initializer tag: $tag'); |
469 } | 557 } |
470 } | 558 } |
471 | 559 |
472 FunctionNode readFunctionNodeOption() { | 560 FunctionNode readFunctionNodeOption() { |
473 return readAndCheckOptionTag() ? readFunctionNode() : null; | 561 return readAndCheckOptionTag() ? readFunctionNode() : null; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
564 int offset = readOffset(); | 652 int offset = readOffset(); |
565 return new VariableSet(readVariableReference(), readExpression()) | 653 return new VariableSet(readVariableReference(), readExpression()) |
566 ..fileOffset = offset; | 654 ..fileOffset = offset; |
567 case Tag.SpecializedVariableSet: | 655 case Tag.SpecializedVariableSet: |
568 int index = tagByte & Tag.SpecializedPayloadMask; | 656 int index = tagByte & Tag.SpecializedPayloadMask; |
569 int offset = readOffset(); | 657 int offset = readOffset(); |
570 return new VariableSet(variableStack[index], readExpression()) | 658 return new VariableSet(variableStack[index], readExpression()) |
571 ..fileOffset = offset; | 659 ..fileOffset = offset; |
572 case Tag.PropertyGet: | 660 case Tag.PropertyGet: |
573 int offset = readOffset(); | 661 int offset = readOffset(); |
574 return new PropertyGet( | 662 return new PropertyGet.byBox( |
575 readExpression(), readName(), readMemberReference(allowNull: true)) | 663 readExpression(), readName(), readMemberReference(allowNull: true)) |
576 ..fileOffset = offset; | 664 ..fileOffset = offset; |
577 case Tag.PropertySet: | 665 case Tag.PropertySet: |
578 int offset = readOffset(); | 666 int offset = readOffset(); |
579 return new PropertySet(readExpression(), readName(), readExpression(), | 667 return new PropertySet.byBox( |
668 readExpression(), | |
669 readName(), | |
670 readExpression(), | |
580 readMemberReference(allowNull: true))..fileOffset = offset; | 671 readMemberReference(allowNull: true))..fileOffset = offset; |
581 case Tag.SuperPropertyGet: | 672 case Tag.SuperPropertyGet: |
582 addTransformerFlag(TransformerFlag.superCalls); | 673 addTransformerFlag(TransformerFlag.superCalls); |
583 return new SuperPropertyGet( | 674 return new SuperPropertyGet.byBox( |
584 readName(), readMemberReference(allowNull: true)); | 675 readName(), readMemberReference(allowNull: true)); |
585 case Tag.SuperPropertySet: | 676 case Tag.SuperPropertySet: |
586 addTransformerFlag(TransformerFlag.superCalls); | 677 addTransformerFlag(TransformerFlag.superCalls); |
587 return new SuperPropertySet( | 678 return new SuperPropertySet.byBox( |
588 readName(), readExpression(), readMemberReference(allowNull: true)); | 679 readName(), readExpression(), readMemberReference(allowNull: true)); |
589 case Tag.DirectPropertyGet: | 680 case Tag.DirectPropertyGet: |
590 return new DirectPropertyGet(readExpression(), readMemberReference()); | 681 return new DirectPropertyGet.byBox( |
682 readExpression(), readMemberReference()); | |
591 case Tag.DirectPropertySet: | 683 case Tag.DirectPropertySet: |
592 return new DirectPropertySet( | 684 return new DirectPropertySet.byBox( |
593 readExpression(), readMemberReference(), readExpression()); | 685 readExpression(), readMemberReference(), readExpression()); |
594 case Tag.StaticGet: | 686 case Tag.StaticGet: |
595 int offset = readOffset(); | 687 int offset = readOffset(); |
596 return new StaticGet(readMemberReference())..fileOffset = offset; | 688 return new StaticGet.byBox(readMemberReference())..fileOffset = offset; |
597 case Tag.StaticSet: | 689 case Tag.StaticSet: |
598 return new StaticSet(readMemberReference(), readExpression()); | 690 return new StaticSet.byBox(readMemberReference(), readExpression()); |
599 case Tag.MethodInvocation: | 691 case Tag.MethodInvocation: |
600 int offset = readOffset(); | 692 int offset = readOffset(); |
601 return new MethodInvocation( | 693 return new MethodInvocation.byBox( |
602 readExpression(), | 694 readExpression(), |
603 readName(), | 695 readName(), |
604 readArguments(), | 696 readArguments(), |
605 readMemberReference(allowNull: true))..fileOffset = offset; | 697 readMemberReference(allowNull: true))..fileOffset = offset; |
606 case Tag.SuperMethodInvocation: | 698 case Tag.SuperMethodInvocation: |
607 int offset = readOffset(); | 699 int offset = readOffset(); |
608 addTransformerFlag(TransformerFlag.superCalls); | 700 addTransformerFlag(TransformerFlag.superCalls); |
609 return new SuperMethodInvocation( | 701 return new SuperMethodInvocation.byBox( |
610 readName(), readArguments(), readMemberReference(allowNull: true)) | 702 readName(), readArguments(), readMemberReference(allowNull: true)) |
611 ..fileOffset = offset; | 703 ..fileOffset = offset; |
612 case Tag.DirectMethodInvocation: | 704 case Tag.DirectMethodInvocation: |
613 return new DirectMethodInvocation( | 705 return new DirectMethodInvocation.byBox( |
614 readExpression(), readMemberReference(), readArguments()); | 706 readExpression(), readMemberReference(), readArguments()); |
615 case Tag.StaticInvocation: | 707 case Tag.StaticInvocation: |
616 int offset = readOffset(); | 708 int offset = readOffset(); |
617 return new StaticInvocation(readMemberReference(), readArguments(), | 709 return new StaticInvocation.byBox( |
618 isConst: false)..fileOffset = offset; | 710 readMemberReference(), readArguments(), isConst: false) |
711 ..fileOffset = offset; | |
619 case Tag.ConstStaticInvocation: | 712 case Tag.ConstStaticInvocation: |
620 int offset = readOffset(); | 713 int offset = readOffset(); |
621 return new StaticInvocation(readMemberReference(), readArguments(), | 714 return new StaticInvocation.byBox( |
622 isConst: true)..fileOffset = offset; | 715 readMemberReference(), readArguments(), isConst: true) |
716 ..fileOffset = offset; | |
623 case Tag.ConstructorInvocation: | 717 case Tag.ConstructorInvocation: |
624 int offset = readOffset(); | 718 int offset = readOffset(); |
625 return new ConstructorInvocation(readMemberReference(), readArguments(), | 719 return new ConstructorInvocation.byBox( |
626 isConst: false)..fileOffset = offset; | 720 readMemberReference(), readArguments(), isConst: false) |
721 ..fileOffset = offset; | |
627 case Tag.ConstConstructorInvocation: | 722 case Tag.ConstConstructorInvocation: |
628 int offset = readOffset(); | 723 int offset = readOffset(); |
629 return new ConstructorInvocation(readMemberReference(), readArguments(), | 724 return new ConstructorInvocation.byBox( |
630 isConst: true)..fileOffset = offset; | 725 readMemberReference(), readArguments(), isConst: true) |
726 ..fileOffset = offset; | |
631 case Tag.Not: | 727 case Tag.Not: |
632 return new Not(readExpression()); | 728 return new Not(readExpression()); |
633 case Tag.LogicalExpression: | 729 case Tag.LogicalExpression: |
634 return new LogicalExpression(readExpression(), | 730 return new LogicalExpression(readExpression(), |
635 logicalOperatorToString(readByte()), readExpression()); | 731 logicalOperatorToString(readByte()), readExpression()); |
636 case Tag.ConditionalExpression: | 732 case Tag.ConditionalExpression: |
637 return new ConditionalExpression(readExpression(), readExpression(), | 733 return new ConditionalExpression(readExpression(), readExpression(), |
638 readExpression(), readDartTypeOption()); | 734 readExpression(), readDartTypeOption()); |
639 case Tag.StringConcatenation: | 735 case Tag.StringConcatenation: |
640 int offset = readOffset(); | 736 int offset = readOffset(); |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
849 | 945 |
850 Block readBlock() { | 946 Block readBlock() { |
851 int stackHeight = variableStack.length; | 947 int stackHeight = variableStack.length; |
852 var body = readStatementList(); | 948 var body = readStatementList(); |
853 variableStack.length = stackHeight; | 949 variableStack.length = stackHeight; |
854 return new Block(body); | 950 return new Block(body); |
855 } | 951 } |
856 | 952 |
857 Supertype readSupertype() { | 953 Supertype readSupertype() { |
858 InterfaceType type = readDartType(); | 954 InterfaceType type = readDartType(); |
859 return new Supertype(type.classNode, type.typeArguments); | 955 return new Supertype.byBox(type.className, type.typeArguments); |
860 } | 956 } |
861 | 957 |
862 Supertype readSupertypeOption() { | 958 Supertype readSupertypeOption() { |
863 return readAndCheckOptionTag() ? readSupertype() : null; | 959 return readAndCheckOptionTag() ? readSupertype() : null; |
864 } | 960 } |
865 | 961 |
866 List<Supertype> readSupertypeList() { | 962 List<Supertype> readSupertypeList() { |
867 return new List<Supertype>.generate(readUInt(), (i) => readSupertype()); | 963 return new List<Supertype>.generate(readUInt(), (i) => readSupertype()); |
868 } | 964 } |
869 | 965 |
(...skipping 18 matching lines...) Expand all Loading... | |
888 switch (tag) { | 984 switch (tag) { |
889 case Tag.BottomType: | 985 case Tag.BottomType: |
890 return const BottomType(); | 986 return const BottomType(); |
891 case Tag.InvalidType: | 987 case Tag.InvalidType: |
892 return const InvalidType(); | 988 return const InvalidType(); |
893 case Tag.DynamicType: | 989 case Tag.DynamicType: |
894 return const DynamicType(); | 990 return const DynamicType(); |
895 case Tag.VoidType: | 991 case Tag.VoidType: |
896 return const VoidType(); | 992 return const VoidType(); |
897 case Tag.InterfaceType: | 993 case Tag.InterfaceType: |
898 return new InterfaceType(readClassReference(), readDartTypeList()); | 994 return new InterfaceType.byBox( |
995 readClassReference(), readDartTypeList()); | |
899 case Tag.SimpleInterfaceType: | 996 case Tag.SimpleInterfaceType: |
900 return new InterfaceType(readClassReference(), const <DartType>[]); | 997 return new InterfaceType.byBox( |
998 readClassReference(), const <DartType>[]); | |
901 case Tag.FunctionType: | 999 case Tag.FunctionType: |
902 int typeParameterStackHeight = typeParameterStack.length; | 1000 int typeParameterStackHeight = typeParameterStack.length; |
903 var typeParameters = readAndPushTypeParameterList(); | 1001 var typeParameters = readAndPushTypeParameterList(); |
904 var requiredParameterCount = readUInt(); | 1002 var requiredParameterCount = readUInt(); |
905 var positional = readDartTypeList(); | 1003 var positional = readDartTypeList(); |
906 var named = readNamedTypeList(); | 1004 var named = readNamedTypeList(); |
907 var returnType = readDartType(); | 1005 var returnType = readDartType(); |
908 typeParameterStack.length = typeParameterStackHeight; | 1006 typeParameterStack.length = typeParameterStackHeight; |
909 return new FunctionType(positional, returnType, | 1007 return new FunctionType(positional, returnType, |
910 typeParameters: typeParameters, | 1008 typeParameters: typeParameters, |
(...skipping 11 matching lines...) Expand all Loading... | |
922 } | 1020 } |
923 } | 1021 } |
924 | 1022 |
925 List<TypeParameter> readAndPushTypeParameterList( | 1023 List<TypeParameter> readAndPushTypeParameterList( |
926 [List<TypeParameter> list, TreeNode parent]) { | 1024 [List<TypeParameter> list, TreeNode parent]) { |
927 int length = readUInt(); | 1025 int length = readUInt(); |
928 if (length == 0) return list ?? <TypeParameter>[]; | 1026 if (length == 0) return list ?? <TypeParameter>[]; |
929 if (list == null) { | 1027 if (list == null) { |
930 list = new List<TypeParameter>.generate( | 1028 list = new List<TypeParameter>.generate( |
931 length, (i) => new TypeParameter(null, null)..parent = parent); | 1029 length, (i) => new TypeParameter(null, null)..parent = parent); |
932 } else { | 1030 } else if (list.length != length) { |
933 list.length = length; | 1031 list.length = length; |
934 for (int i = 0; i < length; ++i) { | 1032 for (int i = 0; i < length; ++i) { |
935 list[i] = new TypeParameter(null, null)..parent = parent; | 1033 list[i] = new TypeParameter(null, null)..parent = parent; |
936 } | 1034 } |
937 } | 1035 } |
938 typeParameterStack.addAll(list); | 1036 typeParameterStack.addAll(list); |
939 for (int i = 0; i < list.length; ++i) { | 1037 for (int i = 0; i < list.length; ++i) { |
940 readTypeParameter(list[i]); | 1038 readTypeParameter(list[i]); |
941 } | 1039 } |
942 return list; | 1040 return list; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
988 isFinal: flags & 0x1 != 0, | 1086 isFinal: flags & 0x1 != 0, |
989 isConst: flags & 0x2 != 0)..fileOffset = offset; | 1087 isConst: flags & 0x2 != 0)..fileOffset = offset; |
990 } | 1088 } |
991 | 1089 |
992 int readOffset() { | 1090 int readOffset() { |
993 // Offset is saved as unsigned, | 1091 // Offset is saved as unsigned, |
994 // but actually ranges from -1 and up (thus the -1) | 1092 // but actually ranges from -1 and up (thus the -1) |
995 return readUInt() - 1; | 1093 return readUInt() - 1; |
996 } | 1094 } |
997 } | 1095 } |
OLD | NEW |