Class: Alf::Algebra::Signature

Inherits:
Object
  • Object
show all
Defined in:
lib/alf/algebra/support/signature.rb

Overview

Provides an operator signature

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(operator) {|_self| ... } ⇒ Signature

Creates an empty signature instance

Yields:

  • (_self)

Yield Parameters:


18
19
20
21
22
23
# File 'lib/alf/algebra/support/signature.rb', line 18

def initialize(operator)
  @operator = operator
  @arguments = []
  @options = []
  yield(self) if block_given?
end

Instance Attribute Details

#argumentsArray (readonly)


10
11
12
# File 'lib/alf/algebra/support/signature.rb', line 10

def arguments
  @arguments
end

#operatorClass (readonly)


7
8
9
# File 'lib/alf/algebra/support/signature.rb', line 7

def operator
  @operator
end

#optionsArray (readonly)


13
14
15
# File 'lib/alf/algebra/support/signature.rb', line 13

def options
  @options
end

Instance Method Details

#argument(name, domain, default = nil, descr = nil) ⇒ Object

Adds an argument to the signature


30
31
32
# File 'lib/alf/algebra/support/signature.rb', line 30

def argument(name, domain, default = nil, descr = nil)
  arguments << [name, domain, default, descr]
end

#collect_on(op) ⇒ Array

Collects signature values on a given operator.

This methods returns a triple `[datasets, arguments, options]` with the respective values collected on `op`.


128
129
130
131
132
133
134
135
136
# File 'lib/alf/algebra/support/signature.rb', line 128

def collect_on(op)
  oper = op.operands
  args = arguments.map{|name,_| op.send(name) }
  opts = Hash[options.map{|name,dom,defa,_|
    val = op.send(name)
    (val == defa) ? nil : [name, val]
  }.compact]
  [oper, args, opts]
end

#installHash

Installs the signature on the operator class

This method installs an attr reader and an attr writer for each signature argument and each signature option.


69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/alf/algebra/support/signature.rb', line 69

def install
  clazz = operator
  code = (arguments + options).each{|siginfo|
    name, domain, = siginfo
    clazz.send(:attr_reader, name)
    clazz.send(:define_method, :"#{name}=") do |val|
      instance_variable_set(:"@#{name}", Support.coerce(val, domain))
    end
    clazz.send(:private, :"#{name}=")
  }
  default_options
end

#option(name, domain, default = nil, descr = nil) ⇒ Object

Adds an option to the signature


39
40
41
# File 'lib/alf/algebra/support/signature.rb', line 39

def option(name, domain, default = nil, descr = nil)
  options << [name, domain, default, descr]
end

#option_parser(receiver, opt = OptionParser.new) ⇒ OptionParser

Builds an option parser instance `opt` prepared for installing options on `receiver`.


49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/alf/algebra/support/signature.rb', line 49

def option_parser(receiver, opt = OptionParser.new)
  options.each do |option|
    name, dom, defa, descr = option
    opt.on(option_name(option), descr || "") do |val|
      if receiver.is_a?(Hash)
        receiver[name] = val
      else
        receiver.send(:"#{name}=", val)
      end
    end
  end
  opt
end

#parse_args(args, receiver) ⇒ Operator

Parses arguments `args` passed to the operator `initialize` and sets attributes accordingly on `receiver`.


88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/alf/algebra/support/signature.rb', line 88

def parse_args(args, receiver)

  # 1) Check and set operands, passed as an array as first argument
  invalid_args!(args) unless args.first.is_a?(Array)
  receiver.send(:operands=, args.shift.map{|op| Operand.coerce(op)})

  # 2) Extract options if provided
  optargs = default_options
  if args.size == (1+arguments.size)
    # options are passed as last argument
    invalid_args!(args) unless args.last.is_a?(Hash)
    optargs = optargs.merge(args.pop)
  elsif args.size > arguments.size
    # too many arguments here
    invalid_args!(args)
  end

  # 3) Set options now, including default ones
  optargs.each_pair do |name,val|
    receiver.send(:"#{name}=", val)
  end

  # 4) Parse other arguments now
  with_each_arg(args) do |name,dom,value|
    invalid_args!(args) if value.nil?
    receiver.send(:"#{name}=", value)
  end

  receiver
end

#to_lispyObject

Returns a lispy synopsis for this signature

Example:

Alf::Algebra::Project.signature.to_shell
# => "(project operand, attributes:AttrList, {allbut: Boolean})"

144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/alf/algebra/support/signature.rb', line 144

def to_lispy
  cmd  = operator.rubycase_name
  oper = operator.nullary? ? "" : (operator.unary? ? "operand" : "left, right")

  args = arguments.map{|name,dom,_|
    dom = dom.to_s[/::([A-Za-z]+)$/, 1] || dom.to_s
    "#{name}:#{dom}"
  }.join(", ")
  args = (args.empty? ? "#{oper}" : "#{oper}, #{args}").strip

  opts = options.map{|name,dom,_|
    dom = dom.to_s[/::([A-Za-z]+)$/, 1] || dom.to_s
    "#{name}: #{dom}"
  }.join(', ')
  opts = opts.empty? ? "" : "{#{opts}}"

  argopt = [args, opts].select{|s| !s.empty?}.join(', ')
  "#{cmd}(#{argopt}".strip + ")"
end