anchor.diff:      int tag = readByte();
       switch (tag) {
         case Tag.TypedefType:
  -        int nullabilityIndex = readByte();
  -        return new TypedefType.byReference(readTypedefReference(),
  -            Nullability.values[nullabilityIndex], readDartTypeList());
  +        return _readTypedefType();
         case Tag.BottomType:
  -        return const BottomType();
  +        return _readBottomType();
         case Tag.InvalidType:
  -        return const InvalidType();
  +        return _readInvalidType();
         case Tag.DynamicType:
  -        return const DynamicType();
  +        return _readDynamicType();
         case Tag.VoidType:
  -        return const VoidType();
  +        return _readVoidType();
         case Tag.NeverType:
  -        int nullabilityIndex = readByte();
  -        return new NeverType(Nullability.values[nullabilityIndex]);
  +        return _readNeverType();
         case Tag.InterfaceType:
  -        int nullabilityIndex = readByte();
  -        Reference reference = readClassReference();
  -        List<DartType> typeArguments = readDartTypeList();
  -        {
  -          CanonicalName canonicalName = reference.canonicalName;
  -          if (canonicalName.name == "FutureOr" &&
  -              canonicalName.parent != null &&
  -              canonicalName.parent.name == "dart:async" &&
  -              canonicalName.parent.parent != null &&
  -              canonicalName.parent.parent.isRoot) {
  -            return new FutureOrType(
  -                typeArguments.single, Nullability.values[nullabilityIndex]);
  -          }
  -        }
  -        return new InterfaceType.byReference(
  -            reference, Nullability.values[nullabilityIndex], typeArguments);
  +        return _readInterfaceType();
         case Tag.SimpleInterfaceType:
  -        int nullabilityIndex = readByte();
  -        Reference classReference = readClassReference();
  -        {
  -          CanonicalName canonicalName = classReference.canonicalName;
  -          if (canonicalName != null &&
  -              !forSupertype &&
  -              canonicalName.name == "Null" &&
  -              canonicalName.parent?.name == "dart:core" &&
  -              (canonicalName.parent?.parent?.isRoot ?? false)) {
  -            return const NullType();
  -          }
  -        }
  -        return new InterfaceType.byReference(classReference,
  -            Nullability.values[nullabilityIndex], const <DartType>[]);
  +        return _readSimpleInterfaceType(forSupertype);
         case Tag.FunctionType:
  -        int typeParameterStackHeight = typeParameterStack.length;
  -        int nullabilityIndex = readByte();
  -        List<TypeParameter> typeParameters = readAndPushTypeParameterList();
  -        int requiredParameterCount = readUInt30();
  -        int totalParameterCount = readUInt30();
  -        List<DartType> positional = readDartTypeList();
  -        List<NamedType> named = readNamedTypeList();
  -        DartType typedefType = readDartTypeOption();
  -        assert(positional.length + named.length == totalParameterCount);
  -        DartType returnType = readDartType();
  -        typeParameterStack.length = typeParameterStackHeight;
  -        return new FunctionType(
  -            positional, returnType, Nullability.values[nullabilityIndex],
  -            typeParameters: typeParameters,
  -            requiredParameterCount: requiredParameterCount,
  -            namedParameters: named,
  -            typedefType: typedefType);
  +        return _readFunctionType();
         case Tag.SimpleFunctionType:
  -        int nullabilityIndex = readByte();
  -        List<DartType> positional = readDartTypeList();
  -        DartType returnType = readDartType();
  -        return new FunctionType(
  -            positional, returnType, Nullability.values[nullabilityIndex]);
  +        return _readSimpleFunctionType();
         case Tag.TypeParameterType:
  -        int declaredNullabilityIndex = readByte();
  -        int index = readUInt30();
  -        DartType bound = readDartTypeOption();
  -        return new TypeParameterType(typeParameterStack[index],
  -            Nullability.values[declaredNullabilityIndex], bound);
  +        return _readTypeParameterType();
         default:
           throw fail('unexpected dart type tag: $tag');
       }
  +  }
  +
  +  DartType _readTypedefType() {
  +    int nullabilityIndex = readByte();
  +    return new TypedefType.byReference(readTypedefReference(),
  +        Nullability.values[nullabilityIndex], readDartTypeList());
  +  }
  +
  +  DartType _readBottomType() {
  +    return const BottomType();
  +  }
  +
  +  DartType _readInvalidType() {
  +    return const InvalidType();
  +  }
  +
  +  DartType _readDynamicType() {
  +    return const DynamicType();
  +  }
  +
  +  DartType _readVoidType() {
  +    return const VoidType();
  +  }
  +
  +  DartType _readNeverType() {
  +    int nullabilityIndex = readByte();
  +    return new NeverType(Nullability.values[nullabilityIndex]);
  +  }
  +
  +  DartType _readInterfaceType() {
  +    int nullabilityIndex = readByte();
  +    Reference reference = readClassReference();
  +    List<DartType> typeArguments = readDartTypeList();
  +    CanonicalName canonicalName = reference.canonicalName;
  +    if (canonicalName.name == "FutureOr" &&
  +        canonicalName.parent != null &&
  +        canonicalName.parent.name == "dart:async" &&
  +        canonicalName.parent.parent != null &&
  +        canonicalName.parent.parent.isRoot) {
  +      return new FutureOrType(
  +          typeArguments.single, Nullability.values[nullabilityIndex]);
  +    }
  +    return new InterfaceType.byReference(
  +        reference, Nullability.values[nullabilityIndex], typeArguments);
  +  }
  +
  +  DartType _readSimpleInterfaceType(bool forSupertype) {
  +    int nullabilityIndex = readByte();
  +    Reference classReference = readClassReference();
  +    CanonicalName canonicalName = classReference.canonicalName;
  +    if (canonicalName != null &&
  +        !forSupertype &&
  +        canonicalName.name == "Null" &&
  +        canonicalName.parent?.name == "dart:core" &&
  +        (canonicalName.parent?.parent?.isRoot ?? false)) {
  +      return const NullType();
  +    }
  +    return new InterfaceType.byReference(classReference,
  +        Nullability.values[nullabilityIndex], const <DartType>[]);
  +  }
  +
  +  DartType _readFunctionType() {
  +    int typeParameterStackHeight = typeParameterStack.length;
  +    int nullabilityIndex = readByte();
  +    List<TypeParameter> typeParameters = readAndPushTypeParameterList();
  +    int requiredParameterCount = readUInt30();
  +    int totalParameterCount = readUInt30();
  +    List<DartType> positional = readDartTypeList();
  +    List<NamedType> named = readNamedTypeList();
  +    DartType typedefType = readDartTypeOption();
  +    assert(positional.length + named.length == totalParameterCount);
  +    DartType returnType = readDartType();
  +    typeParameterStack.length = typeParameterStackHeight;
  +    return new FunctionType(
  +        positional, returnType, Nullability.values[nullabilityIndex],
  +        typeParameters: typeParameters,
  +        requiredParameterCount: requiredParameterCount,
  +        namedParameters: named,
  +        typedefType: typedefType);
  +  }
  +
  +  DartType _readSimpleFunctionType() {
  +    int nullabilityIndex = readByte();
  +    List<DartType> positional = readDartTypeList();
  +    DartType returnType = readDartType();
  +    return new FunctionType(
  +        positional, returnType, Nullability.values[nullabilityIndex]);
  +  }
  +
  +  DartType _readTypeParameterType() {
  +    int declaredNullabilityIndex = readByte();
  +    int index = readUInt30();
  +    DartType bound = readDartTypeOption();
  +    return new TypeParameterType(typeParameterStack[index],
  +        Nullability.values[declaredNullabilityIndex], bound);
     }
   
     List<TypeParameter> readAndPushTypeParameterList(
  
positive.code:     int tag = readByte();
      switch (tag) {
        case Tag.ExpressionStatement:
          return new ExpressionStatement(readExpression());
        case Tag.Block:
          return readBlock();
        case Tag.AssertBlock:
          return readAssertBlock();
        case Tag.EmptyStatement:
          return new EmptyStatement();
        case Tag.AssertStatement:
          return new AssertStatement(readExpression(),
              conditionStartOffset: readOffset(),
              conditionEndOffset: readOffset(),
              message: readExpressionOption());
        case Tag.LabeledStatement:
          LabeledStatement label = new LabeledStatement(null);
          labelStack.add(label);
          label.body = readStatement()..parent = label;
          labelStack.removeLast();
          return label;
        case Tag.BreakStatement:
          int offset = readOffset();
          int index = readUInt30();
          return new BreakStatement(labelStack[labelStackBase + index])
            ..fileOffset = offset;
        case Tag.WhileStatement:
          int offset = readOffset();
          return new WhileStatement(readExpression(), readStatement())
            ..fileOffset = offset;
        case Tag.DoStatement:
          int offset = readOffset();
          return new DoStatement(readStatement(), readExpression())
            ..fileOffset = offset;
        case Tag.ForStatement:
          int variableStackHeight = variableStack.length;
          int offset = readOffset();
          List<VariableDeclaration> variables =
              readAndPushVariableDeclarationList();
          Expression condition = readExpressionOption();
          List<Expression> updates = readExpressionList();
          Statement body = readStatement();
          variableStack.length = variableStackHeight;
          return new ForStatement(variables, condition, updates, body)
            ..fileOffset = offset;
        case Tag.ForInStatement:
        case Tag.AsyncForInStatement:
          bool isAsync = tag == Tag.AsyncForInStatement;
          int variableStackHeight = variableStack.length;
          int offset = readOffset();
          int bodyOffset = readOffset();
          VariableDeclaration variable = readAndPushVariableDeclaration();
          Expression iterable = readExpression();
          Statement body = readStatement();
          variableStack.length = variableStackHeight;
          return new ForInStatement(variable, iterable, body, isAsync: isAsync)
            ..fileOffset = offset
            ..bodyOffset = bodyOffset;
        case Tag.SwitchStatement:
          int offset = readOffset();
          Expression expression = readExpression();
          int count = readUInt30();
          List<SwitchCase> cases =
              new List<SwitchCase>.filled(count, null, growable: true);
          for (int i = 0; i < count; ++i) {
            cases[i] = new SwitchCase.empty();
          }
          switchCaseStack.addAll(cases);
          for (int i = 0; i < cases.length; ++i) {
            readSwitchCaseInto(cases[i]);
          }
          switchCaseStack.length -= count;
          return new SwitchStatement(expression, cases)..fileOffset = offset;
        case Tag.ContinueSwitchStatement:
          int offset = readOffset();
          int index = readUInt30();
          return new ContinueSwitchStatement(
              switchCaseStack[switchCaseStackBase + index])
            ..fileOffset = offset;
        case Tag.IfStatement:
          int offset = readOffset();
          return new IfStatement(
              readExpression(), readStatement(), readStatementOrNullIfEmpty())
            ..fileOffset = offset;
        case Tag.ReturnStatement:
          int offset = readOffset();
          return new ReturnStatement(readExpressionOption())..fileOffset = offset;
        case Tag.TryCatch:
          Statement body = readStatement();
          int flags = readByte();
          return new TryCatch(body, readCatchList(), isSynthetic: flags & 2 == 2);
        case Tag.TryFinally:
          return new TryFinally(readStatement(), readStatement());
        case Tag.YieldStatement:
          int offset = readOffset();
          int flags = readByte();
          return new YieldStatement(readExpression(),
              isYieldStar: flags & YieldStatement.FlagYieldStar != 0,
              isNative: flags & YieldStatement.FlagNative != 0)
            ..fileOffset = offset;
        case Tag.VariableDeclaration:
          VariableDeclaration variable = readVariableDeclaration();
          variableStack.add(variable); // Will be popped by the enclosing scope.
          return variable;
        case Tag.FunctionDeclaration:
          int offset = readOffset();
          VariableDeclaration variable = readVariableDeclaration();
          variableStack.add(variable); // Will be popped by the enclosing scope.
          FunctionNode function = readFunctionNode();
          return new FunctionDeclaration(variable, function)..fileOffset = offset;
        default:
          throw fail('unexpected statement tag: $tag');
      }
    }
  
    void readSwitchCaseInto(SwitchCase caseNode) {
  
negative.code:     bool isSynthetic = readByte() == 1;
      switch (tag) {
        case Tag.InvalidInitializer:
          return _readInvalidInitializer();
        case Tag.FieldInitializer:
          return _readFieldInitializer(isSynthetic);
        case Tag.SuperInitializer:
          return _readSuperInitializer(isSynthetic);
        case Tag.RedirectingInitializer:
          return _readRedirectingInitializer();
        case Tag.LocalInitializer:
          return _readLocalInitializer();
        case Tag.AssertInitializer:
          return _readAssertInitializer();
        default:
          throw fail('unexpected initializer tag: $tag');
      }
    }
  
    Initializer _readInvalidInitializer() {
      return new InvalidInitializer();
    }
  
    Initializer _readFieldInitializer(bool isSynthetic) {
      Reference reference = readMemberReference();
      Expression value = readExpression();
      return new FieldInitializer.byReference(reference, value)
        ..isSynthetic = isSynthetic;
    }
  
    Initializer _readSuperInitializer(bool isSynthetic) {
      int offset = readOffset();
      Reference reference = readMemberReference();
      Arguments arguments = readArguments();
      return new SuperInitializer.byReference(reference, arguments)
        ..isSynthetic = isSynthetic
        ..fileOffset = offset;
    }
  
    Initializer _readRedirectingInitializer() {
      int offset = readOffset();
      return new RedirectingInitializer.byReference(
          readMemberReference(), readArguments())
        ..fileOffset = offset;
    }
  
    Initializer _readLocalInitializer() {
      return new LocalInitializer(readAndPushVariableDeclaration());
    }
  
    Initializer _readAssertInitializer() {
      return new AssertInitializer(readStatement());
    }
  
    FunctionNode readFunctionNodeOption(bool lazyLoadBody, int outerEndOffset) {
  