class TypedRb::Types::TyEither
Attributes
options[RW]
Public Class Methods
new(node=nil)
click to toggle source
Calls superclass method
# File lib/typed/types/ty_either.rb, line 5 def initialize(node=nil) super(NilClass, node) @options = { :normal => TypedRb::Types::TyUnit.new } end
wrap(type)
click to toggle source
# File lib/typed/types/ty_either.rb, line 10 def self.wrap(type) if type.either? type elsif type.stack_jump? either = TyEither.new(type.node) either[type.jump_kind] = type either else either = TyEither.new(type.node) either[:normal] = type either end end
Public Instance Methods
[](kind)
click to toggle source
# File lib/typed/types/ty_either.rb, line 64 def [](kind) valid_kind?(kind) options[kind] end
[]=(kind, value)
click to toggle source
# File lib/typed/types/ty_either.rb, line 69 def []=(kind, value) valid_kind?(kind) options[kind] = value end
all_kinds()
click to toggle source
# File lib/typed/types/ty_either.rb, line 60 def all_kinds [:normal] + kinds end
apply_bindings(bindings_map)
click to toggle source
# File lib/typed/types/ty_either.rb, line 106 def apply_bindings(bindings_map) all_kinds.each do |kind| if self[kind] if self[kind].is_a?(Polymorphism::TypeVariable) self[kind].apply_bindings(bindings_map) self[kind] = self[kind].bound if self[kind].bound elsif self[kind].is_a?(TyGenericSingletonObject) || self[kind].is_a?(TyGenericObject) self[kind].apply_bindings(bindings_map) end end end self end
break?()
click to toggle source
# File lib/typed/types/ty_either.rb, line 44 def break? !options[:break].nil? && options[:break].break? end
check_type(context, types=[:return])
click to toggle source
# File lib/typed/types/ty_either.rb, line 74 def check_type(context, types=[:return]) relevant_types = types.map { |type| self[type] }.reject(&:nil?) relevant_types = relevant_types.map { |type| type.stack_jump? ? type.wrapped_type : type } relevant_types = relevant_types.map { |type| type.check_type(context) } relevant_types.max rescue relevant_types.reduce { |type_a, type_b| type_a.union(type_b) } end
compatible?(other_type, relation = :lt)
click to toggle source
This compatible function is to use the normal wrapped type in regular comparisons
# File lib/typed/types/ty_either.rb, line 82 def compatible?(other_type, relation = :lt) (options[:normal] || TyUnit.new(node)).compatible?(other_type, relation) end
compatible_either?(other_type)
click to toggle source
This compatible function is to build the comparison in conditional terms
# File lib/typed/types/ty_either.rb, line 87 def compatible_either?(other_type) if other_type.either? # either vs either kinds.each do |kind| check_jump_kind(kind, other_type[kind]) end check_normal_kind(other_type[:normal]) elsif other_type.stack_jump? # either vs jump check_jump_kind(other_type.jump_kind, other_type) else # either vs normal flow check_normal_kind(other_type) end self end
either?()
click to toggle source
# File lib/typed/types/ty_either.rb, line 36 def either? true end
has_jump?()
click to toggle source
# File lib/typed/types/ty_either.rb, line 52 def has_jump? !(options[:return] || options[:next] || options[:break]).nil? end
kinds()
click to toggle source
# File lib/typed/types/ty_either.rb, line 56 def kinds [:return, :next, :break] end
next?()
click to toggle source
# File lib/typed/types/ty_either.rb, line 48 def next? !options[:next].nil? && options[:next].next? end
return?()
click to toggle source
# File lib/typed/types/ty_either.rb, line 40 def return? !options[:return].nil? && options[:return].return? end
to_s()
click to toggle source
# File lib/typed/types/ty_either.rb, line 101 def to_s vals = options.to_a.reject {|(k,v)| v.nil? }.map{ |k,v| "#{k}:#{v}" }.join(" | ") "Either[#{vals}]" end
unwrap()
click to toggle source
# File lib/typed/types/ty_either.rb, line 24 def unwrap normal = self[:normal].is_a?(TypedRb::Types::TyUnit) ? nil : self[:normal] wrapped_types = [normal, self[:return], self[:break], self[:next]].compact if wrapped_types.count > 1 self elsif wrapped_types.count == 1 wrapped_types.first else TypedRb::Types::TyUnit.new end end
Private Instance Methods
check_jump_kind(kind, other_type)
click to toggle source
# File lib/typed/types/ty_either.rb, line 122 def check_jump_kind(kind, other_type) if self[kind].nil? && other_type self[kind] = other_type elsif self[kind] && other_type max_type = max(self[kind].wrapped_type, other_type.wrapped_type) self[kind] = TyStackJump.new(kind, max_type) end end
check_normal_kind(other_type)
click to toggle source
# File lib/typed/types/ty_either.rb, line 131 def check_normal_kind(other_type) self[:normal] = max(self[:normal], other_type) end
max(type_a, type_b)
click to toggle source
# File lib/typed/types/ty_either.rb, line 135 def max(type_a, type_b) return (type_a || type_b) if type_a.nil? || type_b.nil? return type_b if type_a.is_a?(Types::TyDynamic) || type_a.is_a?(Types::TyDynamicFunction) return type_a if type_b.is_a?(Types::TyDynamic) || type_b.is_a?(Types::TyDynamicFunction) return type_b if type_a.is_a?(Types::TyError) return type_a if type_b.is_a?(Types::TyError) type_vars = [type_a, type_b].select { |type| type.is_a?(Polymorphism::TypeVariable) } if type_vars.count == 2 type_vars[0].compatible?(type_vars[1], :lt) type_vars[1].compatible?(type_vars[0], :lt) type_vars[0] elsif type_vars.count == 1 type_var = type_vars.first non_type_var = ([type_a, type_b] - type_vars).first type_var.compatible?(non_type_var, :gt) type_var else begin [type_a, type_b].max rescue Exception => ex type_a.union(type_b) end end end
valid_kind?(kind)
click to toggle source
# File lib/typed/types/ty_either.rb, line 161 def valid_kind?(kind) unless kind == :normal || kinds.include?(kind) fail Exception, "Invalid kind of either type #{kind}" end end