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