class Steep::TypeInference::Logic

def environments(truthy_vars:, falsey_vars:, lvar_env:)

def environments(truthy_vars:, falsey_vars:, lvar_env:)
  truthy_hash = lvar_env.assigned_types.dup
  falsey_hash = lvar_env.assigned_types.dup
  (truthy_vars + falsey_vars).each do |var|
    type = lvar_env[var]
    truthy_type, falsey_type = partition_union(type)
    if truthy_vars.include?(var)
      truthy_hash[var] = LocalVariableTypeEnv::Entry.new(type: truthy_type)
    end
    if falsey_vars.include?(var)
      falsey_hash[var] = LocalVariableTypeEnv::Entry.new(type: falsey_type)
    end
  end
  [
    lvar_env.except(truthy_vars).update(assigned_types: truthy_hash),
    lvar_env.except(falsey_vars).update(assigned_types: falsey_hash)
  ]
end

def initialize(subtyping:)

def initialize(subtyping:)
  @subtyping = subtyping
end

def nodes(node:)

def nodes(node:)
  case node.type
  when :lvasgn
    rhs = node.children[1]
    t, f = nodes(node: rhs)
    [
      t.merge([node]),
      f.merge([node])
    ]
  when :and
    lhs, rhs = node.children
    lt, _ = nodes(node: lhs)
    rt, _ = nodes(node: rhs)
    [
      Result.new([node]) + lt + rt,
      Result.new([node])
    ]
  when :or
    lhs, rhs = node.children
    _, lf = nodes(node: lhs)
    _, rf = nodes(node: rhs)
    [
      Result.new([node]),
      Result.new([node]) + lf + rf
    ]
  when :begin
    nodes(node: node.children.last)
  else
    [
      Result.new([node]),
      Result.new([node])
    ]
  end
end

def partition_union(type)

def partition_union(type)
  case type
  when AST::Types::Union
    falsey_types, truthy_types = type.types.partition do |type|
      case type
      when AST::Types::Nil
        true
      when AST::Types::Literal
        type.value == false
      end
    end
    [
      truthy_types.empty? ? AST::Types::Bot.new : AST::Types::Union.build(types: truthy_types),
      falsey_types.empty? ? AST::Types::Bot.new : AST::Types::Union.build(types: falsey_types)
    ]
  when AST::Types::Any, AST::Types::Top, AST::Types::Boolean, AST::Types::Void
    [type, type]
  else
    [type, AST::Types::Bot.new]
  end
end