def eval(env:, type:, node:)
def eval(env:, type:, node:)
value_node, vars = decompose_value(node)
truthy_env = env
falsy_env = env
if type.is_a?(AST::Types::Any)
type = guess_type_from_method(node) || type
end
if type.is_a?(AST::Types::Logic::Base)
vars.each do |var_name|
var_type = truthy_env[var_name]
truthy_type, falsy_type = factory.unwrap_optional(var_type)
falsy_type ||= AST::Builtin.nil_type
truthy_env = truthy_env.assign!(var_name, node: node, type: truthy_type) {|_, type, _| type }
falsy_env = truthy_env.assign!(var_name, node: node, type: falsy_type) {|_, type, _| type }
end
case type
when AST::Types::Logic::Env
truthy_env = type.truthy
falsy_env = type.falsy
when AST::Types::Logic::ReceiverIsNil
case value_node.type
when :send
receiver = value_node.children[0]
if receiver
_, receiver_vars = decompose_value(receiver)
receiver_vars.each do |receiver_var|
var_type = env[receiver_var]
truthy_type, falsy_type = factory.unwrap_optional(var_type)
truthy_env = truthy_env.assign!(receiver_var, node: node, type: falsy_type || AST::Builtin.nil_type)
falsy_env = falsy_env.assign!(receiver_var, node: node, type: truthy_type)
end
end
end
when AST::Types::Logic::ReceiverIsArg
case value_node.type
when :send
receiver, _, arg = value_node.children
if receiver
_, receiver_vars = decompose_value(receiver)
arg_type = typing.type_of(node: arg)
if arg_type.is_a?(AST::Types::Name::Singleton)
receiver_vars.each do |var_name|
case var_name
when :_, :__any__, :__skip__
# skip
else
var_type = env[var_name]
truthy_type, falsy_type = type_case_select(var_type, arg_type.name)
truthy_env = truthy_env.assign!(var_name, node: node, type: truthy_type)
falsy_env = falsy_env.assign!(var_name, node: node, type: falsy_type)
end
end
end
end
end
when AST::Types::Logic::ArgIsReceiver
case value_node.type
when :send
receiver, _, arg = value_node.children
if receiver
_, arg_vars = decompose_value(arg)
receiver_type = factory.deep_expand_alias(typing.type_of(node: receiver))
if receiver_type.is_a?(AST::Types::Name::Singleton)
arg_vars.each do |var_name|
var_type = env[var_name]
truthy_type, falsy_type = type_case_select(var_type, receiver_type.name)
truthy_env = truthy_env.assign!(var_name, node: node, type: truthy_type)
falsy_env = falsy_env.assign!(var_name, node: node, type: falsy_type)
end
end
end
end
when AST::Types::Logic::ArgEqualsReceiver
case value_node.type
when :send
receiver, _, arg = value_node.children
if receiver
_, arg_vars = decompose_value(arg)
arg_vars.each do |var_name|
var_type = factory.deep_expand_alias(env[var_name])
truthy_types, falsy_types = literal_var_type_case_select(receiver, var_type)
truthy_env = truthy_env.assign!(var_name, node: node, type: AST::Types::Union.build(types: truthy_types, location: nil))
falsy_env = falsy_env.assign!(var_name, node: node, type: AST::Types::Union.build(types: falsy_types, location: nil))
end
end
end
when AST::Types::Logic::Not
receiver, * = value_node.children
receiver_type = typing.type_of(node: receiver)
falsy_env, truthy_env = eval(env: env, type: receiver_type, node: receiver)
end
else
_, vars = decompose_value(node)
vars.each do |var_name|
var_type = env[var_name]
truthy_type, falsy_type = factory.unwrap_optional(var_type)
if falsy_type
truthy_env = truthy_env.assign!(var_name, node: node, type: truthy_type)
falsy_env = falsy_env.assign!(var_name, node: node, type: falsy_type)
else
truthy_env = truthy_env.assign!(var_name, node: node, type: truthy_type)
falsy_env = falsy_env.assign!(var_name, node: node, type: truthy_type)
end
end
end
[truthy_env, falsy_env]
end