Class: Finitio::SubType

Inherits:
Type
  • Object
show all
Defined in:
lib/finitio/type/sub_type.rb,
lib/finitio/generation/sub_type.rb

Overview

A sub type generator, through specialization by constraints.

A sub type captures a subset of the values of a super type, through a constraint. For instance, a Byte type can be defined as a subset of all integers, as follows:

Byte := Integer( i | i >= 0 and i <= 255 )

This class allows defining such sub types with multiple named constraints. For instance,

Int  = BuiltinType.new(Integer)
Byte = SubType.new(Int, positive: ->(i){ i >= 0 },
                        small:    ->(i){ i <= 255 })

The concrete representation of the super type is kept as representation of the sub type. In other words:

R(Byte) = R(Int) = Fixnum

Accordingly, the ‘dress` transformation function has the following signature:

dress :: Alpha  -> Byte   throws TypeError
dress :: Object -> Fixnum throws TypeError

Constant Summary

Constants included from Metadata

Metadata::EMPTY_METADATA

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Type

#anonymous?, #name, #name=, #named?, #suppremum, #to_s

Methods included from Metadata

#metadata, #metadata=, #metadata?

Constructor Details

#initialize(super_type, constraints, name = nil, metadata = nil) ⇒ SubType

Returns a new instance of SubType.



30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/finitio/type/sub_type.rb', line 30

def initialize(super_type, constraints, name = nil,  = nil)
  unless super_type.is_a?(Type)
    raise ArgumentError, "Finitio::Type expected, got #{super_type}"
  end

  unless constraints.is_a?(Array) &&
         constraints.all?{|v| v.is_a?(Constraint) }
    raise ArgumentError, "[Constraint] expected for constraints, got #{constraints}"
  end

  super(name, )
  @super_type, @constraints = super_type, constraints.freeze
end

Instance Attribute Details

#constraintsObject (readonly)

Returns the value of attribute constraints.



43
44
45
# File 'lib/finitio/type/sub_type.rb', line 43

def constraints
  @constraints
end

#super_typeObject (readonly)

Returns the value of attribute super_type.



43
44
45
# File 'lib/finitio/type/sub_type.rb', line 43

def super_type
  @super_type
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



88
89
90
91
92
93
# File 'lib/finitio/type/sub_type.rb', line 88

def ==(other)
  super || (
    other.is_a?(SubType) && (other.super_type == super_type) &&
    set_equal?(constraints, other.constraints)
  )
end

#[](name) ⇒ Object



49
50
51
# File 'lib/finitio/type/sub_type.rb', line 49

def [](name)
  constraints.find{|c| c.name == name }
end

#default_nameObject



53
54
55
# File 'lib/finitio/type/sub_type.rb', line 53

def default_name
  constraints.first.name.to_s.capitalize
end

#dress(value, handler = DressHelper.new) ⇒ Object

Check that ‘value` can be uped through the supertype, then verify all constraints. Raise an error if anything goes wrong.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/finitio/type/sub_type.rb', line 63

def dress(value, handler = DressHelper.new)
  # Check that the supertype is able to dress the value.
  # Rewrite and set cause to any encountered TypeError.
  uped = handler.try(self, value) do
    super_type.dress(value, handler)
  end

  # Check each constraint in turn
  constraints.each do |constraint|
    next if constraint===uped
    msg = handler.default_error_message(self, value)
    if constraint.named? && constraints.size>1
      msg << " (not #{constraint.name})"
    end
    handler.fail!(msg)
  end

  # seems good, return the uped value
  uped
end

#generate_data(generator, world = nil) ⇒ Object



4
5
6
# File 'lib/finitio/generation/sub_type.rb', line 4

def generate_data(generator, world = nil)
  generator.call(super_type, world)
end

#hashObject



96
97
98
# File 'lib/finitio/type/sub_type.rb', line 96

def hash
  self.class.hash ^ super_type.hash ^ set_hash(constraints)
end

#include?(value) ⇒ Boolean

Returns:

  • (Boolean)


57
58
59
# File 'lib/finitio/type/sub_type.rb', line 57

def include?(value)
  super_type.include?(value) && constraints.all?{|c| c===value }
end

#representatorObject



45
46
47
# File 'lib/finitio/type/sub_type.rb', line 45

def representator
  super_type.representator
end

#resolve_proxies(system) ⇒ Object



100
101
102
# File 'lib/finitio/type/sub_type.rb', line 100

def resolve_proxies(system)
  SubType.new(super_type.resolve_proxies(system), constraints, name, )
end

#unconstrainedObject



84
85
86
# File 'lib/finitio/type/sub_type.rb', line 84

def unconstrained
  super_type.unconstrained
end