Chromium Code Reviews| Index: pkg/kernel/lib/binary/ast_from_binary.dart |
| diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart |
| index 100fe9886627918ff9ff771dae1c3443e94e0f66..a8c09eb41addc62f7515fbb660d1e89467f4174e 100644 |
| --- a/pkg/kernel/lib/binary/ast_from_binary.dart |
| +++ b/pkg/kernel/lib/binary/ast_from_binary.dart |
| @@ -3,11 +3,11 @@ |
| // BSD-style license that can be found in the LICENSE file. |
| library kernel.ast_from_binary; |
| +import 'dart:convert'; |
| + |
| import '../ast.dart'; |
| +import '../transformations/flags.dart'; |
| import 'tag.dart'; |
| -import 'loader.dart'; |
| -import 'dart:convert'; |
| -import 'package:kernel/transformations/flags.dart'; |
| class ParseError { |
| String filename; |
| @@ -21,8 +21,6 @@ class ParseError { |
| } |
| class BinaryBuilder { |
| - final BinaryReferenceLoader loader; |
| - final List<Library> importTable = <Library>[]; |
| final List<VariableDeclaration> variableStack = <VariableDeclaration>[]; |
| final List<LabeledStatement> labelStack = <LabeledStatement>[]; |
| int labelStackBase = 0; |
| @@ -31,16 +29,19 @@ class BinaryBuilder { |
| final String filename; |
| final List<int> _bytes; |
| int _byteIndex = 0; |
| - Library _currentLibrary; |
| List<String> _stringTable; |
| List<String> _sourceUriTable; |
| + List<CanonicalName> _linkTable; |
| int _transformerFlags = 0; |
| + Library _currentLibrary; |
| // If something goes wrong, this list should indicate what library, |
| // class, and member was being built. |
| List<String> debugPath = <String>[]; |
| - BinaryBuilder(this.loader, this._bytes, [this.filename]); |
| + bool _isReadingLibraryImplementation = false; |
| + |
| + BinaryBuilder(this._bytes, [this.filename]); |
| fail(String message) { |
| throw new ParseError(message, |
| @@ -126,10 +127,10 @@ class BinaryBuilder { |
| InferredValue readOptionalInferredValue() { |
| if (readAndCheckOptionTag()) { |
| - Class baseClass = readClassReference(allowNull: true); |
| + LinkedNodeBox baseClass = readClassReference(allowNull: true); |
| BaseClassKind baseClassKind = BaseClassKind.values[readByte()]; |
| int valueBits = readByte(); |
| - return new InferredValue(baseClass, baseClassKind, valueBits); |
| + return new InferredValue.byBox(baseClass, baseClassKind, valueBits); |
| } |
| return null; |
| } |
| @@ -170,7 +171,82 @@ class BinaryBuilder { |
| } |
| } |
| - Program readProgramFile() { |
| + /// Reads a list of linked nodes, reusing any existing objects already in the |
| + /// linking tree. The nodes are merged into [list], and if reading the library |
| + /// implementation, the order is corrected. |
| + /// |
| + /// [readObject] should read the object definition and its canonical name. |
| + /// If an existing object is bound to the canonical name, the existing object |
| + /// must be reused and returned. |
| + void _mergeLinkedNodeList( |
| + List<LinkedNode> list, LinkedNode readObject(), TreeNode parent) { |
| + if (_isReadingLibraryImplementation) { |
| + // When reading the library implementation, overwrite the whole list |
| + // with the new one. |
| + _fillTreeNodeList(list, readObject, parent); |
| + } else { |
| + // When reading an external library, the results should either be: |
| + // - merged with the existing external library definition (if any) |
| + // - ignored if the library implementation is already in memory |
| + int numberOfNodes = readUInt(); |
| + for (int i = 0; i < numberOfNodes; ++i) { |
| + var value = readObject(); |
| + // We use the parent pointer of a node to determine if it already is in |
| + // the AST and hence should not be added again. |
| + if (value.parent == null) { |
| + list.add(value..parent = parent); |
| + } |
| + } |
| + } |
| + } |
| + |
| + void readLinkTable(CanonicalName linkRoot) { |
| + int length = readUInt(); |
| + _linkTable = new List<CanonicalName>(length); |
| + for (int i = 0; i < length; ++i) { |
| + int biasedParentIndex = readUInt(); |
| + String name = readStringReference(); |
| + var parent = |
| + biasedParentIndex == 0 ? linkRoot : _linkTable[biasedParentIndex - 1]; |
| + _linkTable[i] = parent.getChild(name); |
| + } |
| + } |
| + |
| + /// Deserializes a kernel program and stores it in [program]. |
| + /// |
| + /// When linking with a non-empty program, canonical names must have been |
| + /// computed ahead of time. |
| + /// |
| + /// The input bytes may contain multiple files concatenated. |
| + void readProgram(Program program) { |
| + while (_byteIndex < _bytes.length) { |
| + _readProgram(program); |
| + } |
| + } |
| + |
| + /// Reads a single program file from the input and loads it into [program], |
| + /// overwriting and reusing any existing data in the program. |
| + /// |
| + /// When linking with a non-empty program, canonical names must have been |
| + /// computed ahead of time. |
| + /// |
| + /// This should *only* be used when there is a reason to not allow |
| + /// concatenated files. |
| + void readSingleFileProgram(Program program) { |
| + _readProgram(program); |
| + if (_byteIndex < _bytes.length) { |
| + if (_byteIndex + 3 < _bytes.length) { |
| + int magic = readMagicWord(); |
| + if (magic == Tag.ProgramFile) { |
| + throw 'Concatenated program file given when a single program ' |
| + 'was expected.'; |
| + } |
| + } |
| + throw 'Unrecognized bytes following program data'; |
| + } |
| + } |
| + |
| + void _readProgram(Program program) { |
|
Kevin Millikin (Google)
2017/02/22 09:09:30
_readOneProgram?
asgerf
2017/02/22 10:06:54
Done.
|
| int magic = readMagicWord(); |
| if (magic != Tag.ProgramFile) { |
| throw fail('This is not a binary dart file. ' |
| @@ -178,22 +254,21 @@ class BinaryBuilder { |
| } |
| readStringTable(); |
| Map<String, Source> uriToSource = readUriToSource(); |
| - importTable.length = readUInt(); |
| - for (int i = 0; i < importTable.length; ++i) { |
| - importTable[i] = new Library(null); |
| - } |
| - for (int i = 0; i < importTable.length; ++i) { |
| - _currentLibrary = importTable[i]; |
| - readLibrary(); |
| + program.uriToSource.addAll(uriToSource); |
| + readLinkTable(program.root); |
| + int numberOfLibraries = readUInt(); |
| + List<Library> libraries = new List<Library>(numberOfLibraries); |
| + for (int i = 0; i < numberOfLibraries; ++i) { |
| + libraries[i] = readLibrary(program); |
| } |
| var mainMethod = readMemberReference(allowNull: true); |
| - return new Program(importTable, uriToSource)..mainMethod = mainMethod; |
| + program.mainMethodName ??= mainMethod; |
| } |
| Map<String, Source> readUriToSource() { |
| readSourceUriTable(); |
| int length = _sourceUriTable.length; |
| - Map<String, Source> uriToLineStarts = <String, Source>{}; |
| + Map<String, Source> uriToSource = <String, Source>{}; |
| for (int i = 0; i < length; ++i) { |
| String uri = _sourceUriTable[i]; |
| String sourceCode = readStringEntry(); |
| @@ -205,24 +280,19 @@ class BinaryBuilder { |
| lineStarts[j] = lineStart; |
| previousLineStart = lineStart; |
| } |
| - uriToLineStarts[uri] = new Source(lineStarts, sourceCode); |
| + uriToSource[uri] = new Source(lineStarts, sourceCode); |
| } |
| - return uriToLineStarts; |
| + return uriToSource; |
| } |
| - void _fillLazilyLoadedList( |
| - List<TreeNode> list, void buildObject(int tag, int index)) { |
| - int length = readUInt(); |
| - list.length = length; |
| - for (int i = 0; i < length; ++i) { |
| - int tag = readByte(); |
| - buildObject(tag, i); |
| - } |
| + CanonicalName readCanonicalNameReference() { |
| + var index = readUInt(); |
| + if (index == 0) return null; |
| + return _linkTable[index - 1]; |
| } |
| - Library readLibraryReference() { |
| - int index = readUInt(); |
| - return importTable[index]; |
| + LinkedNodeBox readLibraryReference() { |
| + return readCanonicalNameReference().getBox(); |
| } |
| DeferredImport readDeferredImportReference() { |
| @@ -230,159 +300,119 @@ class BinaryBuilder { |
| return _currentLibrary.deferredImports[index]; |
| } |
| - Class readClassReference({bool allowNull: false}) { |
| - int tag = readByte(); |
| - if (tag == Tag.NullReference) { |
| - if (!allowNull) { |
| - throw 'Expected a class reference to be valid but was `null`.'; |
| - } |
| - return null; |
| - } else { |
| - var library = readLibraryReference(); |
| - int index = readUInt(); |
| - return loader.getClassReference(library, tag, index); |
| + LinkedNodeBox readClassReference({bool allowNull: false}) { |
| + var name = readCanonicalNameReference(); |
| + if (name == null && !allowNull) { |
| + throw 'Expected a class reference to be valid but was `null`.'; |
| } |
| + return name?.getBox(); |
| } |
| - Member readMemberReference({bool allowNull: false}) { |
| - int tag = readByte(); |
| - switch (tag) { |
| - case Tag.LibraryFieldReference: |
| - case Tag.LibraryProcedureReference: |
| - var library = readLibraryReference(); |
| - var index = readUInt(); |
| - return loader.getLibraryMemberReference(library, tag, index); |
| - |
| - case Tag.ClassFieldReference: |
| - case Tag.ClassConstructorReference: |
| - case Tag.ClassProcedureReference: |
| - var classNode = readClassReference(); |
| - var index = readUInt(); |
| - return loader.getClassMemberReference(classNode, tag, index); |
| - |
| - case Tag.NullReference: |
| - if (!allowNull) { |
| - throw 'Expected a member reference to be valid but was `null`.'; |
| - } |
| - return null; |
| - |
| - default: |
| - throw fail('Invalid member reference tag: $tag'); |
| + LinkedNodeBox readMemberReference({bool allowNull: false}) { |
| + var name = readCanonicalNameReference(); |
| + if (name == null && !allowNull) { |
| + throw 'Expected a member reference to be valid but was `null`.'; |
| } |
| + return name?.getBox(); |
| } |
| Name readName() { |
| String text = readStringReference(); |
| if (text.isNotEmpty && text[0] == '_') { |
| - return new Name(text, readLibraryReference()); |
| + return new Name.byReference(text, readLibraryReference()); |
| } else { |
| return new Name(text); |
| } |
| } |
| - Uri readImportUri() { |
| - return Uri.parse(readStringReference()); |
| - } |
| - |
| - void readLibrary() { |
| + Library readLibrary(Program program) { |
| int flags = readByte(); |
| - _currentLibrary.isExternal = (flags & 0x1) != 0; |
| - _currentLibrary.name = readStringOrNullIfEmpty(); |
| - _currentLibrary.importUri = readImportUri(); |
| - debugPath.add(_currentLibrary.name ?? |
| - _currentLibrary.importUri?.toString() ?? |
| - 'library'); |
| - |
| + bool isExternal = (flags & 0x1) != 0; |
| + _isReadingLibraryImplementation = !isExternal; |
| + var canonicalName = readCanonicalNameReference(); |
| + LinkedNodeBox box = canonicalName.getBox(); |
| + Library library = box.node; |
| + bool shouldWriteData = library == null || _isReadingLibraryImplementation; |
| + if (library == null) { |
| + library = new Library(Uri.parse(canonicalName.name), box: box); |
| + program.libraries.add(library..parent = program); |
| + } |
| + _currentLibrary = library; |
| + String name = readStringOrNullIfEmpty(); |
| // TODO(jensj): We currently save (almost the same) uri twice. |
| - _currentLibrary.fileUri = readUriReference(); |
| - |
| - _readDeferredImports(_currentLibrary); |
| - _fillLazilyLoadedList(_currentLibrary.classes, (int tag, int index) { |
| - readClass(loader.getClassReference(_currentLibrary, tag, index), tag); |
| - }); |
| - _fillLazilyLoadedList(_currentLibrary.fields, (int tag, int index) { |
| - readField( |
| - loader.getLibraryMemberReference(_currentLibrary, tag, index), tag); |
| - }); |
| - _fillLazilyLoadedList(_currentLibrary.procedures, (int tag, int index) { |
| - readProcedure( |
| - loader.getLibraryMemberReference(_currentLibrary, tag, index), tag); |
| - }); |
| - debugPath.removeLast(); |
| - } |
| + String fileUri = readUriReference(); |
| - void _readDeferredImports(Library library) { |
| - int count = readUInt(); |
| - library.deferredImports.length = count; |
| - for (int i = 0; i < count; ++i) { |
| - var importNode = _readDeferredImport(); |
| - library.deferredImports.add(importNode..parent = library); |
| + if (shouldWriteData) { |
| + library.isExternal = isExternal; |
| + library.name = name; |
| + library.fileUri = fileUri; |
| } |
| - } |
| - DeferredImport _readDeferredImport() { |
| - return new DeferredImport(readLibraryReference(), readStringReference()); |
| + _readDeferredImports(library); |
| + |
| + debugPath.add(library.name ?? library.importUri?.toString() ?? 'library'); |
| + |
| + _mergeLinkedNodeList(library.classes, readClass, library); |
| + _mergeLinkedNodeList(library.fields, readField, library); |
| + _mergeLinkedNodeList(library.procedures, readProcedure, library); |
| + |
| + debugPath.removeLast(); |
| + _currentLibrary = null; |
| + return library; |
| } |
| - void readClass(Class node, int tag) { |
| - assert(node != null); |
| - switch (tag) { |
| - case Tag.NormalClass: |
| - readNormalClass(node); |
| - break; |
| - case Tag.MixinClass: |
| - readMixinClass(node); |
| - break; |
| - default: |
| - throw fail('Invalid class tag: $tag'); |
| + void _readDeferredImports(Library library) { |
| + int length = readUInt(); |
| + if (library.isExternal) { |
| + assert(length == 0); |
| + return; |
| + } |
| + library.deferredImports.length = length; |
| + for (int i = 0; i < length; ++i) { |
| + library.deferredImports[i] = new DeferredImport.byBox( |
| + readLibraryReference(), readStringReference())..parent = library; |
| } |
| } |
| - void readNormalClass(Class node) { |
| + Class readClass() { |
| + int tag = readByte(); |
| + assert(tag == Tag.Class); |
| + var canonicalName = readCanonicalNameReference(); |
| + var box = canonicalName.getBox(); |
| + Class node = box.node; |
| + bool shouldWriteData = node == null || _isReadingLibraryImplementation; |
| + if (node == null) { |
| + node = new Class(box: box)..level = ClassLevel.Temporary; |
| + } |
| node.fileOffset = readOffset(); |
| int flags = readByte(); |
| node.isAbstract = flags & 0x1 != 0; |
| int levelIndex = (flags >> 1) & 0x3; |
| - node.level = ClassLevel.values[levelIndex + 1]; |
| - node.name = readStringOrNullIfEmpty(); |
| - node.fileUri = readUriReference(); |
| - node.annotations = readAnnotationList(node); |
| + var level = ClassLevel.values[levelIndex + 1]; |
| + if (level.index >= node.level.index) { |
| + node.level = level; |
| + } |
| + var name = readStringOrNullIfEmpty(); |
| + var fileUri = readUriReference(); |
| + var annotations = readAnnotationList(node); |
| debugPath.add(node.name ?? 'normal-class'); |
| readAndPushTypeParameterList(node.typeParameters, node); |
| - node.supertype = readSupertypeOption(); |
| + var supertype = readSupertypeOption(); |
| + var mixedInType = readSupertypeOption(); |
| _fillNonTreeNodeList(node.implementedTypes, readSupertype); |
| - _fillLazilyLoadedList(node.fields, (int tag, int index) { |
| - readField(loader.getClassMemberReference(node, tag, index), tag); |
| - }); |
| - _fillLazilyLoadedList(node.constructors, (int tag, int index) { |
| - readConstructor(loader.getClassMemberReference(node, tag, index), tag); |
| - }); |
| - _fillLazilyLoadedList(node.procedures, (int tag, int index) { |
| - readProcedure(loader.getClassMemberReference(node, tag, index), tag); |
| - }); |
| - typeParameterStack.length = 0; |
| - debugPath.removeLast(); |
| - } |
| - |
| - void readMixinClass(Class node) { |
| - node.fileOffset = readOffset(); |
| - int flags = readByte(); |
| - node.isAbstract = flags & 0x1 != 0; |
| - int levelIndex = (flags >> 1) & 0x3; |
| - node.level = ClassLevel.values[levelIndex]; |
| - node.name = readStringOrNullIfEmpty(); |
| - node.fileUri = readUriReference(); |
| - node.annotations = readAnnotationList(node); |
| - debugPath.add(node.name ?? 'mixin-class'); |
| - readAndPushTypeParameterList(node.typeParameters, node); |
| - node.supertype = readSupertype(); |
| - node.mixedInType = readSupertype(); |
| - _fillNonTreeNodeList(node.implementedTypes, readDartType); |
| - _fillLazilyLoadedList(node.constructors, (int tag, int index) { |
| - readConstructor(loader.getClassMemberReference(node, tag, index), tag); |
| - }); |
| + _mergeLinkedNodeList(node.fields, readField, node); |
| + _mergeLinkedNodeList(node.constructors, readConstructor, node); |
| + _mergeLinkedNodeList(node.procedures, readProcedure, node); |
| typeParameterStack.length = 0; |
| debugPath.removeLast(); |
| + if (shouldWriteData) { |
| + node.name = name; |
| + node.fileUri = fileUri; |
| + node.annotations = annotations; |
| + node.supertype = supertype; |
| + node.mixedInType = mixedInType; |
| + } |
| + return node; |
| } |
| int getAndResetTransformerFlags() { |
| @@ -396,58 +426,114 @@ class BinaryBuilder { |
| _transformerFlags |= flags; |
| } |
| - void readField(Field node, int tag) { |
| - // Note: as with readProcedure and readConstructor, the tag parameter |
| - // is unused, but we pass it in to clarify that the tag has already been |
| - // consumed from the input. |
| + Field readField() { |
| + int tag = readByte(); |
| assert(tag == Tag.Field); |
| - node.fileOffset = readOffset(); |
| - node.fileEndOffset = readOffset(); |
| - node.flags = readByte(); |
| - node.name = readName(); |
| - node.fileUri = readUriReference(); |
| - node.annotations = readAnnotationList(node); |
| + var canonicalName = readCanonicalNameReference(); |
| + var box = canonicalName.getBox(); |
| + Field node = box.node; |
| + bool shouldWriteData = node == null || _isReadingLibraryImplementation; |
| + if (node == null) { |
| + node = new Field(null, box: box); |
| + } |
| + int fileOffset = readOffset(); |
| + int fileEndOffset = readOffset(); |
| + int flags = readByte(); |
| + var name = readName(); |
| + var fileUri = readUriReference(); |
| + var annotations = readAnnotationList(node); |
| debugPath.add(node.name?.name ?? 'field'); |
| - node.type = readDartType(); |
| - node.inferredValue = readOptionalInferredValue(); |
| - node.initializer = readExpressionOption(); |
| - node.initializer?.parent = node; |
| - node.transformerFlags = getAndResetTransformerFlags(); |
| + var type = readDartType(); |
| + var inferredValue = readOptionalInferredValue(); |
| + var initializer = readExpressionOption(); |
| + int transformerFlags = getAndResetTransformerFlags(); |
| debugPath.removeLast(); |
| + if (shouldWriteData) { |
| + node.fileOffset = fileOffset; |
| + node.fileEndOffset = fileEndOffset; |
| + node.flags = flags; |
| + node.name = name; |
| + node.fileUri = fileUri; |
| + node.annotations = annotations; |
| + node.type = type; |
| + node.inferredValue = inferredValue; |
| + node.initializer = initializer; |
| + node.initializer?.parent = node; |
| + node.transformerFlags = transformerFlags; |
| + } |
| + return node; |
| } |
| - void readConstructor(Constructor node, int tag) { |
| + Constructor readConstructor() { |
| + int tag = readByte(); |
| assert(tag == Tag.Constructor); |
| - node.fileOffset = readOffset(); |
| - node.fileEndOffset = readOffset(); |
| - node.flags = readByte(); |
| - node.name = readName(); |
| - node.annotations = readAnnotationList(node); |
| + var canonicalName = readCanonicalNameReference(); |
| + var box = canonicalName.getBox(); |
| + Constructor node = box.node; |
| + bool shouldWriteData = node == null || _isReadingLibraryImplementation; |
| + if (node == null) { |
| + node = new Constructor(null, box: box); |
| + } |
| + var fileOffset = readOffset(); |
| + var fileEndOffset = readOffset(); |
| + var flags = readByte(); |
| + var name = readName(); |
| + var annotations = readAnnotationList(node); |
| debugPath.add(node.name?.name ?? 'constructor'); |
| - node.function = readFunctionNode()..parent = node; |
| - pushVariableDeclarations(node.function.positionalParameters); |
| - pushVariableDeclarations(node.function.namedParameters); |
| + var function = readFunctionNode(); |
| + pushVariableDeclarations(function.positionalParameters); |
| + pushVariableDeclarations(function.namedParameters); |
| _fillTreeNodeList(node.initializers, readInitializer, node); |
| variableStack.length = 0; |
| - node.transformerFlags = getAndResetTransformerFlags(); |
| + var transformerFlags = getAndResetTransformerFlags(); |
| debugPath.removeLast(); |
| + if (shouldWriteData) { |
| + node.fileOffset = fileOffset; |
| + node.fileEndOffset = fileEndOffset; |
| + node.flags = flags; |
| + node.name = name; |
| + node.annotations = annotations; |
| + node.function = function..parent = node; |
| + node.transformerFlags = transformerFlags; |
| + } |
| + return node; |
| } |
| - void readProcedure(Procedure node, int tag) { |
| + Procedure readProcedure() { |
| + int tag = readByte(); |
| assert(tag == Tag.Procedure); |
| - node.fileOffset = readOffset(); |
| - node.fileEndOffset = readOffset(); |
| + var canonicalName = readCanonicalNameReference(); |
| + var box = canonicalName.getBox(); |
| + Procedure node = box.node; |
| + bool shouldWriteData = node == null || _isReadingLibraryImplementation; |
| + if (node == null) { |
| + node = new Procedure(null, null, null, box: box); |
| + } |
| + var fileOffset = readOffset(); |
| + var fileEndOffset = readOffset(); |
| int kindIndex = readByte(); |
| - node.kind = ProcedureKind.values[kindIndex]; |
| - node.flags = readByte(); |
| - node.name = readName(); |
| - node.fileUri = readUriReference(); |
| - node.annotations = readAnnotationList(node); |
| + var kind = ProcedureKind.values[kindIndex]; |
| + var flags = readByte(); |
| + var name = readName(); |
| + var fileUri = readUriReference(); |
| + var annotations = readAnnotationList(node); |
| debugPath.add(node.name?.name ?? 'procedure'); |
| - node.function = readFunctionNodeOption(); |
| - node.function?.parent = node; |
| - node.transformerFlags = getAndResetTransformerFlags(); |
| + var function = readFunctionNodeOption(); |
| + var transformerFlags = getAndResetTransformerFlags(); |
| debugPath.removeLast(); |
| + if (shouldWriteData) { |
| + node.fileOffset = fileOffset; |
| + node.fileEndOffset = fileEndOffset; |
| + node.kind = kind; |
| + node.flags = flags; |
| + node.name = name; |
| + node.fileUri = fileUri; |
| + node.annotations = annotations; |
| + node.function = function; |
| + node.function?.parent = node; |
| + node.transformerFlags = transformerFlags; |
| + } |
| + return node; |
| } |
| Initializer readInitializer() { |
| @@ -456,11 +542,13 @@ class BinaryBuilder { |
| case Tag.InvalidInitializer: |
| return new InvalidInitializer(); |
| case Tag.FieldInitializer: |
| - return new FieldInitializer(readMemberReference(), readExpression()); |
| + return new FieldInitializer.byBox( |
| + readMemberReference(), readExpression()); |
| case Tag.SuperInitializer: |
| - return new SuperInitializer(readMemberReference(), readArguments()); |
| + return new SuperInitializer.byBox( |
| + readMemberReference(), readArguments()); |
| case Tag.RedirectingInitializer: |
| - return new RedirectingInitializer( |
| + return new RedirectingInitializer.byBox( |
| readMemberReference(), readArguments()); |
| case Tag.LocalInitializer: |
| return new LocalInitializer(readAndPushVariableDeclaration()); |
| @@ -571,34 +659,38 @@ class BinaryBuilder { |
| ..fileOffset = offset; |
| case Tag.PropertyGet: |
| int offset = readOffset(); |
| - return new PropertyGet( |
| + return new PropertyGet.byBox( |
| readExpression(), readName(), readMemberReference(allowNull: true)) |
| ..fileOffset = offset; |
| case Tag.PropertySet: |
| int offset = readOffset(); |
| - return new PropertySet(readExpression(), readName(), readExpression(), |
| + return new PropertySet.byBox( |
| + readExpression(), |
| + readName(), |
| + readExpression(), |
| readMemberReference(allowNull: true))..fileOffset = offset; |
| case Tag.SuperPropertyGet: |
| addTransformerFlag(TransformerFlag.superCalls); |
| - return new SuperPropertyGet( |
| + return new SuperPropertyGet.byBox( |
| readName(), readMemberReference(allowNull: true)); |
| case Tag.SuperPropertySet: |
| addTransformerFlag(TransformerFlag.superCalls); |
| - return new SuperPropertySet( |
| + return new SuperPropertySet.byBox( |
| readName(), readExpression(), readMemberReference(allowNull: true)); |
| case Tag.DirectPropertyGet: |
| - return new DirectPropertyGet(readExpression(), readMemberReference()); |
| + return new DirectPropertyGet.byBox( |
| + readExpression(), readMemberReference()); |
| case Tag.DirectPropertySet: |
| - return new DirectPropertySet( |
| + return new DirectPropertySet.byBox( |
| readExpression(), readMemberReference(), readExpression()); |
| case Tag.StaticGet: |
| int offset = readOffset(); |
| - return new StaticGet(readMemberReference())..fileOffset = offset; |
| + return new StaticGet.byBox(readMemberReference())..fileOffset = offset; |
| case Tag.StaticSet: |
| - return new StaticSet(readMemberReference(), readExpression()); |
| + return new StaticSet.byBox(readMemberReference(), readExpression()); |
| case Tag.MethodInvocation: |
| int offset = readOffset(); |
| - return new MethodInvocation( |
| + return new MethodInvocation.byBox( |
| readExpression(), |
| readName(), |
| readArguments(), |
| @@ -606,28 +698,32 @@ class BinaryBuilder { |
| case Tag.SuperMethodInvocation: |
| int offset = readOffset(); |
| addTransformerFlag(TransformerFlag.superCalls); |
| - return new SuperMethodInvocation( |
| + return new SuperMethodInvocation.byBox( |
| readName(), readArguments(), readMemberReference(allowNull: true)) |
| ..fileOffset = offset; |
| case Tag.DirectMethodInvocation: |
| - return new DirectMethodInvocation( |
| + return new DirectMethodInvocation.byBox( |
| readExpression(), readMemberReference(), readArguments()); |
| case Tag.StaticInvocation: |
| int offset = readOffset(); |
| - return new StaticInvocation(readMemberReference(), readArguments(), |
| - isConst: false)..fileOffset = offset; |
| + return new StaticInvocation.byBox( |
| + readMemberReference(), readArguments(), isConst: false) |
| + ..fileOffset = offset; |
| case Tag.ConstStaticInvocation: |
| int offset = readOffset(); |
| - return new StaticInvocation(readMemberReference(), readArguments(), |
| - isConst: true)..fileOffset = offset; |
| + return new StaticInvocation.byBox( |
| + readMemberReference(), readArguments(), isConst: true) |
| + ..fileOffset = offset; |
| case Tag.ConstructorInvocation: |
| int offset = readOffset(); |
| - return new ConstructorInvocation(readMemberReference(), readArguments(), |
| - isConst: false)..fileOffset = offset; |
| + return new ConstructorInvocation.byBox( |
| + readMemberReference(), readArguments(), isConst: false) |
| + ..fileOffset = offset; |
| case Tag.ConstConstructorInvocation: |
| int offset = readOffset(); |
| - return new ConstructorInvocation(readMemberReference(), readArguments(), |
| - isConst: true)..fileOffset = offset; |
| + return new ConstructorInvocation.byBox( |
| + readMemberReference(), readArguments(), isConst: true) |
| + ..fileOffset = offset; |
| case Tag.Not: |
| return new Not(readExpression()); |
| case Tag.LogicalExpression: |
| @@ -856,7 +952,7 @@ class BinaryBuilder { |
| Supertype readSupertype() { |
| InterfaceType type = readDartType(); |
| - return new Supertype(type.classNode, type.typeArguments); |
| + return new Supertype.byBox(type.className, type.typeArguments); |
| } |
| Supertype readSupertypeOption() { |
| @@ -895,9 +991,11 @@ class BinaryBuilder { |
| case Tag.VoidType: |
| return const VoidType(); |
| case Tag.InterfaceType: |
| - return new InterfaceType(readClassReference(), readDartTypeList()); |
| + return new InterfaceType.byBox( |
| + readClassReference(), readDartTypeList()); |
| case Tag.SimpleInterfaceType: |
| - return new InterfaceType(readClassReference(), const <DartType>[]); |
| + return new InterfaceType.byBox( |
| + readClassReference(), const <DartType>[]); |
| case Tag.FunctionType: |
| int typeParameterStackHeight = typeParameterStack.length; |
| var typeParameters = readAndPushTypeParameterList(); |
| @@ -929,7 +1027,7 @@ class BinaryBuilder { |
| if (list == null) { |
| list = new List<TypeParameter>.generate( |
| length, (i) => new TypeParameter(null, null)..parent = parent); |
| - } else { |
| + } else if (list.length != length) { |
| list.length = length; |
| for (int i = 0; i < length; ++i) { |
| list[i] = new TypeParameter(null, null)..parent = parent; |