// 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.

// Generates the type tables used by DartFuzz.
//
// Usage:
//   dart gen_type_table.dart > dartfuzz_type_table.dart
//
// Reformat:
//   tools/sdks/dart-sdk/bin/dartfmt -w \
//   runtime/tools/dartfuzz/dartfuzz_type_table.dart
//
// Then send out modified dartfuzz_type_table.dart for review together
// with a modified dartfuzz.dart that increases the version.

import 'dart:io';
import 'dart:math';

import 'package:args/args.dart';

import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/element/element.dart';

import 'gen_util.dart';

// Minimum number of operators that are required for a type to be included in
// the type table.
final int operatorCountThreshold = 2;

//
// Operators and functions.
//

// Map type to a list of constructors names with a list of constructor
// parameter types.
Map<String, Map<String, List<String>>> constructors =
    new Map<String, Map<String, List<String>>>();

// Map type to a list of assignment operators with a set of the
// assignable right hand side types.
Map<String, Map<String, Set<String>>> assignOps =
    new Map<String, Map<String, Set<String>>>();

// Map type to a list of binary operators with set of the respective
// types for the first and second operand.
Map<String, Map<String, Set<List<String>>>> binOps =
    new Map<String, Map<String, Set<List<String>>>>();

// Map type to a list of available unary operators.
Map<String, Set<String>> uniOps = new Map<String, Set<String>>();

//
// Type grouping.
//

// All Set<E> types: SET_INT, SET_STRING, etc.
Set<String> setTypes = new Set<String>();

// All Map<K, V> types: MAP_INT_STRING, MAP_DOUBLE_BOOL, etc.
Set<String> mapTypes = new Set<String>();

// All List<E> types: LIST_INT, LIST_STRING, etc.
Set<String> listTypes = new Set<String>();

// All floating point types: DOUBLE, SET_DOUBLE, MAP_X_DOUBLE, etc.
Set<String> fpTypes = new Set<String>();

// All iterable types: Set types + List types.
// These can be used in for(x in <iterable type>),
// therefore Map is not included.
Set<String> iterableTypes1 = new Set<String>();

// All trivially indexable types: Map types and List types.
// Elements of these can be written and read by [], unlike Set
// which uses getElementAt to access individual elements
Set<String> indexableTypes = new Set<String>();

// Complex types: Collection types instantiated with nested argument
// e.g Map<List<>, >.
Set<String> complexTypes = new Set<String>();

//
// Type relations.
//

// Map type to the resulting type when subscripted.
// Example: List<String> subscripts to String.
Map<String, String> subscriptsTo = new Map<String, String>();

// Map type to a Set of types that contain it as an element.
// Example: String is element of List<String> and Map<int, String>
Map<String, Set<String>> elementOf = new Map<String, Set<String>>();

// Map type to a Set of types that contain it as an indexable element.
// Same as element of, but without Set types.
Map<String, Set<String>> indexableElementOf = new Map<String, Set<String>>();

// Map type to type required as index.
// Example: List<String> is indexed by int,
// Map<String, double> indexed by String.
Map<String, String> indexedBy = new Map<String, String>();

//
// Interface relationships.
//

// Map Interface type to Set of types that implement it.
// Example: interface num is implemented by int and double.
Map<String, Set<String>> interfaceRels = new Map<String, Set<String>>();

// Convert analyzer's displayName to constant name used by dartfuzz.
// Example: Set<int, String> -> SET_INT_STRING
String getConstName(String displayName) {
  String constName = displayName;
  constName = constName.replaceAll('<', '_');
  constName = constName.replaceAll('>', '');
  constName = constName.replaceAll(', ', '_');
  constName = constName.toUpperCase();
  return constName;
}

// Returns true if the given type fails the filter criteria.
bool shouldFilterType(String typName, {bool fp = true, bool flatTp = false}) {
  if (!fp && fpTypes.contains(typName)) {
    return true;
  }
  if (flatTp && complexTypes.contains(typName)) {
    return true;
  }
  return false;
}

// Returns true if any of the paramters in the list fails the
// filter criteria.
bool shouldFilterParameterList(List<String> parameters,
    {bool fp = true, bool flatTp = false}) {
  for (String parameter in parameters) {
    if (shouldFilterType(parameter, fp: fp, flatTp: flatTp)) {
      return true;
    }
  }
  return false;
}

// Filter a set of a list of parameters according to their type.
// A paramter list is only retained if all of the contained paramters
// pass the filter criteria.
Set<List<String>> filterParameterList(Set<List<String>> parameterList,
    {bool fp = true, bool flatTp = false}) {
  Set<List<String>> filteredParams = <List<String>>{};
  for (List<String> parameters in parameterList) {
    if (!shouldFilterParameterList(parameters, fp: fp, flatTp: flatTp)) {
      filteredParams.add(parameters);
    }
  }
  return filteredParams;
}

// Filter a set of parameters according to their type.
Set<String> filterParameterSet(Set<String> parameterSet,
    {bool fp = true, bool flatTp = false}) {
  Set<String> filteredParams = <String>{};
  for (String parameter in parameterSet) {
    if (!shouldFilterType(parameter, fp: fp, flatTp: flatTp)) {
      filteredParams.add(parameter);
    }
  }
  return filteredParams;
}

// Filter map of operators to a set of a list of parameter types
// as used for binary operators.
Map<String, Set<List<String>>> filterOperatorMapSetList(
    Map<String, Set<List<String>>> operators,
    {bool fp = true,
    bool flatTp = false}) {
  Map<String, Set<List<String>>> filteredOps = <String, Set<List<String>>>{};
  operators.forEach((op, parameterList) {
    Set<List<String>> filteredParams =
        filterParameterList(parameterList, fp: fp, flatTp: flatTp);
    if (filteredParams.isNotEmpty) {
      filteredOps[op] = filteredParams;
    }
  });
  return filteredOps;
}

// Filter map of operators to a List of parameter types as used for
// constructors.
Map<String, List<String>> filterOperatorMapList(
    Map<String, List<String>> operators,
    {bool fp = true,
    bool flatTp = false}) {
  Map<String, List<String>> filteredOps = <String, List<String>>{};
  operators.forEach((op, parameterList) {
    if (!shouldFilterParameterList(parameterList, fp: fp, flatTp: flatTp)) {
      filteredOps[op] = parameterList;
    }
  });
  return filteredOps;
}

// Filter map of operators to a set of rhs types as used for assignment
// operators.
Map<String, Set<String>> filterOperatorMapSet(
    Map<String, Set<String>> operators,
    {bool fp = true,
    bool flatTp = false}) {
  Map<String, Set<String>> filteredOps = <String, Set<String>>{};
  operators.forEach((op, parameterSet) {
    Set<String> filteredParams =
        filterParameterSet(parameterSet, fp: fp, flatTp: flatTp);
    if (filteredParams.isNotEmpty) {
      filteredOps[op] = filteredParams;
    }
  });
  return filteredOps;
}

// Filter map of type to map of operators as used for binary operators.
Map<String, Map<String, Set<List<String>>>> filterTypesMap4(
    Map<String, Map<String, Set<List<String>>>> types,
    {bool fp = true,
    bool flatTp = false}) {
  Map<String, Map<String, Set<List<String>>>> filteredTypes =
      <String, Map<String, Set<List<String>>>>{};
  types.forEach((baseType, ops) {
    if (shouldFilterType(baseType, fp: fp, flatTp: flatTp)) {
      return true;
    }
    Map<String, Set<List<String>>> filteredOps =
        filterOperatorMapSetList(ops, fp: fp, flatTp: flatTp);
    if (filteredOps.isNotEmpty) {
      filteredTypes[baseType] = filteredOps;
    }
  });
  return filteredTypes;
}

// Print map of type to map of operators as used for binary operators.
void printTypeMap4(
    String name, Map<String, Map<String, Set<List<String>>>> types,
    {bool fp = true, bool flatTp = false}) {
  final bool subclass = !fp || flatTp;
  final String prefix = "${subclass ? "DartType." : ""}";
  print("  static const Map<DartType, Map<String, " +
      "Set<List<DartType>>>> ${name} = {");
  Map<String, Map<String, Set<List<String>>>> filteredTypes =
      filterTypesMap4(types, fp: fp, flatTp: flatTp);
  for (var baseType in filteredTypes.keys.toList()..sort()) {
    var ops = filteredTypes[baseType];
    print("    ${prefix}${baseType}: {");
    for (var op in ops.keys.toList()..sort()) {
      var paramTypeL = ops[op];
      print("      '${op}': {");
      for (var paramTypes in paramTypeL) {
        stdout.write("          [");
        for (String paramType in paramTypes) {
          stdout.write("${prefix}${paramType}, ");
        }
        print("],");
      }
      print("        },");
    }
    print("    },");
  }
  print("  };");
}

// Filter map of type to map of operators as used for assignment operators.
Map<String, Map<String, Set<String>>> filterTypesMap3Set(
    Map<String, Map<String, Set<String>>> types,
    {bool fp = true,
    bool flatTp = false}) {
  Map<String, Map<String, Set<String>>> filteredTypes =
      <String, Map<String, Set<String>>>{};
  types.forEach((baseType, ops) {
    if (shouldFilterType(baseType, fp: fp, flatTp: flatTp)) {
      return true;
    }
    Map<String, Set<String>> filteredOps =
        filterOperatorMapSet(ops, fp: fp, flatTp: flatTp);
    if (filteredOps.isNotEmpty) {
      filteredTypes[baseType] = filteredOps;
    }
  });
  return filteredTypes;
}

// Print map of type to map of operators as used for assignment operators.
void printTypeMap3Set(String name, Map<String, Map<String, Set<String>>> types,
    {bool fp = true, bool flatTp = false}) {
  final bool subclass = !fp || flatTp;
  final String prefix = "${subclass ? "DartType." : ""}";
  print("  static const Map<DartType, " +
      "Map<String, Set<DartType>>> ${name} = {");

  Map<String, Map<String, Set<String>>> filteredTypes =
      filterTypesMap3Set(types, fp: fp, flatTp: flatTp);
  for (var baseType in filteredTypes.keys.toList()..sort()) {
    var ops = filteredTypes[baseType];
    print("    ${prefix}${baseType}: {");
    for (var op in ops.keys.toList()) {
      var paramTypes = ops[op];
      stdout.write("      '${op}': {");
      for (String paramType in paramTypes.toList()..sort()) {
        stdout.write("${prefix}${paramType}, ");
      }
      print("}, ");
    }
    print("    },");
  }
  print("  };");
}

// Filter map of type to map of operators as used for constructors.
Map<String, Map<String, List<String>>> filterTypesMap3(
    Map<String, Map<String, List<String>>> types,
    {bool fp = true,
    bool flatTp = false}) {
  Map<String, Map<String, List<String>>> filteredTypes =
      <String, Map<String, List<String>>>{};
  types.forEach((baseType, ops) {
    if (shouldFilterType(baseType, fp: fp, flatTp: flatTp)) {
      return true;
    }
    Map<String, List<String>> filteredOps =
        filterOperatorMapList(ops, fp: fp, flatTp: flatTp);
    if (filteredOps.isNotEmpty) {
      filteredTypes[baseType] = filteredOps;
    }
  });
  return filteredTypes;
}

// Print map of type to map of operators as used for constructors.
void printTypeMap3(String name, Map<String, Map<String, List<String>>> types,
    {bool fp = true, bool flatTp = false}) {
  final bool subclass = !fp || flatTp;
  final String prefix = "${subclass ? "DartType." : ""}";
  print("  static const Map<DartType, Map<String, " +
      "List<DartType>>> ${name} = {");
  var filteredTypes = filterTypesMap3(types, fp: fp, flatTp: flatTp);
  for (var baseType in filteredTypes.keys.toList()..sort()) {
    var ops = filteredTypes[baseType];
    print("    ${prefix}${baseType}: {");
    for (var op in ops.keys.toList()..sort()) {
      var paramTypes = ops[op];
      stdout.write("      '${op}': [");
      for (String paramType in paramTypes.toList()..sort()) {
        stdout.write("${prefix}${paramType}, ");
      }
      print("], ");
    }
    print("    },");
  }
  print("  };");
}

// Filter map of type collection name to set of types.
Map<String, Set<String>> filterTypesMap2(Map<String, Set<String>> types,
    {bool fp = true, bool flatTp = false}) {
  Map<String, Set<String>> filteredTypes = <String, Set<String>>{};
  types.forEach((baseType, parameterSet) {
    if (shouldFilterType(baseType, fp: fp, flatTp: flatTp)) {
      return true;
    }
    Set<String> filteredParams =
        filterParameterSet(parameterSet, fp: fp, flatTp: flatTp);
    if (filteredParams.isNotEmpty) {
      filteredTypes[baseType] = filteredParams;
    }
  });
  return filteredTypes;
}

// Print map of type collection name to set of types.
void printTypeMap2(String name, Map<String, Set<String>> types,
    {bool fp = true, bool flatTp = false}) {
  final bool subclass = !fp || flatTp;
  final String prefix = "${subclass ? "DartType." : ""}";
  print("  static const Map<DartType, Set<DartType>> ${name} = {");
  var filteredTypes = filterTypesMap2(types, fp: fp, flatTp: flatTp);
  for (var baseType in filteredTypes.keys.toList()..sort()) {
    var paramTypes = filteredTypes[baseType];
    stdout.write("    ${prefix}${baseType}: { ");
    for (String paramType in paramTypes.toList()..sort()) {
      stdout.write("${prefix}${paramType}, ");
    }
    print("},");
  }
  print("  };");
}

// Filter map of type to type.
Map<String, String> filterTypesMap1(Map<String, String> types,
    {bool fp = true, bool flatTp = false}) {
  Map<String, String> filteredTypes = <String, String>{};
  types.forEach((baseType, paramType) {
    if (shouldFilterType(baseType, fp: fp, flatTp: flatTp)) {
      return true;
    }
    if (shouldFilterType(paramType, fp: fp, flatTp: flatTp)) {
      return true;
    }
    filteredTypes[baseType] = paramType;
  });
  return filteredTypes;
}

// Print map of type to type.
void printTypeMap1(String name, Map<String, String> types,
    {bool fp = true, bool flatTp = false}) {
  final bool subclass = !fp || flatTp;
  final String prefix = "${subclass ? "DartType." : ""}";
  print("  static const Map<DartType, DartType> ${name} = {");
  var filteredTypes = filterTypesMap1(types, fp: fp, flatTp: flatTp);
  for (var baseType in filteredTypes.keys.toList()..sort()) {
    var paramType = filteredTypes[baseType];
    print("    ${prefix}"
        "${baseType}: ${prefix}${paramType}, ");
  }
  print("  };");
}

// Filter set of types.
Set<String> filterTypesSet(Set<String> choices,
    {bool fp = true, bool flatTp = false}) {
  Set<String> filteredTypes = {};
  filteredTypes.addAll(choices);
  if (!fp) {
    filteredTypes = filteredTypes.difference(fpTypes);
  }
  if (flatTp) {
    filteredTypes = filteredTypes.difference(complexTypes);
  }
  return filteredTypes;
}

// Print set of types.
void printTypeSet(String name, Set<String> types,
    {bool fp = true, bool flatTp = false}) {
  final bool subclass = !fp || flatTp;
  final String prefix = "${subclass ? "DartType." : ""}";
  stdout.write("  static const Set<DartType> ${name} = {");
  for (String typName in filterTypesSet(types, fp: fp, flatTp: flatTp).toList()
    ..sort()) {
    stdout.write("${prefix}$typName, ");
  }
  print("};");
}

// Filter map to type to set of operators as used for unitary operators.
Map<String, Set<String>> filterTypeMapSet(Map<String, Set<String>> types,
    {bool fp = true, bool flatTp = false}) {
  Map<String, Set<String>> filteredTypes = <String, Set<String>>{};
  types.forEach((baseType, params) {
    if (shouldFilterType(baseType, fp: fp, flatTp: flatTp)) {
      return true;
    }
    filteredTypes[baseType] = params;
  });
  return filteredTypes;
}

// Print map to type to set of operators as used for unitary operators.
void printTypeMapSet(String name, Map<String, Set<String>> types,
    {bool fp = true, bool flatTp = false}) {
  final bool subclass = !fp || flatTp;
  final String prefix = "${subclass ? "DartType." : ""}";
  print("  static const Map<DartType, Set<String>> $name = {");
  var filteredTypes = filterTypeMapSet(types, fp: fp, flatTp: flatTp);
  for (var baseType in filteredTypes.keys.toList()..sort()) {
    var paramTypes = filteredTypes[baseType].toList()..sort();
    print("    ${prefix}${baseType}: {" + paramTypes.join(", ") + "},");
  }
  print("  };");
}

// Print all generated and collected types, operators and type collections.
void printTypeTable(Set<InterfaceType> allTypes,
    {bool fp = true, bool flatTp = false}) {
  final bool subclass = !fp || flatTp;
  if (!subclass) {
    print("""
// 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.

/// Class that represents some common Dart types.
///
/// NOTE: this code has been generated automatically.
///""");
  }

  String className = 'DartType${fp ? "" : "NoFp"}${flatTp ? "FlatTp" : ""}';

  print('class $className'
      '${subclass ? " extends DartType" : ""} {');
  print("  final String name;");
  if (!subclass) {
    print("  const DartType._withName(this.name);");
    print("""
  factory $className.fromDartConfig(
      {bool enableFp = false, bool disableNesting =
    false}) {
    if (enableFp && !disableNesting) {
      return DartType();
    } else if (!enableFp && !disableNesting) {
      return DartTypeNoFp();
    } else if (enableFp && disableNesting) {
      return DartTypeFlatTp();
    } else {
      return DartTypeNoFpFlatTp();
    }
  }""");
  } else {
    print('  const $className'
        '._withName(this.name) : super._withName(name);');
  }

  print("""
  const $className() : name = null;
  static bool isListType(DartType tp) {
    return DartType._listTypes.contains(tp);
  }

  static bool isMapType(DartType tp) {
    return DartType._mapTypes.contains(tp);
  }

  static bool isCollectionType(DartType tp) {
    return DartType._collectionTypes.contains(tp);
  }

  static bool isGrowableType(DartType tp) {
    return DartType._growableTypes.contains(tp);
  }

  static bool isComplexType(DartType tp) {
    return DartType._complexTypes.contains(tp);
  }

  bool isInterfaceOfType(DartType tp, DartType iTp) {
    return _interfaceRels.containsKey(iTp) && _interfaceRels[iTp].contains(tp);
  }

  Set<DartType> get mapTypes {
    return _mapTypes;
  }

  bool isSpecializable(DartType tp) {
    return _interfaceRels.containsKey(tp);
  }

  Set<DartType> interfaces(DartType tp) {
    if (_interfaceRels.containsKey(tp)) {
      return _interfaceRels[tp];
    }
    return null;
  }

  DartType indexType(DartType tp) {
    if (_indexedBy.containsKey(tp)) {
      return _indexedBy[tp];
    }
    return null;
  }

  Set<DartType> indexableElementTypes(DartType tp) {
    if (_indexableElementOf.containsKey(tp)) {
      return _indexableElementOf[tp];
    }
    return null;
  }

  bool isIndexableElementType(DartType tp) {
    return _indexableElementOf.containsKey(tp);
  }

  DartType elementType(DartType tp) {
    if (_subscriptsTo.containsKey(tp)) {
      return _subscriptsTo[tp];
    }
    return null;
  }

  Set<DartType> get iterableTypes1 {
    return _iterableTypes1;
  }

  Set<String> uniOps(DartType tp) {
    if (_uniOps.containsKey(tp)) {
      return _uniOps[tp];
    }
    return <String>{};
  }

  Set<String> binOps(DartType tp) {
    if (_binOps.containsKey(tp)) {
      return _binOps[tp].keys.toSet();
    }
    return <String>{};
  }

  Set<List<DartType>> binOpParameters(DartType tp, String op) {
    if (_binOps.containsKey(tp) &&
        _binOps[tp].containsKey(op)) {
      return _binOps[tp][op];
    }
    return null;
  }

  Set<String> assignOps(DartType tp) {
    if (_assignOps.containsKey(tp)) {
      return _assignOps[tp].keys.toSet();
    }
    return <String>{};
  }

  Set<DartType> assignOpRhs(DartType tp, String op) {
    if (_assignOps.containsKey(tp) &&
        _assignOps[tp].containsKey(op)) {
      return _assignOps[tp][op];
    }
    return <DartType>{};
  }

  bool hasConstructor(DartType tp) {
    return _constructors.containsKey(tp);
  }

  Set<String> constructors(DartType tp) {
    if (_constructors.containsKey(tp)) {
      return _constructors[tp].keys.toSet();
    }
    return <String>{};
  }

  List<DartType> constructorParameters(DartType tp, String constructor) {
    if (_constructors.containsKey(tp) &&
        _constructors[tp].containsKey(constructor)) {
      return _constructors[tp][constructor];
    }
    return null;
  }

  Set<DartType> get allTypes {
    return _allTypes;
  }

""");

  Set<String> instTypes = {};

  // Generate one static DartType instance for all instantiable types.
  // TODO (felih): maybe add void type?
  allTypes.forEach((baseType) {
    String constName = getConstName(baseType.displayName);
    instTypes.add(constName);
    if (!subclass) {
      print("  static const ${constName} = const " +
          "DartType._withName(\"${baseType.displayName}\");");
    }
  });

  if (!subclass) {
    // Generate one static DartType instance for all non instantiable types.
    // These are required to resolve interface relations, but should not be
    // used directly to generate dart programs.
    print("");
    print("  // NON INSTANTIABLE" "");
    interfaceRels.keys.forEach((constName) {
      if (instTypes.contains(constName)) return true;
      print("  static const ${constName} = const " +
          "DartType._withName(\"__${constName}\");");
    });
  }

  // Generate a list of all instantiable types.
  print("");
  print("""
  // All types extracted from analyzer.
  static const _allTypes = {""");
  filterTypesSet(instTypes, fp: fp, flatTp: flatTp).forEach((constName) {
    print("    ${subclass ? "DartType." : ""}${constName},");
  });
  print("  };");

  print("");
  print("""
  // All List<E> types: LIST_INT, LIST_STRING, etc.""");
  printTypeSet("_listTypes", listTypes, fp: fp, flatTp: flatTp);

  print("");
  print("""
  // All Set types: SET_INT, SET_STRING, etc.""");
  printTypeSet("_setTypes", setTypes, fp: fp, flatTp: flatTp);

  print("");
  print("""
  // All Map<K, V> types: MAP_INT_STRING, MAP_DOUBLE_BOOL, etc.""");
  printTypeSet("_mapTypes", mapTypes, fp: fp, flatTp: flatTp);

  print("");
  print("""
  // All collection types: list, map and set types.""");
  printTypeSet("_collectionTypes", {...listTypes, ...setTypes, ...mapTypes},
      fp: fp, flatTp: flatTp);

  print("");
  print("""
  // All growable types: list, map, set and string types.""");
  printTypeSet(
      "_growableTypes", {...listTypes, ...setTypes, ...mapTypes, 'STRING'},
      fp: fp, flatTp: flatTp);

  if (!subclass) {
    print("");
    print(
        "  // All floating point types: DOUBLE, SET_DOUBLE, MAP_X_DOUBLE, etc.");
    printTypeSet("_fpTypes", fpTypes);
  }

  print("");
  print("""
  // All trivially indexable types: Map types and List types.
  // Elements of these can be written and read by [], unlike Set
  // which uses getElementAt to access individual elements.""");
  printTypeSet("_indexableTypes", indexableTypes, fp: fp, flatTp: flatTp);

  print("");
  print("""
  // Map type to the resulting type when subscripted.
  // Example: List<String> subscripts to String.""");
  printTypeMap1("_subscriptsTo", subscriptsTo, fp: fp, flatTp: flatTp);

  print("");
  print("""
  // Map type to type required as index.
  // Example: List<String> is indexed by int,
  // Map<String, double> indexed by String.""");
  printTypeMap1("_indexedBy", indexedBy, fp: fp, flatTp: flatTp);

  print("");
  print("""
  // Map type to a Set of types that contain it as an element.
  // Example: String is element of List<String> and Map<int, String>""");
  printTypeMap2("_elementOf", elementOf, fp: fp, flatTp: flatTp);

  print("");
  print("""
  // Map type to a Set of types that contain it as an indexable element.
  // Same as element of, but without Set types.""");
  printTypeMap2("_indexableElementOf", indexableElementOf,
      fp: fp, flatTp: flatTp);

  print("");
  print("""
  // All iterable types: Set types + List types.
  // These can be used in for(x in <iterable type>),
  // therefore Map is not included.""");
  printTypeSet("_iterableTypes1", iterableTypes1, fp: fp, flatTp: flatTp);

  if (!subclass) {
    print("");
    print("""
  // Complex types: Collection types instantiated with nested argument
  // e.g Map<List<>, >.""");
    printTypeSet("_complexTypes", complexTypes);
  }

  print("");
  print("""
  // Map Interface type to Set of types that implement it.
  // Example: interface num is implemented by int and double.""");
  printTypeMap2("_interfaceRels", interfaceRels, fp: fp, flatTp: flatTp);

  print("");
  print("""
  // Map type to a list of constructors names with a list of constructor
  // parameter types.""");
  printTypeMap3("_constructors", constructors, fp: fp, flatTp: flatTp);

  print("");
  print("""
  // Map type to a list of binary operators with set of the respective
  // types for the first and second operand.""");
  printTypeMap4("_binOps", binOps, fp: fp, flatTp: flatTp);

  print("");
  print("""
  // Map type to a list of available unary operators.""");
  printTypeMapSet("_uniOps", uniOps, fp: fp, flatTp: flatTp);

  print("");
  print("""
  // Map type to a list of assignment operators with a set of the
  // assignable right hand side types.""");
  printTypeMap3Set("_assignOps", assignOps, fp: fp, flatTp: flatTp);

  print("}");
  print("");
}

// Returns true if type can be set and get via [].
bool isIndexable(InterfaceType tp) {
  bool isIndexable = false;
  for (var method in tp.methods) {
    if (method.name == "[]") {
      isIndexable = true;
      break;
    }
  }
  return isIndexable;
}

// Returns true if iTypeName == typeName or if
// iTypeName is an interface type that is implemented by typeName.
// List<int> is interface of Int8List
bool isInterfaceOf(String iTypName, String typName) {
  return iTypName == typName ||
      (interfaceRels.containsKey(iTypName) &&
          interfaceRels[iTypName].contains(typName));
}

// Filter operator parameters so that the more specific types are discarded if
// the respective interface type is already in the list.
// This is required not only to give each parameter type equal probability but
// also so that dartfuzz can efficiently filter floating point types from the
// interface relations.
Set<List<String>> filterOperator(Set<List<String>> op) {
  Set<List<String>> newOp = new Set<List<String>>();
  if (op.length < 2) return op;
  for (List<String> params1 in op) {
    bool keep = false;
    for (List<String> params2 in op) {
      for (int k = 0; k < params1.length; ++k) {
        if (!isInterfaceOf(params2[k], params1[k])) {
          keep = true;
          break;
        }
      }
      if (keep) break;
    }
    if (keep) {
      newOp.add(params1);
    }
  }
  return newOp;
}

// See comment on filterOpterator.
void filterOperators(Set<InterfaceType> allTypes) {
  for (InterfaceType tp in allTypes) {
    String typName = getConstName(tp.displayName);
    if (!binOps.containsKey(typName)) continue;
    for (String op in binOps[typName].keys) {
      binOps[typName][op] = filterOperator(binOps[typName][op]);
    }
  }
}

// Extract all binary and unary operators for tp.
// Operators are stored by return type in the following way:
// return type: { operator: { parameter types } }
// Example: bool: { == : { [int, int], [double, double] }}
//          int: {'~', '-'},
// Does not recurse into interfaces and superclasses of tp.
void getOperatorsForTyp(String typName, InterfaceType tp, fromLiteral) {
  for (MethodElement method in tp.methods) {
    // Detect whether tp can be parsed from a literal (dartfuzz.dart can
    // already handle that).
    // This is usually indicated by the presence of the static constructor
    // 'castFrom' or 'parse'.
    if (method.isStatic &&
        (method.name == 'castFrom' || method.name == 'parse')) {
      fromLiteral.add(getConstName(tp.displayName));
    }
    // Hack: dartfuzz.dart already handles subscripts, therefore we exclude
    // them from the generated type table.
    if (method.name.startsWith('[]')) continue;
    if (method.isOperator) {
      // TODO (felih): Include support for type 'dynamic'.
      bool skip = false;
      for (var p in method.parameters) {
        if (getConstName(p.type.displayName) == 'DYNAMIC') {
          skip = true;
          break;
        }
      }
      if (skip) continue;
      if (method.parameters.length == 1) {
        // Get binary operators.

        String retTypName = getConstName(method.returnType.displayName);
        binOps[retTypName] ??= new Map<String, Set<List<String>>>();
        binOps[retTypName][method.name] ??= new Set<List<String>>();

        String rhsTypName = getConstName(method.parameters[0].type.displayName);

        // TODO (felih): no hashing for List<String> ?
        // if i remove this test i will get duplicates even though it is a Set.
        bool present = false;
        for (List<String> o in binOps[retTypName][method.name]) {
          if (o[0] == typName && o[1] == rhsTypName) {
            present = true;
            break;
          }
        }
        if (!present)
          binOps[retTypName][method.name].add([typName, rhsTypName]);

        // Add some assignment operators corresponding to the binary operators.
        // Example: for '+' add '+='.
        // Bool types have to be filtered because boolean binary operators
        // can not be used to derive assignment operators in this way, e.g.
        // <= is not a valid assignment operator for bool types.
        if (retTypName != 'BOOL') {
          assignOps[retTypName] ??= new Map<String, Set<String>>();
          String ao = method.name + '=';
          assignOps[retTypName][ao] ??= new Set<String>();
          assignOps[retTypName][ao].add(rhsTypName);
        }
      } else {
        // Get unary operators.
        uniOps[typName] ??= new Set<String>();
        String uo = method.name;
        // Hack: remove unary from operator so that the operator name can be
        // used directly for source code generation.
        if (uo.startsWith('unary')) uo = '-';
        uniOps[typName].add('\'$uo\'');
      }
    }
  }
}

// Extract all binary and unary operators for all types.
void getOperators(Set<InterfaceType> allTypes) {
  // Set of types that can be constructed directly from literals and do
  // not need special constructors (e.g. List<int> = [1, 2] as opposed to
  // Int8List int8list = Int8List.fromList([1, 2]) ).
  Set<String> fromLiteral = new Set<String>();

  // getOperatorsForTyp uses a heuristic to detect which types can be
  // constructed from a literal, but the heuristic misses the String type
  // so we have to add it manually.
  fromLiteral.add('STRING');
  // Get binary, unary and assignment operators.
  for (InterfaceType tp in allTypes) {
    String typName = getConstName(tp.displayName);
    // Manually add basic assignment operators which each type supports.
    assignOps[typName] ??= new Map<String, Set<String>>();
    assignOps[typName]['='] = {typName};
    assignOps[typName]['??='] = {typName};
    getOperatorsForTyp(typName, tp, fromLiteral);
  }

  // Add some static ops not extractable from dart:core/typed_data.
  for (String typName in binOps.keys) {
    binOps[typName] ??= new Map<String, Set<List<String>>>();
    binOps[typName]['??'] = {
      [typName, typName],
    };
  }
  binOps['BOOL'] ??= new Map<String, Set<List<String>>>();
  binOps['BOOL']['&&'] = {
    ['BOOL', 'BOOL'],
  };
  binOps['BOOL']['||'] = {
    ['BOOL', 'BOOL'],
  };
  uniOps['BOOL'] ??= new Set<String>();
  uniOps['BOOL'].add('\'!\'');

  // Get constructors.
  for (InterfaceType tp in allTypes) {
    String typName = getConstName(tp.displayName);
    // Skip types that are constructable from a literal.
    if (fromLiteral.contains(typName)) {
      continue;
    }
    for (ConstructorElement constructor in tp.constructors) {
      if (constructor.name.startsWith('_')) continue;
      List<String> params = new List<String>();
      bool canConstruct = true;
      for (var p in constructor.parameters) {
        String tstr = getConstName(p.type.displayName);
        // Only allow trivially constructable parameters. If a constructor
        // parameter is not constructable from a literal, skip the constructor.
        if (!fromLiteral.contains(tstr)) {
          canConstruct = false;
          break;
        }
        // Only add positional required parameters.
        // TODO (felih): include named and optional parameters.
        if (!p.isNamed) params.add(tstr);
      }
      if (!canConstruct) continue;

      constructors[typName] ??= new Map<String, List<String>>();
      constructors[typName][constructor.name] = params;
    }
  }
  // Removed redundant specialized parameter types.
  // E.g. if num is already contained remove bool and int.
  filterOperators(allTypes);
}

// Analyze types to extract element and subscript relations
// as well as precision type attributes.
void analyzeTypes(Set<InterfaceType> allTypes) {
  // Extract basic floating point types.
  for (InterfaceType tp in allTypes) {
    if (tp.displayName.contains('Float') ||
        tp.displayName.contains('float') ||
        tp.displayName.contains('double') ||
        tp.displayName.contains('Double'))
      fpTypes.add(getConstName(tp.displayName));
  }

  // Analyze all types to extract information useful for dart code generation.
  for (InterfaceType tp in allTypes) {
    final typName = getConstName(tp.displayName);

    // Find topmost interface type, e.g. List<int> is interface for Int8List.
    InterfaceType iTyp = tp;
    while (iTyp.typeArguments.isEmpty && !iTyp.interfaces.isEmpty) {
      iTyp = tp.interfaces[0];
    }

    // Group current type with their respective type group.
    if (iTyp.name == "Set") setTypes.add(typName);
    if (iTyp.name == "List") listTypes.add(typName);
    if (iTyp.name == "Map") mapTypes.add(typName);

    if (iTyp.typeArguments.length == 1) {
      // Analyze Array, List and Set types.
      String argName = getConstName(iTyp.typeArguments[0].displayName);
      subscriptsTo[typName] = argName;
      elementOf[argName] ??= new Set<String>();
      elementOf[argName].add(typName);
      if (isIndexable(iTyp)) {
        indexableElementOf[argName] ??= new Set<String>();
        indexableElementOf[argName].add(typName);
        indexedBy[typName] = 'INT';
        indexableTypes.add(typName);
      }
      // Check if type is floating point precision.
      if (fpTypes.contains(typName) || fpTypes.contains(argName)) {
        fpTypes.add(typName);
      }
    } else if (iTyp.typeArguments.length == 2) {
      // Analyze Map types.
      String argName0 = getConstName(iTyp.typeArguments[0].displayName);
      String argName1 = getConstName(iTyp.typeArguments[1].displayName);
      subscriptsTo[typName] = argName1;
      elementOf[argName1] ??= new Set<String>();
      elementOf[argName1].add(typName);
      indexableElementOf[argName1] ??= new Set<String>();
      indexableElementOf[argName1].add(typName);
      indexedBy[typName] = argName0;
      indexableTypes.add(typName);
      // Check if type is floating point precision.
      if (fpTypes.contains(typName) ||
          fpTypes.contains(argName0) ||
          fpTypes.contains(argName1)) {
        fpTypes.add(typName);
      }
    }
  }
}

// Split types into sets of types with none, one and two parameters
// respectively.
void getParameterizedTypes(
    Set<InterfaceType> allTypes, // Set of all types.
    Set<InterfaceType> pTypes1, // Out: types with one parameter e.g. List.
    Set<InterfaceType> pTypes2, // Out: types with two parameters e.g. Map.
    Set<InterfaceType> iTypes) {
  // Out: types with no parameters.
  for (var tp in allTypes) {
    if (tp.typeArguments.length == 1 && tp.typeArguments[0].name == 'E')
      pTypes1.add(tp);
    else if (tp.typeArguments.length == 2 &&
        tp.typeArguments[0].name == 'K' &&
        tp.typeArguments[1].name == 'V')
      pTypes2.add(tp);
    else
      iTypes.add(tp);
  }
}

// Generate new types by instantiating types with one and two parameters
// with the types having no parameters (or the parameters of which have
// already been instantiated).
// There will be no more then maxNew types generated.
Set<InterfaceType> instantiatePTypes(
    Set<InterfaceType> pTypes1, // Types with one parameter.
    Set<InterfaceType> pTypes2, // Types with two parameters.
    Set<InterfaceType> iTypes, // Types with no parameters.
    {double maxNew = 64.0}) {
  // Maximum number of newly generated types.
  Set<InterfaceType> newITypes = new Set<InterfaceType>();

  // Calculate the total number of new types if all combinations were used.
  int nNew = pTypes1.length * iTypes.length +
      pTypes2.length * iTypes.length * iTypes.length;
  // Calculate how many generated types have to be skipped in order to stay
  // under the maximum number set for generating new types (maxNew).
  double step = maxNew / nNew;
  double cntr = 0.0;

  // Instantiate List and Set types.
  pTypes1.forEach((pType) {
    iTypes.forEach((iType) {
      cntr += step;
      if (cntr >= 1.0) {
        cntr -= 1.0;
      } else {
        return true;
      }
      ParameterizedType ptx = pType.instantiate([iType]);
      newITypes.add(ptx);
      if (iType.typeArguments.length >= 1) {
        complexTypes.add(getConstName(ptx.displayName));
      }
    });
  });

  // Instantiate Map types.
  pTypes2.forEach((pType) {
    iTypes.forEach((iType1) {
      iTypes.forEach((iType2) {
        cntr += step;
        if (cntr >= 1.0) {
          cntr -= 1.0;
        } else {
          return true;
        }
        ParameterizedType ptx = pType.instantiate([iType1, iType2]);
        newITypes.add(ptx);
        if (iType1.typeArguments.length >= 1 ||
            iType2.typeArguments.length >= 1) {
          complexTypes.add(getConstName(ptx.displayName));
        }
      });
    });
  });

  // Add instantiated types to the set of types with no free parameters.
  return iTypes.union(newITypes);
}

Set<InterfaceType> instantiateAllTypes(
    Set<InterfaceType> allTypes, Set<String> iTypeFilter, int depth,
    {double maxNew = 64.0}) {
  // Types with one parameter (List, Set).
  Set<InterfaceType> pTypes1 = new Set<InterfaceType>();
  // Types with two parameters (Map).
  Set<InterfaceType> pTypes2 = new Set<InterfaceType>();
  // Types with no parameters or parameters of which have already been
  // instantiated.
  Set<InterfaceType> iTypes = new Set<InterfaceType>();
  // Fill type sets with respective parameter types.
  getParameterizedTypes(allTypes, pTypes1, pTypes2, iTypes);

  // Filter the list of zero parameter types to exclude
  // complex types like Int8List.
  Set<InterfaceType> filteredITypes = {};
  for (var iType in iTypes) {
    if (iTypeFilter.contains(iType.displayName)) {
      filteredITypes.add(iType);
    }
  }

  // Instantiate types with one or two free parameters.
  // Concatenate the newly instantiated types with the previous set of
  // instantiated or zero parameter types to be used as input for the next
  // round or instantiation.
  // Each iteration constructs more nested types like
  // Map<Map<int, int>, List<int>>.
  for (int i = 0; i < depth + 1; ++i) {
    double mn = max(1, maxNew / (depth + 1));
    filteredITypes = filteredITypes
        .union(instantiatePTypes(pTypes1, pTypes2, filteredITypes, maxNew: mn));
  }
  // Return list of instantiated types.
  return iTypes.union(filteredITypes);
}

// Heuristic of which types to include:
// count the number of operators and
// check if the type can be constructed from a literal.
int countOperators(ClassElement ce) {
  int no = 0;
  ce.methods.forEach((method) {
    if (method.isOperator) {
      no++;
    }
    // Detect whether type can be parsed from a literal (dartfuzz.dart can
    // already handle that).
    // This is usually indicated by the presence of the static constructor
    // 'castFrom' or 'parse'.
    if (method.isStatic &&
        (method.name == 'castFrom' || method.name == 'parse')) {
      no += 100;
    }
    for (InterfaceType ci in ce.interfaces) {
      no += countOperators(ci.element);
    }
  });
  return no;
}

// Analyze typed_data and core libraries to extract data types.
void getDataTypes(Set<InterfaceType> allTypes, String dartTop) async {
  final AnalysisSession session = GenUtil.createAnalysisSession(dartTop);

  // Visit libraries for type table generation.
  await visitLibraryAtUri(session, 'dart:typed_data', allTypes);
  await visitLibraryAtUri(session, 'dart:core', allTypes);
}

visitLibraryAtUri(
    AnalysisSession session, String uri, Set<InterfaceType> allTypes) async {
  String libPath = session.uriConverter.uriToPath(Uri.parse(uri));
  ResolvedLibraryResult result = await session.getResolvedLibrary(libPath);
  if (result.state != ResultState.VALID) {
    throw new StateError('Unable to resolve "$uri"');
  }
  visitLibrary(result.element, allTypes);
}

visitLibrary(LibraryElement library, Set<InterfaceType> allTypes) async {
  // This uses the element model to traverse the code. The element model
  // represents the semantic structure of the code. A library consists of
  // one or more compilation units.
  for (CompilationUnitElement unit in library.units) {
    visitCompilationUnit(unit, allTypes);
  }
}

visitCompilationUnit(CompilationUnitElement unit, Set<InterfaceType> allTypes) {
  // Each compilation unit contains elements for all of the top-level
  // declarations in a single file, such as variables, functions, and
  // classes. Note that `types` only returns classes. You can use
  // `mixins` to visit mixins, `enums` to visit enum, `functionTypeAliases`
  // to visit typedefs, etc.
  for (ClassElement classElement in unit.types) {
    if (classElement.isPublic) {
      // Hack: Filter out some difficult types.
      // TODO (felih): include filtered types.
      if (classElement.name.startsWith('Unmodifiable')) continue;
      if (classElement.name.startsWith('Iterable')) continue;
      if (classElement.name.startsWith('BigInt')) continue;
      if (classElement.name.startsWith('DateTime')) continue;
      if (classElement.name.startsWith('Uri')) continue;
      // Compute heuristic to decide whether to include the type.
      int no = countOperators(classElement);
      if (no > operatorCountThreshold) {
        allTypes.add(classElement.type);
      }
    }
  }
}

// Get all interface implemented by type.
Set<String> getInterfaces(InterfaceType tp) {
  Set<String> iTypes = new Set<String>();
  for (InterfaceType iTyp in tp.interfaces) {
    String ifTypName = getConstName(iTyp.displayName);
    iTypes.add(ifTypName);
    iTypes = iTypes.union(getInterfaces(iTyp));
  }
  return iTypes;
}

// Get interface and inheritance relationships for all types.
void getInterfaceRels(Set<InterfaceType> allTypes) {
  for (InterfaceType tp in allTypes) {
    String typName = getConstName(tp.displayName);
    for (String ifTypName in getInterfaces(tp)) {
      interfaceRels[ifTypName] ??= new Set<String>();
      interfaceRels[ifTypName].add(typName);
      if (ifTypName.contains('ITERABLE')) {
        iterableTypes1.add(typName);
      }
    }
    for (InterfaceType it in tp.element.allSupertypes) {
      String ifTypName = getConstName(it.displayName);
      interfaceRels[ifTypName] ??= new Set<String>();
      interfaceRels[ifTypName].add(typName);
    }
  }
  // If interface can be instantiated,
  // add it to the relation list so that we can
  // do tp1 = oneof(interfaceRels[tp2]) in dartfuzz with a chance of
  // tp1 == tp1.
  for (InterfaceType tp in allTypes) {
    String typName = getConstName(tp.displayName);
    if (interfaceRels.containsKey(typName)) {
      interfaceRels[typName].add(typName);
    }
  }
}

main(List<String> arguments) async {
  final parser = new ArgParser()
    ..addOption('dart-top', help: 'explicit value for \$DART_TOP')
    ..addOption('depth',
        help: 'Nesting depth, e.g. List<String> is depth 0, ' +
            'List<List<String>>' +
            'is depth 1. Remark: dart type tables grow ' +
            'exponentially with this, ' +
            'therefore types with higher nesting ' +
            'depth are partially filtered.',
        defaultsTo: '1');
  try {
    final results = parser.parse(arguments);
    int depth = int.parse(results['depth']);
    Set<InterfaceType> allTypes = new Set<InterfaceType>();
    // Filter types to instantiate parameterized types with, this excludes
    // complex types like Int8List (might be added later).
    Set<String> iTypeFilter = {'int', 'bool', 'double', 'String'};
    // Extract basic types from dart::core and dart::typed_data.
    await getDataTypes(allTypes, results['dart-top']);
    // Instantiate parameterized types like List<E>.
    allTypes = instantiateAllTypes(allTypes, iTypeFilter, depth, maxNew: 64);
    // Extract interface Relations between types.
    getInterfaceRels(allTypes);
    // Extract operators from instantiated types.
    getOperators(allTypes);
    // Analyze instantiated types to get elementof/subscript and floating point
    // information.
    analyzeTypes(allTypes);
    // Print everything.
    printTypeTable(allTypes);
    printTypeTable(allTypes, fp: false);
    printTypeTable(allTypes, flatTp: true);
    printTypeTable(allTypes, fp: false, flatTp: true);
  } catch (e) {
    print('Usage: dart gen_type_table.dart [OPTIONS]\n${parser.usage}\n$e');
    exitCode = 255;
  }
}
