Class: Emfrp::Typing::UnionType

Inherits:
Object
  • Object
show all
Defined in:
lib/emfrp/typing/union_type.rb

Defined Under Namespace

Classes: UnifyError

Constant Summary collapse

NameCounter =
(0..10000).to_a

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ UnionType

Returns a new instance of UnionType.



36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/emfrp/typing/union_type.rb', line 36

def initialize(*args)
  if args.length == 2
    @typename = args[0]
    @typeargs = args[1]
  elsif args.length == 0
    @union = [self]
    @name_id = NameCounter.shift
    @original_name_id = @name_id
  else
    raise "Wrong number of arguments (#{args.length} for 0, 2)"
  end
end

Instance Attribute Details

#name_idObject

Returns the value of attribute name_id.



12
13
14
# File 'lib/emfrp/typing/union_type.rb', line 12

def name_id
  @name_id
end

#original_typevar_nameObject

Returns the value of attribute original_typevar_name.



12
13
14
# File 'lib/emfrp/typing/union_type.rb', line 12

def original_typevar_name
  @original_typevar_name
end

#typeargsObject (readonly)

Returns the value of attribute typeargs.



11
12
13
# File 'lib/emfrp/typing/union_type.rb', line 11

def typeargs
  @typeargs
end

#typenameObject (readonly)

Returns the value of attribute typename.



11
12
13
# File 'lib/emfrp/typing/union_type.rb', line 11

def typename
  @typename
end

#unionObject

Returns the value of attribute union.



12
13
14
# File 'lib/emfrp/typing/union_type.rb', line 12

def union
  @union
end

Class Method Details

.from_type(type, tbl = {}) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/emfrp/typing/union_type.rb', line 15

def self.from_type(type, tbl={})
  case type
  when Emfrp::Type
    new(type[:name][:desc], type[:args].map{|a| from_type(a, tbl)})
  when TypeVar
    name = type[:name][:desc]
    if tbl[name]
      tbl[name]
    else
      a = new()
      tbl[name] = a
      a.original_typevar_name = name
      a
    end
  when UnionType
    type
  else
    raise "unexpected type #{type.class} (bug)"
  end
end

Instance Method Details

#clone_utype(tbl = {}) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/emfrp/typing/union_type.rb', line 114

def clone_utype(tbl={})
  if self.var?
    if tbl[self]
      tbl[self]
    else
      alt = self.class.new
      self.union.each{|t| tbl[t] = alt}
      alt
    end
  else
    self.class.new(self.typename, self.typeargs.map{|t| t.clone_utype(tbl)})
  end
end

#collect_union(visited = {}) ⇒ Object



93
94
95
96
97
98
# File 'lib/emfrp/typing/union_type.rb', line 93

def collect_union(visited={})
  return [] if visited[self]
  visited[self] = true
  res = @union + @union.map{|t| t.collect_union(visited)}.flatten
  return res.uniq
end

#has_var?Boolean

Returns:

  • (Boolean)


77
78
79
80
81
82
83
# File 'lib/emfrp/typing/union_type.rb', line 77

def has_var?
  if self.var?
    true
  else
    self.typeargs.any?{|x| x.has_var?}
  end
end

#include?(other) ⇒ Boolean

Returns:

  • (Boolean)


67
68
69
70
71
72
73
74
75
# File 'lib/emfrp/typing/union_type.rb', line 67

def include?(other)
  if self.match?(other)
    true
  elsif !self.var?
    self.typeargs.any?{|x| x.include?(other)}
  else
    false
  end
end

#inspectObject



186
187
188
189
190
191
192
193
194
# File 'lib/emfrp/typing/union_type.rb', line 186

def inspect
  if self.var?
    #"a#{self.name_id}[#{@original_name_id}]" + (@original_typevar_name ? "(#{@original_typevar_name})" : "")
    "a#{self.name_id}" + (@original_typevar_name ? "(#{@original_typevar_name})" : "")
  else
    args = self.typeargs.size > 0 ? "[#{self.typeargs.map{|t| t.inspect}.join(", ")}]" : ""
    "#{self.typename}#{args}"
  end
end

#match?(other) ⇒ Boolean

Returns:

  • (Boolean)


53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/emfrp/typing/union_type.rb', line 53

def match?(other)
  if self.var? && other.var?
    self.name_id == other.name_id
  elsif !self.var? && !other.var?
    if self.typename == other.typename && self.typeargs.size == other.typeargs.size
      self.typeargs.zip(other.typeargs).all?{|a, b| a.match?(b)}
    else
      false
    end
  else
    false
  end
end

#occur_check(var) ⇒ Object



152
153
154
155
156
157
158
159
# File 'lib/emfrp/typing/union_type.rb', line 152

def occur_check(var)
  if !self.var?
    self.typeargs.each{|t| t.occur_check(var)}
  end
  if self == var
    raise UnifyError.new(nil, nil)
  end
end

#to_flatten_uniq_strObject



174
175
176
177
178
179
180
181
182
183
184
# File 'lib/emfrp/typing/union_type.rb', line 174

def to_flatten_uniq_str
  if self.var?
    raise "error"
  end
  if self.typeargs.size > 0
    args = self.typeargs.map{|t| t.to_flatten_uniq_str}.join("_")
    "#{self.typename}_#{args}"
  else
    "#{self.typename}"
  end
end

#to_uniq_strObject



161
162
163
164
165
166
167
168
169
170
171
# File 'lib/emfrp/typing/union_type.rb', line 161

def to_uniq_str
  if self.var?
    raise "error"
  end
  if self.typeargs.size > 0
    args = self.typeargs.map{|t| t.to_uniq_str}.join(", ")
    "#{self.typename}[#{args}]"
  else
    "#{self.typename}"
  end
end

#transform(other) ⇒ Object



108
109
110
111
112
# File 'lib/emfrp/typing/union_type.rb', line 108

def transform(other)
  @typename = other.typename
  @typeargs = other.typeargs
  @union = nil
end

#typevarsObject



100
101
102
103
104
105
106
# File 'lib/emfrp/typing/union_type.rb', line 100

def typevars
  if var?
    [self]
  else
    typeargs.map{|t| t.typevars}.flatten
  end
end

#unify(other) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/emfrp/typing/union_type.rb', line 128

def unify(other)
  if !self.var? && !other.var?
    if self.typename == other.typename && self.typeargs.size == other.typeargs.size
      self.typeargs.zip(other.typeargs).each{|t1, t2| t1.unify(t2)}
    else
      raise UnifyError.new(nil, nil)
    end
  elsif !self.var? && other.var?
    other.collect_union.each do |t|
      self.occur_check(t)
      t.transform(self)
    end
  elsif self.var? && !other.var?
    self.collect_union.each do |t|
      other.occur_check(t)
      t.transform(other)
    end
  else
    self.unite(self, other)
  end
rescue UnifyError => err
  raise UnifyError.new(self, other)
end

#unite(a, b) ⇒ Object



85
86
87
88
89
90
91
# File 'lib/emfrp/typing/union_type.rb', line 85

def unite(a, b)
  new_union = (a.collect_union + b.collect_union).uniq
  substitute_id = new_union.map{|t| t.name_id}.min
  new_union.each{|t| t.name_id = substitute_id}
  a.union = new_union
  b.union = new_union
end

#var?Boolean

Returns:

  • (Boolean)


49
50
51
# File 'lib/emfrp/typing/union_type.rb', line 49

def var?
  @union
end