Class: Typisch::Type::Object

Inherits:
Constructor show all
Defined in:
lib/typisch/object.rb

Constant Summary

Constants inherited from Constructor

Constructor::CONSTRUCTOR_TYPE_SUBCLASSES

Instance Attribute Summary collapse

Attributes inherited from Typisch::Type

#name

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Constructor

#alternative_types, inherited, #type_lattice

Methods inherited from Typisch::Type

#<, #<=, #<=>, #==, #===, #>, #>=, #alternative_types, #annotations, #annotations=, #excluding_null, #inspect, #recursive?, subtype?, #target, #to_s

Constructor Details

#initialize(tag, property_names_to_types = {}) ⇒ Object

Returns a new instance of Object.

Raises:

  • (ArgumentError)


16
17
18
19
20
# File 'lib/typisch/object.rb', line 16

def initialize(tag, property_names_to_types={})
  @tag = tag
  raise ArgumentError, "expected String tag name for first argument" unless tag.is_a?(::String) && !tag.empty?
  @property_names_to_types = property_names_to_types
end

Instance Attribute Details

#property_names_to_typesObject (readonly)

Returns the value of attribute property_names_to_types.



22
23
24
# File 'lib/typisch/object.rb', line 22

def property_names_to_types
  @property_names_to_types
end

#tagObject (readonly)

Returns the value of attribute tag.



22
23
24
# File 'lib/typisch/object.rb', line 22

def tag
  @tag
end

Class Method Details

.check_subtype(x, y, &recursively_check_subtype) ⇒ Object



8
9
10
11
12
13
# File 'lib/typisch/object.rb', line 8

def check_subtype(x, y, &recursively_check_subtype)
  return false unless x.class_or_module <= y.class_or_module
  y.property_names_to_types.all? do |y_propname, y_type|
    x_type = x[y_propname] and recursively_check_subtype[x_type, y_type]
  end
end

.top_typeObject



4
5
6
# File 'lib/typisch/object.rb', line 4

def top_type(*)
  new("Object")
end

Instance Method Details

#[](property_name) ⇒ Object



36
37
38
# File 'lib/typisch/object.rb', line 36

def [](property_name)
  @property_names_to_types[property_name]
end

#canonicalize!Object



62
63
64
65
66
# File 'lib/typisch/object.rb', line 62

def canonicalize!
  @property_names_to_types.keys.each do |name|
    @property_names_to_types[name] = @property_names_to_types[name].target
  end
end

#check_type(instance, &recursively_check_type) ⇒ Object

For now, will only accept classes of object where the properties are available via attr_reader-style getter methods. TODO: maybe make allowances for objects which want to type-check via hash-style property access too.



43
44
45
46
47
48
49
# File 'lib/typisch/object.rb', line 43

def check_type(instance, &recursively_check_type)
  instance.is_a?(class_or_module) &&
  @property_names_to_types.all? do |prop_name, type|
    instance.respond_to?(prop_name) &&
    recursively_check_type[type, instance.send(prop_name)]
  end
end

#class_or_moduleObject



24
25
26
# File 'lib/typisch/object.rb', line 24

def class_or_module
  tag.split('::').inject(::Object) {|a,b| a.const_get(b)}
end

#property_annotations(property_name) ⇒ Object



68
69
70
# File 'lib/typisch/object.rb', line 68

def property_annotations(property_name)
  (annotations[:properties] ||= {})[property_name] ||= {}
end

#property_namesObject



28
29
30
# File 'lib/typisch/object.rb', line 28

def property_names
  @property_names_to_types.keys
end

#shallow_check_type(instance) ⇒ Object



51
52
53
# File 'lib/typisch/object.rb', line 51

def shallow_check_type(instance)
  instance.is_a?(class_or_module)
end

#subexpression_typesObject



32
33
34
# File 'lib/typisch/object.rb', line 32

def subexpression_types
  @property_names_to_types.values
end

#to_string(depth, indent) ⇒ Object



55
56
57
58
59
60
# File 'lib/typisch/object.rb', line 55

def to_string(depth, indent)
  next_indent = "#{indent}  "
  pairs = @property_names_to_types.map {|n,t| "#{n.inspect} => #{t.to_s(depth+1, "#{indent}  ")}"}
  tag = @tag == "Object" ? '' : "#{@tag},"
  "object(#{tag}\n#{next_indent}#{pairs.join(",\n#{next_indent}")}\n#{indent})"
end