// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// TypeReferences are 'holes' in the generated JavaScript that are filled in by
/// the emitter with code to access a type.
///
/// The Dart code
///
///     foo1() => bar<int>(X<String>());
///
/// might be compiled to something like the following, with TypeReference1
/// referring to the constructed type `X<String>`, and TypeReference2 referring
/// to the method type argument `int`:
///
///     foo1: function() {
///       return bar(new X(TypeReference1), TypeReference2);
///     }
///
/// The dart method `foo2` would be compiled separately, with the generated code
/// containing TypeReference3 referring to `int`:
///
///     foo2() => bar<int>(null);
/// -->
///     foo2: function() {
///       return bar(null, TypeReference3);
///     }
///
/// When the code for an output unit (main unit or deferred loaded unit) is
/// assembled, there will also be a TypeReferenceResource 'hole', so the
/// assembled looks something like
///
///     foo: function() {
///       return bar(new X(TypeReference1), TypeReference2);
///     }
///     foo2: function() {
///       return bar(null, TypeReference3);
///     }
///     ...
///     TypeReferenceResource
///
/// The TypeReferenceFinalizer decides on a strategy for accessing the types. In
/// most cases it is best to precompute the types and access them via a
/// object. The TypeReference nodes are filled in with property access
/// expressions and the TypeReferenceResource is filled in with the precomputed
/// data, something like:
///
///     foo1: function() {
///       return bar(new X(type$.X_String), type$.int);
///     }
///     foo2: function() {
///       return bar(null, type$.int);
///     }
///     ...
///     var type$ = {
///       int: findType("int"),
///       X_String: findType("X<String>")
///     };
///
/// In minified mode, the properties `int` and `X_String` can be replaced by
/// shorter names.
library js_backend.type_reference;

import 'package:front_end/src/api_unstable/dart2js.dart'
    show $0, $9, $A, $Z, $_, $a, $z;

import '../common/elements.dart' show CommonElements;
import '../elements/types.dart';
import '../js/js.dart' as js;
import '../js_emitter/code_emitter_task.dart' show Emitter;
import '../js_model/type_recipe.dart'
    show
        TypeRecipe,
        TypeExpressionRecipe,
        SingletonTypeEnvironmentRecipe,
        FullTypeEnvironmentRecipe;
import '../serialization/serialization.dart';
import '../util/util.dart' show Hashing;
import 'frequency_assignment.dart';
import 'namer.dart';
import 'runtime_types_new.dart' show RecipeEncoder;

/// Run the minifier for 'type$' property names even in non-minified mode,
/// making a name from minified name and the readable name. Usage:
///
///     DART_VM_OPTIONS='-DDebugMinifyTypesHolder=true' dart2js ...
///
const _debugMinify = bool.fromEnvironment('DebugMinifyTypesHolder');

/// A [TypeReference] is a deferred JavaScript expression that refers to the
/// runtime representation of a ground type or ground type environment.  The
/// deferred expression is filled in by the TypeReferenceFinalizer which is
/// called from the fragment emitter. The replacement expression could be any
/// expression, e.g. a call, or a reference to a variable, or property of a
/// variable.
class TypeReference extends js.DeferredExpression implements js.AstContainer {
  static const String tag = 'type-reference';

  /// [typeRecipe] is a recipe for a ground type or type environment.
  final TypeRecipe typeRecipe;

  // TODO(sra): Refine the concept of reference context and replace the
  // 'forConstant' and 'forLazyInitializer' flags.

  // `true` if TypeReference is in code that initializes constant value.
  bool forConstant = false;

  // `true` if TypeReference is in code for a lazy initializer of a static
  // variable.
  bool forLazyInitializer = false;

  js.Expression _value;

  @override
  final js.JavaScriptNodeSourceInformation sourceInformation;

  TypeReference(this.typeRecipe) : sourceInformation = null;
  TypeReference._(this.typeRecipe, this._value, this.sourceInformation);

  factory TypeReference.readFromDataSource(DataSource source) {
    source.begin(tag);
    TypeRecipe recipe = source.readTypeRecipe();
    bool forLazyInitializer = source.readBool();
    source.end(tag);
    return TypeReference(recipe)..forLazyInitializer = forLazyInitializer;
  }

  void writeToDataSink(DataSink sink) {
    sink.begin(tag);
    sink.writeTypeRecipe(typeRecipe);
    sink.writeBool(forLazyInitializer);
    sink.end(tag);
  }

  set value(js.Expression value) {
    assert(!isFinalized && value != null);
    _value = value;
  }

  @override
  js.Expression get value {
    assert(isFinalized, 'TypeReference is unassigned');
    return _value;
  }

  @override
  bool get isFinalized => _value != null;

  // Precedence will be CALL or LEFT_HAND_SIDE depending on what expression the
  // reference is resolved to.
  @override
  int get precedenceLevel => value.precedenceLevel;

  @override
  TypeReference withSourceInformation(
      js.JavaScriptNodeSourceInformation newSourceInformation) {
    if (newSourceInformation == sourceInformation) return this;
    if (newSourceInformation == null) return this;
    return TypeReference._(typeRecipe, _value, newSourceInformation);
  }

  @override
  Iterable<js.Node> get containedNodes => isFinalized ? [_value] : const [];

  @override
  String nonfinalizedDebugText() {
    TypeRecipe typeRecipe = this.typeRecipe;
    if (typeRecipe is TypeExpressionRecipe) {
      return 'TypeReference"${typeRecipe.type.toString()}"';
    }
    return super.nonfinalizedDebugText();
  }
}

/// A [TypeReferenceResource] is a deferred JavaScript statement determined by
/// the finalization of type references. It is the injection point for data or
/// code to support type references. For example, if the
/// [TypeReferenceFinalizer] decides that type should be referred to via a
/// variable, the [TypeReferenceResource] would be set to code that declares and
/// initializes the variable.
class TypeReferenceResource extends js.DeferredStatement
    implements js.AstContainer {
  js.Statement _statement;

  @override
  final js.JavaScriptNodeSourceInformation sourceInformation;

  TypeReferenceResource() : sourceInformation = null;
  TypeReferenceResource._(this._statement, this.sourceInformation);

  set statement(js.Statement statement) {
    assert(!isFinalized && statement != null);
    _statement = statement;
  }

  @override
  js.Statement get statement {
    assert(isFinalized, 'TypeReferenceResource is unassigned');
    return _statement;
  }

  @override
  bool get isFinalized => _statement != null;

  @override
  TypeReferenceResource withSourceInformation(
      js.JavaScriptNodeSourceInformation newSourceInformation) {
    if (newSourceInformation == sourceInformation) return this;
    if (newSourceInformation == null) return this;
    return TypeReferenceResource._(_statement, newSourceInformation);
  }

  @override
  Iterable<js.Node> get containedNodes => isFinalized ? [_statement] : const [];

  @override
  void visitChildren<T>(js.NodeVisitor<T> visitor) {
    _statement?.accept<T>(visitor);
  }

  @override
  void visitChildren1<R, A>(js.NodeVisitor1<R, A> visitor, A arg) {
    _statement?.accept1<R, A>(visitor, arg);
  }
}

abstract class TypeReferenceFinalizer {
  /// Collects TypeReference and TypeReferenceResource nodes from the JavaScript
  /// AST [code];
  void addCode(js.Node code);

  /// Performs analysis on all collected TypeReference nodes finalizes the
  /// values to expressions to access the types.
  void finalize();
}

class TypeReferenceFinalizerImpl implements TypeReferenceFinalizer {
  final Emitter _emitter;
  final CommonElements _commonElements;
  final RecipeEncoder _recipeEncoder;
  final bool _minify;

  /*late final*/ _TypeReferenceCollectorVisitor _visitor;
  TypeReferenceResource _resource;

  /// Maps the recipe (type expression) to the references with the same recipe.
  /// Much of the algorithm's state is stored in the _ReferenceSet objects.
  final Map<TypeRecipe, _ReferenceSet> _referencesByRecipe = {};

  TypeReferenceFinalizerImpl(
      this._emitter, this._commonElements, this._recipeEncoder, this._minify) {
    _visitor = _TypeReferenceCollectorVisitor(this);
  }

  @override
  void addCode(js.Node code) {
    code.accept(_visitor);
  }

  @override
  void finalize() {
    assert(_resource != null, 'TypeReferenceFinalizer needs resource');
    _allocateNames();
    _updateReferences();
  }

  // Called from collector visitor.
  void _registerTypeReference(TypeReference node) {
    TypeRecipe recipe = node.typeRecipe;
    _ReferenceSet refs = _referencesByRecipe[recipe] ??= _ReferenceSet(recipe);
    refs.count++;
    if (node.forConstant) refs.countInConstant++;
    if (node.forLazyInitializer) refs.countInLazyInitializer++;
    refs._references.add(node);
  }

  // Called from collector visitor.
  void _registerTypeReferenceResource(TypeReferenceResource node) {
    assert(_resource == null);
    _resource = node;
  }

  void _updateReferences() {
    js.Expression helperAccess =
        _emitter.staticFunctionAccess(_commonElements.findType);

    js.Expression loadTypeCall(TypeRecipe recipe, String helperLocal) {
      js.Expression recipeExpression =
          _recipeEncoder.encodeGroundRecipe(_emitter, recipe);
      return js.js(r'#(#)', [helperLocal ?? helperAccess, recipeExpression]);
    }

    // Emit generate-at-use references.
    for (_ReferenceSet referenceSet in _referencesByRecipe.values) {
      if (referenceSet.generateAtUse) {
        TypeRecipe recipe = referenceSet.recipe;
        js.Expression reference = loadTypeCall(recipe, null);
        for (TypeReference ref in referenceSet._references) {
          ref.value = reference;
        }
      }
    }

    List<_ReferenceSet> referenceSetsUsingProperties =
        _referencesByRecipe.values.where((ref) => !ref.generateAtUse).toList();

    // Sort by name (which is unique and mostly stable) so that similar recipes
    // are grouped together.
    referenceSetsUsingProperties.sort((a, b) => a.name.compareTo(b.name));

    // We can generate a literal with calls to H.findType (minified to typically
    // e.g. H.xy) or cache H.findType in a local in a scope created by an IIFE.
    // Doing so saves 2-3 bytes per entry, but with an overhead of 30+ bytes for
    // the IIFE.  So it is smaller to use the IIFE only for over 10 or so types.
    const minUseIIFE = 10;
    String helperLocal =
        referenceSetsUsingProperties.length < minUseIIFE ? null : 'findType';

    List<js.Property> properties = [];
    for (_ReferenceSet referenceSet in referenceSetsUsingProperties) {
      TypeRecipe recipe = referenceSet.recipe;
      var propertyName = js.string(referenceSet.propertyName);
      properties
          .add(js.Property(propertyName, loadTypeCall(recipe, helperLocal)));
      var access = js.js('#.#', [typesHolderLocalName, propertyName]);
      for (TypeReference ref in referenceSet._references) {
        ref.value = access;
      }
    }

    if (properties.isEmpty) {
      _resource.statement = js.Block.empty();
    } else {
      js.Expression initializer =
          js.ObjectInitializer(properties, isOneLiner: false);
      if (helperLocal != null) {
        // A named IIFE helps attribute startup time in profiling.
        var function = js.js(r'function rtii(){var # = #; return #}',
            [js.VariableDeclaration(helperLocal), helperAccess, initializer]);
        initializer = js.js('#()', js.Parentheses(function));
      }
      _resource.statement = js.js.statement(r'var # = #',
          [js.VariableDeclaration(typesHolderLocalName), initializer]);
    }
  }

  // This is a top-level local name in the generated JavaScript top-level
  // function, so will be minified automatically. The name should not collide
  // with any other locals.
  static const typesHolderLocalName = r'type$';

  void _allocateNames() {
    // Filter out generate-at-use cases and allocate unique names to the rest.
    List<_ReferenceSet> referencesInTable = [];
    Set<String> usedNames = {};
    for (_ReferenceSet referenceSet in _referencesByRecipe.values) {
      // - If a type is used only once from a constant then the findType can be
      // a subexpression of constant since it will be evaluated exactly once and
      // need not be stored anywhere else.
      if (referenceSet.count == 1 && referenceSet.countInConstant == 1) {
        continue;
      }

      // - Lazy initializers are usually evaluated on demand and only once, so
      // it is worth deferrering evaluating the type references until the lazy
      // initializer is executed, provided it does not increase program
      // size too much.
      //
      // Assuming minification in a large program, the size for precomputed is
      //
      //     abc:f("TTT"),/*once*/ +  type$.abc/*N times*/
      //
      // i.e. 13 + 5N. The size for repeated generate-at-use is
      //
      //      H.lookupType("TTT") /*N times*/
      //
      // i.e. 10N. Repeated is smaller when 10N < 13+5N, or N < 2.6. Since we
      // get a startup benefit of not evaluating the type recipe, lets round
      // up. Note that we don't know the size of the recipe ("TTT" assumes an
      // infrequently referenced non-generic interface type), but if the recipe
      // is larger, it is in a string so the program has the same number of
      // tokens and the extra bytes will be parsed efficiently.
      const int maxRepeatedLookups = 3;

      if (referenceSet.countInLazyInitializer == referenceSet.count &&
          referenceSet.count <= maxRepeatedLookups) {
        continue;
      }

      // TODO(sra): There are other contexts that would be beneficial, e.g. a
      // type reference occuring only in a throw expression.

      String suggestedName = _RecipeToIdentifier().run(referenceSet.recipe);
      if (usedNames.contains(suggestedName)) {
        for (int i = 2; true; i++) {
          String next = '${suggestedName}_$i';
          if (usedNames.contains(next)) continue;
          suggestedName = next;
          break;
        }
      }
      usedNames.add(suggestedName);
      referenceSet.name = suggestedName;
      referencesInTable.add(referenceSet);
    }

    if (!_minify && !_debugMinify) {
      // For unminified code, use the characteristic names as property names.
      // TODO(sra): Some of these names are long. We could truncate the names
      // after the unique prefix.
      for (_ReferenceSet referenceSet in referencesInTable) {
        referenceSet.propertyName = referenceSet.name;
      }
      return;
    }

    // Step 2. Sort by frequency to arrange common entries have shorter property
    // names.
    List<_ReferenceSet> referencesByFrequency = referencesInTable.toList()
      ..sort((a, b) {
        assert(a.name != b.name);
        int r = b.count.compareTo(a.count); // Decreasing frequency.
        if (r != 0) return r;
        return a.name.compareTo(b.name); // Tie-break with characteristic name.
      });

    for (var referenceSet in referencesByFrequency) {
      referenceSet.hash = _hashCharacteristicString(referenceSet.name);
    }

    int hashOf(int index) => referencesByFrequency[index].hash;
    int countOf(int index) => referencesByFrequency[index].count;
    void assign(int index, String name) {
      if (_minify) {
        referencesByFrequency[index].propertyName = name;
      } else {
        var refSet = referencesByFrequency[index];
        refSet.propertyName = name + '_' + refSet.name;
      }
    }

    //naiveFrequencyAssignment(
    semistableFrequencyAssignment(referencesByFrequency.length,
        minifiedNameSequence(), hashOf, countOf, assign);
  }

  static int _hashCharacteristicString(String s) {
    int hash = 0;
    for (int i = 0; i < s.length; i++) {
      hash = Hashing.mixHashCodeBits(hash, s.codeUnitAt(i));
    }
    return hash;
  }

  /// Returns an infinite sequence of property names in increasing size.
  static Iterable<String> minifiedNameSequence() sync* {
    List<int> nextName = [$a];

    /// Increments the letter at [pos] in the current name. Also takes care of
    /// overflows to the left. Returns the carry bit, i.e., it returns `true`
    /// if all positions to the left have wrapped around.
    ///
    /// If [nextName] is initially 'a', this will generate the sequence
    ///
    ///     [a-zA-Z_]
    ///     [a-zA-Z_][0-9a-zA-Z_]
    ///     [a-zA-Z_][0-9a-zA-Z_][0-9a-zA-Z_]
    ///     ...
    bool incrementPosition(int pos) {
      bool overflow = false;
      if (pos < 0) return true;
      int value = nextName[pos];
      if (value == $9) {
        value = $a;
      } else if (value == $z) {
        value = $A;
      } else if (value == $Z) {
        value = $_;
      } else if (value == $_) {
        overflow = incrementPosition(pos - 1);
        value = (pos > 0) ? $0 : $a;
      } else {
        value++;
      }
      nextName[pos] = value;
      return overflow;
    }

    while (true) {
      yield String.fromCharCodes(nextName);
      if (incrementPosition(nextName.length - 1)) {
        nextName.add($0);
      }
    }
  }
}

/// Set of references to a single recipe.
class _ReferenceSet {
  final TypeRecipe recipe;

  // Number of times a TypeReference for [recipe] occurs in the tree-scan of the
  // JavaScript ASTs.
  int count = 0;

  // Number tree-scan occurrences in a constant initializer.
  int countInConstant = 0;
  // Number tree-scan occurrences in a static lazy initializer.
  int countInLazyInitializer = 0;

  // It is possible for the JavaScript AST to be a DAG, so collect
  // [TypeReference]s as set so we don't try to update one twice.
  final Set<TypeReference> _references = Set.identity();

  /// Characteristic name of the recipe - this can be used as a property name
  /// for emitting unminified code, and as a stable hash source for minified
  /// names.  [name] is `null` if [recipe] should always be generated at use.
  String name;

  /// Property name for 'indexing' into the precomputed types.
  String propertyName;

  /// A stable hash code that can be used for picking stable minified names.
  int hash = 0;

  _ReferenceSet(this.recipe);

  // If we don't assign a name it means we should not precompute the recipe.
  bool get generateAtUse => name == null;
}

/// Scans a JavaScript AST to collect all the TypeReference nodes.
///
/// The state is kept in the finalizer so that this scan could be extended to
/// look for other deferred expressions in one pass.
class _TypeReferenceCollectorVisitor extends js.BaseVisitorVoid {
  final TypeReferenceFinalizerImpl _finalizer;

  _TypeReferenceCollectorVisitor(this._finalizer);

  @override
  void visitNode(js.Node node) {
    assert(node is! TypeReference);
    assert(node is! TypeReferenceResource);
    if (node is js.AstContainer) {
      for (js.Node element in node.containedNodes) {
        element.accept(this);
      }
    } else {
      super.visitNode(node);
    }
  }

  @override
  void visitDeferredExpression(js.DeferredExpression node) {
    if (node is TypeReference) {
      _finalizer._registerTypeReference(node);
    } else {
      visitNode(node);
    }
  }

  @override
  void visitDeferredStatement(js.DeferredStatement node) {
    if (node is TypeReferenceResource) {
      _finalizer._registerTypeReferenceResource(node);
    } else {
      visitNode(node);
    }
  }
}

/// Returns a valid JavaScript identifier characterizing the recipe. The names
/// tend to look like the type expression with the non-identifier characters
/// removed.  Separators 'of' and 'and' are sometimes used to separate complex
/// types.
///
///     Map<int,int>        "Map_int_int"
///     Map<int,List<int>>  "Map_of_int_and_List_int"
///
///
/// For many common types the strings are unique, but this is not
/// guaranteed. This needs to be disambiguated at a higher level.
///
/// Different types can have the same string if the types contain different
/// interface types with the same name (i.e. from different libraries), or types
/// with names that contain underscores or dollar signs. There is also some
/// ambiguity in the generated names in the interest of keeping most names
/// short, e.g. "FutureOr_int_Function" could be "FutureOr<int> Function()" or
/// "FutureOr<int Function()>".
class _RecipeToIdentifier extends DartTypeVisitor<void, DartType> {
  final Map<DartType, int> _backrefs = Map.identity();
  final List<String> _fragments = [];

  String run(TypeRecipe recipe) {
    if (recipe is TypeExpressionRecipe) {
      _visit(recipe.type, null);
    } else if (recipe is SingletonTypeEnvironmentRecipe) {
      _add(r'$env');
      _visit(recipe.type, null);
    } else if (recipe is FullTypeEnvironmentRecipe) {
      _add(r'$env');
      if (recipe.classType != null) _visit(recipe.classType, null);
      _add('${recipe.types.length}');
      int index = 0;
      for (DartType type in recipe.types) {
        ++index;
        _add('${index}');
        _visit(type, null);
      }
    } else {
      throw StateError('Unexpected recipe: $recipe');
    }
    String result = _fragments.join('_');
    if (Namer.startsWithIdentifierCharacter(result)) return result;
    return 'z' + result;
  }

  void _add(String text) {
    _fragments.add(text);
  }

  void _identifier(String text) {
    _add(Namer.replaceNonIdentifierCharacters(text));
  }

  bool _comma(bool needsComma) {
    if (needsComma) _add('and');
    return true;
  }

  void _visit(DartType type, DartType parent) {
    type.accept(this, parent);
  }

  @override
  void visitLegacyType(covariant LegacyType type, _) {
    _add('legacy');
    _visit(type.baseType, type);
  }

  @override
  void visitNullableType(covariant NullableType type, _) {
    _add('nullable');
    _visit(type.baseType, type);
  }

  @override
  void visitNeverType(covariant NeverType type, _) {
    _add('Never');
  }

  @override
  void visitVoidType(covariant VoidType type, _) {
    _add('void');
  }

  @override
  void visitDynamicType(covariant DynamicType type, _) {
    _add('dynamic');
  }

  @override
  void visitErasedType(covariant ErasedType type, _) {
    _add('erased');
  }

  @override
  void visitAnyType(covariant AnyType type, _) {
    _add('any');
  }

  @override
  void visitTypeVariableType(covariant TypeVariableType type, DartType parent) {
    _identifier(type.element.typeDeclaration.name);
    _identifier(type.element.name);
  }

  @override
  void visitFunctionTypeVariable(covariant FunctionTypeVariable type, _) {
    int index = type.index;
    String name = index < 26 ? String.fromCharCode($A + index) : 'v\$${index}';
    _add(name);
  }

  @override
  void visitFunctionType(covariant FunctionType type, DartType parent) {
    if (_dagCheck(type)) return;

    _visit(type.returnType, type);
    _add('Function');
    var typeVariables = type.typeVariables;
    if (typeVariables.isNotEmpty) {
      bool needsComma = false;
      for (FunctionTypeVariable typeVariable in typeVariables) {
        needsComma = _comma(needsComma);
        _visit(typeVariable, type);
        DartType bound = typeVariable.bound;
        if (!bound.isObject) {
          _add('extends');
          _visit(typeVariable.bound, typeVariable);
        }
      }
    }
    var parameterTypes = type.parameterTypes;
    var optionalParameterTypes = type.optionalParameterTypes;
    var namedParameters = type.namedParameters;
    var requiredNamedParameters = type.requiredNamedParameters;

    if (optionalParameterTypes.isEmpty &&
        namedParameters.isEmpty &&
        parameterTypes.every(_isSimple)) {
      // e.g.  "void_Function_int_int"
      for (DartType parameterType in parameterTypes) {
        _visit(parameterType, type);
      }
      return;
    }
    if (parameterTypes.length > 1) {
      _add('${parameterTypes.length}');
    }
    bool needsComma = false;
    for (DartType parameterType in parameterTypes) {
      needsComma = _comma(needsComma);
      _visit(parameterType, type);
    }
    if (optionalParameterTypes.isNotEmpty) {
      _add(r'$opt');
      bool needsOptionalComma = false;
      for (DartType typeArgument in optionalParameterTypes) {
        needsOptionalComma = _comma(needsOptionalComma);
        _visit(typeArgument, type);
      }
    }
    if (namedParameters.isNotEmpty) {
      _add(r'$named');
      bool needsNamedComma = false;
      for (int index = 0; index < namedParameters.length; index++) {
        needsNamedComma = _comma(needsNamedComma);
        if (requiredNamedParameters.contains(namedParameters[index])) {
          _add(r'$req');
        }
        _identifier(namedParameters[index]);
        _visit(type.namedParameterTypes[index], type);
      }
    }
  }

  @override
  void visitInterfaceType(covariant InterfaceType type, _) {
    var arguments = type.typeArguments;

    // Don't bother DAG-checking (generating back-ref encodings) for interface
    // types which 'print' as a single identifier.
    if (arguments.isNotEmpty && _dagCheck(type)) return;

    _identifier(type.element.name);

    if (arguments.isEmpty) return;
    if (arguments.length == 1) {
      // e.g. "List_of_int_Function"
      if (arguments.first.withoutNullability is FunctionType) {
        _add('of');
      }
      // e.g. "List_int"
      _visit(arguments.first, type);
      return;
    }
    if (arguments.every(_isSimple)) {
      // e.g. "Map_String_String"
      for (DartType argument in arguments) {
        _visit(argument, type);
      }
      return;
    }
    // e.g "Map_of_String_and_int_Function"
    _add('of');
    bool needsComma = false;
    for (DartType argument in arguments) {
      needsComma = _comma(needsComma);
      _visit(argument, type);
    }
  }

  bool _dagCheck(DartType type) {
    int /*?*/ ref = _backrefs[type];
    if (ref != null) {
      _add('\$$ref');
      return true;
    }
    _backrefs[type] = _backrefs.length;
    return false;
  }

  /// Returns `true` for types which print as a single identifier.
  static bool _isSimple(DartType type) {
    return type is DynamicType ||
        type is VoidType ||
        type is AnyType ||
        (type is InterfaceType && type.typeArguments.isEmpty);
  }

  @override
  void visitFutureOrType(covariant FutureOrType type, _) {
    _identifier('FutureOr');
    _visit(type.typeArgument, type);
  }
}
