Module: Eventbox::ArgumentWrapper

Defined in:
lib/eventbox/argument_wrapper.rb

Class Method Summary collapse

Class Method Details

.build(method, name) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/eventbox/argument_wrapper.rb', line 5

def self.build(method, name)
  parameters = method.parameters
  if parameters.find { |t, n| n.to_s.start_with?("") }

    # Change a Proc object to a Method, so that we are able to differ between :opt and :req parameters.
    # This is because Ruby (wrongly IMHO) reports required parameters as optional.
    # The only way to get the true parameter types is through define_method.
    is_proc = Proc === method
    if is_proc
      cl = Class.new do
        define_method(:to_method, &method)
      end
      method = cl.instance_method(:to_method)
      parameters = method.parameters
    end

    decls = []
    convs = []
    rets = []
    parameters.each_with_index do |(t, n), i|
      €var = n.to_s.start_with?("")
      case t
      when :req
        decls << n
        if €var
          convs << "#{n} = WrappedObject.new(#{n}, source_event_loop, :#{n})"
        end
        rets << n
      when :opt
        decls << "#{n}=nil"
        if €var
          convs << "#{n} = #{n} ? WrappedObject.new(#{n}, source_event_loop, :#{n}) : []"
        end
        rets << "*#{n}"
      when :rest
        decls << "*#{n}"
        if €var
          convs << "#{n}.map!{|v| WrappedObject.new(v, source_event_loop, :#{n}) }"
        end
        rets << "*#{n}"
      when :keyreq
        decls << "#{n}:"
        if €var
          convs << "#{n} = WrappedObject.new(#{n}, source_event_loop, :#{n})"
        end
        rets << "#{n}: #{n}"
      when :key
        decls << "#{n}:nil"
        if €var
          convs << "#{n} = #{n} ? {#{n}: WrappedObject.new(#{n}, source_event_loop, :#{n})} : {}"
        else
          convs << "#{n} = #{n} ? {#{n}: #{n}} : {}"
        end
        rets << "**#{n}"
      when :keyrest
        decls << "**#{n}"
        if €var
          convs << "#{n}.each{|k, v| #{n}[k] = WrappedObject.new(v, source_event_loop, :#{n}) }"
        end
        rets << "**#{n}"
      when :block
        if €var
          raise "block to `#{name}' can't be wrapped"
        end
      end
    end
    code = "#{is_proc ? :proc : :lambda} do |source_event_loop#{decls.map{|s| ",#{s}"}.join }| # #{name}\n  #{convs.join("\n")}\n  [#{rets.join(",")}]\nend"
    instance_eval(code, "wrapper code defined in #{__FILE__}:#{__LINE__} for #{name}")
  end
end