Module: Cube::Interface

Defined in:
lib/cube/interfaces.rb

Defined Under Namespace

Classes: InterfaceMatchError, MethodArityError, MethodMissing, PrivateVisibleMethodMissing, PublicVisibleMethodMissing, TypeMismatchError

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.match_specs(i1specs, i2specs) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/cube/interfaces.rb', line 13

def self.match_specs(i1specs, i2specs)
  i1specs.each do |meth, i1spec|
    i2spec = i2specs[meth]
    raise InterfaceMatchError, "Method `#{meth}` not found" unless i2spec
    i2_in = i2spec[:in]
    i1_in = i1spec[:in]
    if i1_in && (!i2_in || i1_in.size != i2_in.size)
      raise InterfaceMatchError, "Method `#{meth}` prototype does not match"
    end
    (i1_in || []).each_index do |i|
      Cube.check_type_spec(i1_in[i], i2_in[i]) { |t1, t2| t2 == t1 }
    end
    i1_out = i1spec[:out]
    if i1_out
      i2_out = i2spec[:out]
      raise InterfaceMatchError, "Method `#{meth}` prototype does not match" unless i2_out
      Cube.check_type_spec(i1_out, i2_out) { |t1, t2| t2 == t1 }
    end
  end
end

Instance Method Details

#assert_match(intf) ⇒ Object

Raises:

  • (ArgumentError)


206
207
208
209
210
211
# File 'lib/cube/interfaces.rb', line 206

def assert_match(intf)
  raise ArgumentError, "#{intf} is not a Cube::Interface" unless intf.is_a?(Interface)
  intf_specs = intf.to_spec
  self_specs = to_spec
  Interface.match_specs(self_specs, intf_specs)
end

#impotentObject



228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/cube/interfaces.rb', line 228

def impotent
  cl = Cube.interface {}.extend(self)
  cl.module_exec do
    def extend_object(mod)
      super
    end
    def append_features(mod)
      super
    end
  end
  cl
end

#proto(meth, *args) ⇒ Object



213
214
215
216
217
218
# File 'lib/cube/interfaces.rb', line 213

def proto(meth, *args)
  out_spec = yield if block_given?
  validate_spec(args)
  validate_spec(out_spec) if out_spec
  @ids.merge!({ meth.to_sym => { in: args, out: out_spec } })
end

#public_visible(*ids) ⇒ Object



220
221
222
223
224
225
226
# File 'lib/cube/interfaces.rb', line 220

def public_visible(*ids)
  unless ids.all? { |id| id.is_a?(Symbol) || id.is_a?(String) }
    raise ArgumentError, "Arguments should be strings or symbols"
  end
  spec = map_spec(ids)
  @ids.merge!(spec)
end

#required_public_methodsObject

Accepts an array of method names that define the interface. When this module is included/implemented, those method names must have already been defined.



193
194
195
# File 'lib/cube/interfaces.rb', line 193

def required_public_methods
  @ids.keys
end

#shellObject

creates a shell object for testing



242
243
244
245
246
247
248
249
250
251
# File 'lib/cube/interfaces.rb', line 242

def shell
  ids = @ids
  unreq = @unreq
  cls = Class.new(Object) do
    (ids.keys - unreq).each do |m|
      define_method(m) { |*args| }
    end
  end
  Cube[cls].send(:shell_implements, self)
end

#to_specObject



197
198
199
200
201
202
203
204
# File 'lib/cube/interfaces.rb', line 197

def to_spec
  inherited = (self.ancestors-[self]).select{ |x| Interface === x }
  inherited_ids = inherited.map{ |x| x.instance_variable_get('@ids') }

  # Store required method ids
  inherited_specs = map_spec(inherited_ids.flatten)
  @ids.merge(inherited_specs)
end