class Steep::AST::Types::Factory

def absolute_type(type, context:)

def absolute_type(type, context:)
  absolute_type = type_1(type).map_type_name do |name|
    absolute_type_name(name, context: context) || name.absolute!
  end
  type(absolute_type)
end

def absolute_type_name(type_name, context:)

def absolute_type_name(type_name, context:)
  type_name_resolver.resolve(type_name, context: context)
end

def class_name?(type_name)

def class_name?(type_name)
  env.class_entry(type_name) ? true : false
end

def deep_expand_alias(type, recursive: Set.new)

def deep_expand_alias(type, recursive: Set.new)
  case type
  when AST::Types::Name::Alias
    unless recursive.member?(type.name)
      unfolded = expand_alias(type)
      deep_expand_alias(unfolded, recursive: recursive.union([type.name]))
    end
  when AST::Types::Union
    types = type.types.map {|ty| deep_expand_alias(ty, recursive: recursive) or return }
    AST::Types::Union.build(types: types)
  when AST::Types::Intersection
    types = type.types.map {|ty| deep_expand_alias(ty, recursive: recursive) or return }
    AST::Types::Intersection.build(types: types)
  else
    type
  end
end

def env

def env
  definition_builder.env
end

def expand_alias(type)

def expand_alias(type)
  case type
  when AST::Types::Name::Alias
    unfold(type.name, type.args)
  else
    type
  end
end

def flatten_union(type, acc = [])

def flatten_union(type, acc = [])
  case type
  when AST::Types::Union
    type.types.each {|ty| flatten_union(ty, acc) }
  else
    acc << type
  end
  acc
end

def function_1(func)

def function_1(func)
  params = func.params
  return_type = func.return_type
  if params
    RBS::Types::Function.new(
      required_positionals: params.required.map {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
      optional_positionals: params.optional.map {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
      rest_positionals: params.rest&.yield_self {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
      trailing_positionals: [],
      required_keywords: params.required_keywords.transform_values {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
      optional_keywords: params.optional_keywords.transform_values {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
      rest_keywords: params.rest_keywords&.yield_self {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
      return_type: type_1(return_type)
    )
  else
    RBS::Types::UntypedFunction.new(return_type: type_1(return_type))
  end
end

def initialize(builder:)

def initialize(builder:)
  @definition_builder = builder
  @type_cache = {}
  @method_type_cache = {}
  @method_type_cache.compare_by_identity
end

def inspect

def inspect
  s = "#<%s:%#018x " % [self.class, object_id]
  s << "@definition_builder=#<%s:%#018x>" % [definition_builder.class, definition_builder.object_id]
  s + ">"
end

def instance_type(type_name, args: nil)

def instance_type(type_name, args: nil)
  raise unless type_name.class?
  definition = definition_builder.build_singleton(type_name)
  def_args = definition.type_params.map { Any.instance }
  if args
    raise if def_args.size != args.size
  else
    args = def_args
  end
  AST::Types::Name::Instance.new(name: type_name, args: args)
end

def method_type(method_type)

def method_type(method_type)
  @method_type_cache[method_type] ||=
    Interface::MethodType.new(
      type_params: method_type.type_params.map {|param| type_param(param) },
      type: Interface::Function.new(
        params: params(method_type.type),
        return_type: type(method_type.type.return_type),
        location: method_type.location
      ),
      block: method_type.block&.yield_self do |block|
        Interface::Block.new(
          optional: !block.required,
          type: Interface::Function.new(
            params: params(block.type),
            return_type: type(block.type.return_type),
            location: nil
          ),
          self_type: type_opt(block.self_type)
        )
      end
    )
end

def method_type_1(method_type)

def method_type_1(method_type)
  RBS::MethodType.new(
    type_params: method_type.type_params.map {|param| type_param_1(param) },
    type: function_1(method_type.type),
    block: method_type.block&.yield_self do |block|
      RBS::Types::Block.new(
        type: function_1(block.type),
        required: !block.optional,
        self_type: type_1_opt(block.self_type)
      )
    end,
    location: nil
  )
end

def module_name?(type_name)

def module_name?(type_name)
  env.module_entry(type_name) ? true : false
end

def normalize_args(type_name, args)

def normalize_args(type_name, args)
  case
  when type_name.class?
    if entry = env.normalized_module_class_entry(type_name)
      type_params = entry.type_params
    end
  when type_name.interface?
    if entry = env.interface_decls.fetch(type_name, nil)
      type_params = entry.decl.type_params
    end
  when type_name.alias?
    if entry = env.type_alias_decls.fetch(type_name, nil)
      type_params = entry.decl.type_params
    end
  end
  if type_params && !type_params.empty?
    RBS::AST::TypeParam.normalize_args(type_params, args)
  else
    args
  end
end

def normalize_type(type)

def normalize_type(type)
  case type
  when AST::Types::Name::Instance
    AST::Types::Name::Instance.new(
      name: env.normalize_module_name(type.name),
      args: type.args.map {|ty| normalize_type(ty) }
    )
  when AST::Types::Name::Singleton
    AST::Types::Name::Singleton.new(
      name: env.normalize_module_name(type.name)
    )
  when AST::Types::Any, AST::Types::Boolean, AST::Types::Bot, AST::Types::Nil,
    AST::Types::Top, AST::Types::Void, AST::Types::Literal, AST::Types::Class, AST::Types::Instance,
    AST::Types::Self, AST::Types::Var, AST::Types::Logic::Base
    type
  when AST::Types::Intersection
    AST::Types::Intersection.build(
      types: type.types.map {|type| normalize_type(type) }
    )
  when AST::Types::Union
    AST::Types::Union.build(
      types: type.types.map {|type| normalize_type(type) }
    )
  when AST::Types::Record
    type.map_type {|type| normalize_type(type) }
  when AST::Types::Tuple
    AST::Types::Tuple.new(
      types: type.types.map {|type| normalize_type(type) }
    )
  when AST::Types::Proc
    type.map_type {|type| normalize_type(type) }
  when AST::Types::Name::Alias
    AST::Types::Name::Alias.new(
      name: type.name,
      args: type.args.map {|ty| normalize_type(ty) }
    )
  when AST::Types::Name::Interface
    AST::Types::Name::Interface.new(
      name: type.name,
      args: type.args.map {|ty| normalize_type(ty) }
    )
  end
end

def params(type)

def params(type)
  case type
  when RBS::Types::Function
    Interface::Function::Params.build(
      required: type.required_positionals.map {|param| type(param.type) },
      optional: type.optional_positionals.map {|param| type(param.type) },
      rest: type.rest_positionals&.yield_self {|param| type(param.type) },
      required_keywords: type.required_keywords.transform_values {|param| type(param.type) },
      optional_keywords: type.optional_keywords.transform_values {|param| type(param.type) },
      rest_keywords: type.rest_keywords&.yield_self {|param| type(param.type) }
    )
  when RBS::Types::UntypedFunction
    nil
  end
end

def partition_union(type)

def partition_union(type)
  case type
  when AST::Types::Name::Alias
    unfold = expand_alias(type)
    if unfold == type
      [type, type]
    else
      partition_union(unfold)
    end
  when AST::Types::Union
    truthy_types = [] #: Array[AST::Types::t]
    falsy_types = [] #: Array[AST::Types::t]
    type.types.each do |type|
      truthy, falsy = partition_union(type)
      truthy_types << truthy if truthy
      falsy_types << falsy if falsy
    end
    [
      truthy_types.empty? ? nil : AST::Types::Union.build(types: truthy_types),
      falsy_types.empty? ? nil : AST::Types::Union.build(types: falsy_types)
    ]
  when AST::Types::Any, AST::Types::Boolean, AST::Types::Top, AST::Types::Logic::Base
    [type, type]
  when AST::Types::Nil
    [nil, type]
  when AST::Types::Literal
    if type.value == false
      [nil, type]
    else
      [type, nil]
    end
  else
    [type, nil]
  end
end

def try_instance_type(type)

def try_instance_type(type)
  case type
  when AST::Types::Name::Instance
    instance_type(type.name)
  when AST::Types::Name::Singleton
    instance_type(type.name)
  else
    nil
  end
end

def try_singleton_type(type)

def try_singleton_type(type)
  case type
  when AST::Types::Name::Instance, AST::Types::Name::Singleton
    AST::Types::Name::Singleton.new(name:type.name)
  else
    nil
  end
end

def type(type)

def type(type)
  if ty = type_cache[type]
    return ty
  end
  type_cache[type] =
    case type
    when RBS::Types::Bases::Any
      Any.instance
    when RBS::Types::Bases::Class
      Class.instance
    when RBS::Types::Bases::Instance
      Instance.instance
    when RBS::Types::Bases::Self
      Self.instance
    when RBS::Types::Bases::Top
      Top.instance
    when RBS::Types::Bases::Bottom
      Bot.instance
    when RBS::Types::Bases::Bool
      Boolean.instance
    when RBS::Types::Bases::Void
      Void.instance
    when RBS::Types::Bases::Nil
      Nil.instance
    when RBS::Types::Variable
      Var.new(name: type.name)
    when RBS::Types::ClassSingleton
      type_name = type.name
      Name::Singleton.new(name: type_name)
    when RBS::Types::ClassInstance
      type_name = type.name
      args = normalize_args(type_name, type.args).map {|arg| type(arg) }
      Name::Instance.new(name: type_name, args: args)
    when RBS::Types::Interface
      type_name = type.name
      args = normalize_args(type_name, type.args).map {|arg| type(arg) }
      Name::Interface.new(name: type_name, args: args)
    when RBS::Types::Alias
      type_name = type.name
      args = normalize_args(type_name, type.args).map {|arg| type(arg) }
      Name::Alias.new(name: type_name, args: args)
    when RBS::Types::Union
      Union.build(types: type.types.map {|ty| type(ty) })
    when RBS::Types::Intersection
      Intersection.build(types: type.types.map {|ty| type(ty) })
    when RBS::Types::Optional
      Union.build(types: [type(type.type), Nil.instance()])
    when RBS::Types::Literal
      Literal.new(value: type.literal)
    when RBS::Types::Tuple
      Tuple.new(types: type.types.map {|ty| type(ty) })
    when RBS::Types::Record
      elements = {} #: Hash[Record::key, AST::Types::t]
      required_keys = Set[] #: Set[Record::key]
      type.all_fields.each do |key, (value, required)|
        required_keys << key if required
        elements[key] = type(value)
      end
      Record.new(elements: elements, required_keys: required_keys)
    when RBS::Types::Proc
      func = Interface::Function.new(
        params: params(type.type),
        return_type: type(type.type.return_type),
        location: nil
      )
      block = if type.block
                Interface::Block.new(
                  type: Interface::Function.new(
                    params: params(type.block.type),
                    return_type: type(type.block.type.return_type),
                    location: nil
                  ),
                  optional: !type.block.required,
                  self_type: type_opt(type.block.self_type)
                )
              end
      Proc.new(
        type: func,
        block: block,
        self_type: type_opt(type.self_type)
      )
    else
      raise "Unexpected type given: #{type}"
    end
end

def type_1(type)

def type_1(type)
  case type
  when Any
    RBS::Types::Bases::Any.new(location: nil)
  when Class
    RBS::Types::Bases::Class.new(location: nil)
  when Instance
    RBS::Types::Bases::Instance.new(location: nil)
  when Self
    RBS::Types::Bases::Self.new(location: nil)
  when Top
    RBS::Types::Bases::Top.new(location: nil)
  when Bot
    RBS::Types::Bases::Bottom.new(location: nil)
  when Boolean
    RBS::Types::Bases::Bool.new(location: nil)
  when Void
    RBS::Types::Bases::Void.new(location: nil)
  when Nil
    RBS::Types::Bases::Nil.new(location: nil)
  when Var
    RBS::Types::Variable.new(name: type.name, location: nil)
  when Name::Singleton
    RBS::Types::ClassSingleton.new(name: type.name, location: nil)
  when Name::Instance
    RBS::Types::ClassInstance.new(
      name: type.name,
      args: type.args.map {|arg| type_1(arg) },
      location: nil
    )
  when Name::Interface
    RBS::Types::Interface.new(
      name: type.name,
      args: type.args.map {|arg| type_1(arg) },
      location: nil
    )
  when Name::Alias
    RBS::Types::Alias.new(
      name: type.name,
      args: type.args.map {|arg| type_1(arg) },
      location: nil
    )
  when Union
    RBS::Types::Union.new(
      types: type.types.map {|ty| type_1(ty) },
      location: nil
    )
  when Intersection
    RBS::Types::Intersection.new(
      types: type.types.map {|ty| type_1(ty) },
      location: nil
    )
  when Literal
    RBS::Types::Literal.new(literal: type.value, location: nil)
  when Tuple
    RBS::Types::Tuple.new(
      types: type.types.map {|ty| type_1(ty) },
      location: nil
    )
  when Record
    all_fields = {} #: Hash[Symbol, [RBS::Types::t, bool]]
    type.elements.each do |key, value|
      raise unless key.is_a?(Symbol)
      all_fields[key] = [type_1(value), type.required?(key)]
    end
    RBS::Types::Record.new(all_fields: all_fields, location: nil)
  when Proc
    block = if type.block
              RBS::Types::Block.new(
                type: function_1(type.block.type),
                required: !type.block.optional?,
                self_type: type_1_opt(type.block.self_type)
              )
            end
    RBS::Types::Proc.new(
      type: function_1(type.type),
      self_type: type_1_opt(type.self_type),
      block: block,
      location: nil
    )
  when Logic::Base
    RBS::Types::Bases::Bool.new(location: nil)
  else
    raise "Unexpected type given: #{type} (#{type.class})"
  end
end

def type_1_opt(type)

def type_1_opt(type)
  if type
    type_1(type)
  end
end

def type_name_resolver

def type_name_resolver
  @type_name_resolver ||= RBS::Resolver::TypeNameResolver.new(definition_builder.env)
end

def type_opt(type)

def type_opt(type)
  if type
    type(type)
  end
end

def type_param(type_param)

def type_param(type_param)
  Interface::TypeParam.new(
    name: type_param.name,
    upper_bound: type_opt(type_param.upper_bound_type),
    variance: type_param.variance,
    unchecked: type_param.unchecked?,
    default_type: type_opt(type_param.default_type)
  )
end

def type_param_1(type_param)

def type_param_1(type_param)
  RBS::AST::TypeParam.new(
    name: type_param.name,
    variance: type_param.variance,
    upper_bound: type_param.upper_bound&.yield_self {|u|
      case u_ = type_1(u)
      when RBS::Types::ClassInstance, RBS::Types::ClassSingleton, RBS::Types::Interface
        u_
      else
        raise "`#{u_}` cannot be type parameter upper bound"
      end
    },
    location: type_param.location
  ).unchecked!(type_param.unchecked)
end

def unfold(type_name, args)

def unfold(type_name, args)
  type(
    definition_builder.expand_alias2(
      type_name,
      args.empty? ? [] : args.map {|t| type_1(t) }
    )
  )
end

def unwrap_optional(type)

def unwrap_optional(type)
  case type
  when AST::Types::Union
    unwrap = type.types.filter_map do |type|
      unless type.is_a?(AST::Types::Nil)
        type
      end
    end
    unless unwrap.empty?
      AST::Types::Union.build(types: unwrap)
    end
  when AST::Types::Nil
    nil
  when AST::Types::Name::Alias
    type_ = expand_alias(type)
    if type_ == type
      type_
    else
      unwrap_optional(type_)
    end
  else
    type
  end
end