predicate 2.3.2 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -0
  3. data/LICENSE.md +17 -19
  4. data/README.md +435 -0
  5. data/bin/g +2 -0
  6. data/lib/predicate/dsl.rb +138 -0
  7. data/lib/predicate/factory.rb +142 -37
  8. data/lib/predicate/grammar.rb +11 -2
  9. data/lib/predicate/grammar.sexp.yml +29 -0
  10. data/lib/predicate/nodes/${op_name}.rb.jeny +12 -0
  11. data/lib/predicate/nodes/and.rb +9 -0
  12. data/lib/predicate/nodes/binary_func.rb +20 -0
  13. data/lib/predicate/nodes/contradiction.rb +2 -7
  14. data/lib/predicate/nodes/dyadic_comp.rb +1 -3
  15. data/lib/predicate/nodes/empty.rb +14 -0
  16. data/lib/predicate/nodes/eq.rb +11 -3
  17. data/lib/predicate/nodes/expr.rb +9 -3
  18. data/lib/predicate/nodes/has_size.rb +14 -0
  19. data/lib/predicate/nodes/identifier.rb +1 -3
  20. data/lib/predicate/nodes/in.rb +7 -6
  21. data/lib/predicate/nodes/intersect.rb +3 -23
  22. data/lib/predicate/nodes/literal.rb +1 -3
  23. data/lib/predicate/nodes/match.rb +1 -21
  24. data/lib/predicate/nodes/nadic_bool.rb +1 -3
  25. data/lib/predicate/nodes/native.rb +1 -3
  26. data/lib/predicate/nodes/not.rb +1 -3
  27. data/lib/predicate/nodes/opaque.rb +1 -3
  28. data/lib/predicate/nodes/qualified_identifier.rb +1 -3
  29. data/lib/predicate/nodes/set_op.rb +26 -0
  30. data/lib/predicate/nodes/subset.rb +11 -0
  31. data/lib/predicate/nodes/superset.rb +11 -0
  32. data/lib/predicate/nodes/tautology.rb +6 -7
  33. data/lib/predicate/nodes/unary_func.rb +16 -0
  34. data/lib/predicate/nodes/var.rb +46 -0
  35. data/lib/predicate/processors/qualifier.rb +4 -0
  36. data/lib/predicate/processors/renamer.rb +4 -0
  37. data/lib/predicate/processors/to_s.rb +28 -0
  38. data/lib/predicate/processors/unqualifier.rb +21 -0
  39. data/lib/predicate/processors.rb +1 -0
  40. data/lib/predicate/sequel/to_sequel.rb +4 -1
  41. data/lib/predicate/sugar.rb +47 -0
  42. data/lib/predicate/version.rb +2 -2
  43. data/lib/predicate.rb +26 -2
  44. data/spec/dsl/test_dsl.rb +204 -0
  45. data/spec/dsl/test_evaluate.rb +65 -0
  46. data/spec/dsl/test_respond_to_missing.rb +35 -0
  47. data/spec/dsl/test_to_skake_case.rb +38 -0
  48. data/spec/factory/shared/a_comparison_factory_method.rb +1 -0
  49. data/spec/factory/test_${op_name}.rb.jeny +12 -0
  50. data/spec/factory/test_comp.rb +28 -5
  51. data/spec/factory/test_empty.rb +11 -0
  52. data/spec/factory/test_has_size.rb +11 -0
  53. data/spec/factory/test_match.rb +1 -0
  54. data/spec/factory/test_set_ops.rb +18 -0
  55. data/spec/factory/test_var.rb +22 -0
  56. data/spec/factory/test_vars.rb +27 -0
  57. data/spec/nodes/${op_name}.jeny/test_evaluate.rb.jeny +19 -0
  58. data/spec/nodes/empty/test_evaluate.rb +42 -0
  59. data/spec/nodes/has_size/test_evaluate.rb +44 -0
  60. data/spec/predicate/test_and_split.rb +18 -0
  61. data/spec/predicate/test_attr_split.rb +18 -0
  62. data/spec/predicate/test_constant_variables.rb +24 -2
  63. data/spec/predicate/test_constants.rb +24 -0
  64. data/spec/predicate/test_evaluate.rb +205 -3
  65. data/spec/predicate/test_free_variables.rb +1 -1
  66. data/spec/predicate/test_to_hash.rb +40 -0
  67. data/spec/predicate/test_to_s.rb +37 -0
  68. data/spec/predicate/test_unqualify.rb +18 -0
  69. data/spec/sequel/test_to_sequel.rb +25 -0
  70. data/spec/shared/a_predicate.rb +30 -0
  71. data/spec/spec_helper.rb +1 -0
  72. data/spec/test_predicate.rb +78 -33
  73. data/spec/test_readme.rb +80 -0
  74. data/spec/test_sugar.rb +48 -0
  75. data/tasks/test.rake +3 -3
  76. metadata +45 -14
  77. data/spec/factory/test_between.rb +0 -12
  78. data/spec/factory/test_intersect.rb +0 -12
@@ -1,78 +1,199 @@
1
1
  class Predicate
2
2
  module Factory
3
3
 
4
+ public # Boolean
5
+
6
+ # Factors a Predicate that captures True
4
7
  def tautology
5
8
  _factor_predicate([:tautology, true])
6
9
  end
7
10
 
11
+ # Factors a Predicate that captures False
8
12
  def contradiction
9
13
  _factor_predicate([:contradiction, false])
10
14
  end
11
15
 
16
+ public # Literals
17
+
18
+ # Factors a Literal node for some ruby value.
19
+ def literal(literal)
20
+ _factor_predicate([:literal, literal])
21
+ end
22
+
23
+ public # Vars & identifiers
24
+
25
+ # Factors a var node, using a given extractor semantics
26
+ def var(formaldef, semantics = :dig)
27
+ _factor_predicate([:var, formaldef, semantics])
28
+ end
29
+
30
+ # Factors a couple of variables at once. The semantics can
31
+ # be passed as a Symbol as last argument and defaults to :dig
32
+ def vars(*args)
33
+ args << :dig unless args.last.is_a?(Symbol)
34
+ args[0...-1].map{|v| var(v, args.last) }
35
+ end
36
+
37
+ # Factors a Predicate for a free variable whose
38
+ # name is provided. If the variable is a Boolean
39
+ # variable, this is a valid Predicate, otherwise
40
+ # it must be used in a higher-level expression.
12
41
  def identifier(name)
13
42
  _factor_predicate([:identifier, name])
14
43
  end
15
44
 
45
+ # Factors a Predicate for a qualified free variable.
46
+ # Same remark as in `identifier`.
16
47
  def qualified_identifier(qualifier, name)
17
48
  _factor_predicate([:qualified_identifier, qualifier, name])
18
49
  end
19
50
 
51
+ # Builds and returns a placeholder that can be used
52
+ # everywhere a literal can be used. Placeholders can
53
+ # be bound later, using `Predicate#bind`.
20
54
  def placeholder
21
55
  Placeholder.new
22
56
  end
23
57
 
58
+ public # Boolean logic
59
+
60
+ # Builds a AND predicate using two sub predicates.
61
+ #
62
+ # Please favor `Predicate#&` instead.
24
63
  def and(left, right = nil)
25
64
  _factor_predicate([:and, sexpr(left), sexpr(right)])
26
65
  end
27
66
 
67
+ # Builds a OR predicate using two sub predicates.
68
+ #
69
+ # Please favor `Predicate#|` instead.
28
70
  def or(left, right = nil)
29
71
  _factor_predicate([:or, sexpr(left), sexpr(right)])
30
72
  end
31
73
 
74
+ # Negates an existing predicate.
75
+ #
76
+ # Please favor `Predicate#!` instead.
32
77
  def not(operand)
33
78
  _factor_predicate([:not, sexpr(operand)])
34
79
  end
35
80
 
81
+ public # Comparison operators
82
+
83
+ # :nodoc:
84
+ def comp(op, h)
85
+ from_hash(h, op)
86
+ end
87
+
88
+ # Factors =, !=, <, <=, >, >= predicates between
89
+ # a variable and either a literal or another variable.
90
+ [ :eq, :neq, :lt, :lte, :gt, :gte ].each do |m|
91
+ define_method(m) do |left, right|
92
+ _factor_predicate([m, sexpr(left), sexpr(right)])
93
+ end
94
+ end
95
+
96
+ # Set operators
97
+
98
+ # Factors a IN predicate between a variable and
99
+ # either a list of values of another variable.
36
100
  def in(left, right)
37
- left, right = sexpr(left), sexpr(right)
38
- if right.literal? && right.empty_value?
39
- contradiction
101
+ case right
102
+ when Range
103
+ return contradiction if right.size == 0
104
+ rl = gte(left, right.begin)
105
+ rr = right.exclude_end? ? lt(left, right.end) : lte(left, right.end)
106
+ self.and(rl, rr)
40
107
  else
41
- _factor_predicate([:in, left, right])
108
+ left, right = sexpr(left), sexpr(right)
109
+ if right.literal? && right.empty_value?
110
+ contradiction
111
+ else
112
+ _factor_predicate([:in, left, right])
113
+ end
42
114
  end
43
115
  end
44
116
  alias :among :in
45
117
 
46
- def intersect(identifier, values)
47
- identifier = sexpr(identifier) if identifier.is_a?(Symbol)
48
- _factor_predicate([:intersect, identifier, values])
118
+ # Factors an INTERSECT predicate between a
119
+ # variable and a list of values.
120
+ [:intersect, :subset, :superset].each do |name|
121
+ define_method(name) do |left, right|
122
+ identifier = sexpr(identifier) if identifier.is_a?(Symbol)
123
+ _factor_predicate([name, sexpr(left), sexpr(right)])
124
+ end
49
125
  end
50
126
 
51
- def comp(op, h)
52
- from_hash(h, op)
127
+ public # Other operators
128
+
129
+ # Factors a MATCH predicate between a variable
130
+ # and a literal or another variable.
131
+ #
132
+ # Matching options can be passes and are specific
133
+ # to the actual usage of the library.
134
+ def match(left, right, options)
135
+ s = [:match, sexpr(left), sexpr(right)]
136
+ s << options unless options.nil?
137
+ _factor_predicate(s)
53
138
  end
54
139
 
55
- [ :eq, :neq, :lt, :lte, :gt, :gte ].each do |m|
56
- define_method(m) do |left, right=nil|
57
- return comp(m, left) if TupleLike===left && right.nil?
58
- _factor_predicate([m, sexpr(left), sexpr(right)])
59
- end
140
+ # Factors an EMPTY predicate that responds true
141
+ # when its operand is something empty.
142
+ #
143
+ # Default evaluation uses ruby `empty?` method.
144
+ def empty(operand)
145
+ _factor_predicate([:empty, sexpr(operand)])
146
+ end
147
+
148
+ # Factors a SIZE predicate that responds true when
149
+ # its operand has a size meeting the right constraint
150
+ # (typically a Range literal)
151
+ def has_size(left, right)
152
+ _factor_predicate([:has_size, sexpr(left), sexpr(right)])
153
+ end
154
+
155
+ #jeny(predicate) # TODO
156
+ #jeny(predicate) def ${op_name}(*args)
157
+ #jeny(predicate) args = args.map{|arg| sexpr(arg) }
158
+ #jeny(predicate) _factor_predicate([:${op_name}] + args)
159
+ #jeny(predicate) end
160
+
161
+ public # Low-level
162
+
163
+ # Factors a predicate from a mapping between variables
164
+ # and values. This typically generates a AND(EQ)
165
+ # predicate, but a value can be an Array (IN) or a
166
+ # Regexp (MATCH).
167
+ def h(h)
168
+ from_hash(h, :eq)
60
169
  end
61
170
 
62
- def between(middle, lower_bound, upper_bound)
63
- _factor_predicate [:and, [:gte, sexpr(middle), sexpr(lower_bound)],
64
- [:lte, sexpr(middle), sexpr(upper_bound)]]
171
+ # Factors a predicate for a ruby Proc that returns
172
+ # truth-value for a single argument.
173
+ def native(arg)
174
+ _factor_predicate([:native, arg])
65
175
  end
66
176
 
177
+ # Converts `arg` to an opaque predicate, whose semantics
178
+ # depends on the actual usage of the library.
179
+ def opaque(arg)
180
+ _factor_predicate([:opaque, arg])
181
+ end
182
+
183
+ public # Semi protected
184
+
185
+ # Builds a AND predicate between all key/value pairs
186
+ # of the provided Hash, using the comparison operator
187
+ # specified.
67
188
  def from_hash(h, op = :eq)
68
189
  if h.empty?
69
190
  tautology
70
191
  else
71
192
  terms = h.to_a.map{|(k,v)|
72
- if v.is_a?(Array)
73
- [:in, sexpr(k), sexpr(v)]
74
- else
75
- [op, sexpr(k), sexpr(v)]
193
+ case v
194
+ when Array then [:in, sexpr(k), sexpr(v)]
195
+ when Regexp then [:match, sexpr(k), sexpr(v) ]
196
+ else [op, sexpr(k), sexpr(v)]
76
197
  end
77
198
  }
78
199
  terms = terms.size == 1 ? terms.first : terms.unshift(:and)
@@ -80,22 +201,6 @@ class Predicate
80
201
  end
81
202
  end
82
203
 
83
- def literal(literal)
84
- _factor_predicate([:literal, literal])
85
- end
86
-
87
- def opaque(arg)
88
- _factor_predicate([:opaque, arg])
89
- end
90
-
91
- def match(left, right, options = nil)
92
- _factor_predicate([:match, sexpr(left), sexpr(right)] + (options.nil? ? [] : [options]))
93
- end
94
-
95
- def native(arg)
96
- _factor_predicate([:native, arg])
97
- end
98
-
99
204
  protected
100
205
 
101
206
  def sexpr(expr)
@@ -10,13 +10,14 @@ class Predicate
10
10
  Expr
11
11
  end
12
12
 
13
- end
13
+ end # module Grammar
14
14
  end # class Predicate
15
15
  require_relative 'nodes/expr'
16
16
  require_relative 'nodes/dyadic_comp'
17
17
  require_relative 'nodes/nadic_bool'
18
18
  require_relative 'nodes/tautology'
19
19
  require_relative 'nodes/contradiction'
20
+ require_relative 'nodes/var'
20
21
  require_relative 'nodes/identifier'
21
22
  require_relative 'nodes/qualified_identifier'
22
23
  require_relative 'nodes/and'
@@ -29,8 +30,16 @@ require_relative 'nodes/gte'
29
30
  require_relative 'nodes/lt'
30
31
  require_relative 'nodes/lte'
31
32
  require_relative 'nodes/in'
33
+ require_relative 'nodes/set_op'
32
34
  require_relative 'nodes/intersect'
35
+ require_relative 'nodes/subset'
36
+ require_relative 'nodes/superset'
33
37
  require_relative 'nodes/literal'
34
- require_relative 'nodes/match'
35
38
  require_relative 'nodes/native'
36
39
  require_relative 'nodes/opaque'
40
+ require_relative 'nodes/unary_func'
41
+ require_relative 'nodes/binary_func'
42
+ require_relative 'nodes/match'
43
+ require_relative 'nodes/empty'
44
+ require_relative 'nodes/has_size'
45
+ #jeny(predicate) require_relative 'nodes/${op_name}'
@@ -3,6 +3,8 @@ rules:
3
3
  - tautology
4
4
  - contradiction
5
5
  - identifier
6
+ - qualified_identifier
7
+ - var
6
8
  - not
7
9
  - and
8
10
  - or
@@ -14,8 +16,13 @@ rules:
14
16
  - gte
15
17
  - in
16
18
  - intersect
19
+ - subset
20
+ - superset
17
21
  - match
18
22
  - native
23
+ - empty
24
+ - has_size
25
+ #jeny(predicate) - ${op_name}
19
26
  tautology:
20
27
  - [ true ]
21
28
  contradiction:
@@ -24,6 +31,8 @@ rules:
24
31
  - [ name ]
25
32
  qualified_identifier:
26
33
  - [ name, name ]
34
+ var:
35
+ - [ formaldef, semantics ]
27
36
  not:
28
37
  - [ predicate ]
29
38
  and:
@@ -46,8 +55,18 @@ rules:
46
55
  - [ varref, term ]
47
56
  intersect:
48
57
  - [ term, term ]
58
+ subset:
59
+ - [ term, term ]
60
+ superset:
61
+ - [ term, term ]
49
62
  match:
50
63
  - [ term, term, options ]
64
+ empty:
65
+ - [ term ]
66
+ has_size:
67
+ - [ term, term ]
68
+ #jeny(predicate) ${op_name}:
69
+ #jeny(predicate) - [ TODO ]
51
70
  term:
52
71
  - varref
53
72
  - literal
@@ -56,6 +75,7 @@ rules:
56
75
  varref:
57
76
  - qualified_identifier
58
77
  - identifier
78
+ - var
59
79
  native:
60
80
  - [ "::Proc" ]
61
81
  literal:
@@ -68,3 +88,12 @@ rules:
68
88
  - "::Hash"
69
89
  name:
70
90
  !ruby/regexp /^[a-zA-Z0-9_]+[?!]?$/
91
+ semantics:
92
+ !ruby/regexp /^(dig)$/
93
+ formaldef:
94
+ - string_formaldef
95
+ - array_formaldef
96
+ string_formaldef:
97
+ - "::String"
98
+ array_formaldef:
99
+ - "::Array"
@@ -0,0 +1,12 @@
1
+ #jeny(predicate)
2
+ class Predicate
3
+ module ${OpName}
4
+ include ${Arity}Func
5
+
6
+ def evaluate(tuple)
7
+ # TODO: implement this
8
+ raise NotImplementedError
9
+ end
10
+
11
+ end
12
+ end
@@ -53,5 +53,14 @@ class Predicate
53
53
  sexpr_body.all?{|operand| operand.evaluate(tuple) }
54
54
  end
55
55
 
56
+ def to_hash
57
+ sexpr_body.inject({}) do |p,term|
58
+ p.merge(term.to_hash){|k,v1,v2|
59
+ super unless v1 == v2
60
+ v1
61
+ }
62
+ end
63
+ end
64
+
56
65
  end
57
66
  end
@@ -0,0 +1,20 @@
1
+ class Predicate
2
+ module BinaryFunc
3
+ include Expr
4
+
5
+ def priority; 80; end
6
+
7
+ def left
8
+ self[1]
9
+ end
10
+
11
+ def right
12
+ self[2]
13
+ end
14
+
15
+ def free_variables
16
+ @free_variables ||= left.free_variables | right.free_variables
17
+ end
18
+
19
+ end
20
+ end
@@ -18,13 +18,8 @@ class Predicate
18
18
  other
19
19
  end
20
20
 
21
- def dyadic_priority
22
- 1000
23
- end
24
-
25
- def priority
26
- 100
27
- end
21
+ def dyadic_priority; 1000; end
22
+ def priority; 100; end
28
23
 
29
24
  def free_variables
30
25
  @free_variables ||= []
@@ -2,9 +2,7 @@ class Predicate
2
2
  module DyadicComp
3
3
  include Expr
4
4
 
5
- def priority
6
- 50
7
- end
5
+ def priority; 50; end
8
6
 
9
7
  def !
10
8
  Factory.send(OP_NEGATIONS[first], self[1], self[2])
@@ -0,0 +1,14 @@
1
+ class Predicate
2
+ module Empty
3
+ include UnaryFunc
4
+
5
+ def evaluate(tuple)
6
+ value = operand.evaluate(tuple)
7
+ unless value.respond_to?(:empty?)
8
+ raise TypeError, "Expected #{value} to respond to empty?"
9
+ end
10
+ value.empty?
11
+ end
12
+
13
+ end
14
+ end
@@ -40,13 +40,21 @@ class Predicate
40
40
  end
41
41
  end
42
42
 
43
- def dyadic_priority
44
- 900
45
- end
43
+ def dyadic_priority; 900; end
46
44
 
47
45
  def evaluate(tuple)
48
46
  left.evaluate(tuple) == right.evaluate(tuple)
49
47
  end
50
48
 
49
+ def to_hash
50
+ if left.identifier? && right.literal? && !right.has_placeholder?
51
+ { left.name => right.value }
52
+ elsif right.identifier? && left.literal? && !left.has_placeholder?
53
+ { right.name => left.value }
54
+ else
55
+ super
56
+ end
57
+ end
58
+
51
59
  end
52
60
  end
@@ -35,9 +35,7 @@ class Predicate
35
35
  sexpr([:not, self])
36
36
  end
37
37
 
38
- def dyadic_priority
39
- 0
40
- end
38
+ def dyadic_priority; 0; end
41
39
 
42
40
  def &(other)
43
41
  return other if other.contradiction?
@@ -77,6 +75,10 @@ class Predicate
77
75
  Qualifier.new(qualifier).call(self)
78
76
  end
79
77
 
78
+ def unqualify
79
+ Unqualifier.new.call(self)
80
+ end
81
+
80
82
  def bind(binding)
81
83
  Binder.new(binding).call(self)
82
84
  end
@@ -93,6 +95,10 @@ class Predicate
93
95
  ToS.call(self, scope: scope)
94
96
  end
95
97
 
98
+ def to_hash
99
+ raise ArgumentError, "Unable to represent #{self} to a Hash"
100
+ end
101
+
96
102
  def sexpr(arg)
97
103
  Factory.sexpr(arg)
98
104
  end
@@ -0,0 +1,14 @@
1
+ class Predicate
2
+ module HasSize
3
+ include BinaryFunc
4
+
5
+ def evaluate(tuple)
6
+ l, r = left.evaluate(tuple), right.evaluate(tuple)
7
+ r = r..r if r.is_a?(Integer)
8
+ raise Error, "Expected Range, got #{r}" unless r.is_a?(Range)
9
+ raise Error, "Expected #{l} to respond to :size" unless l.respond_to?(:size)
10
+ r === l.size
11
+ end
12
+
13
+ end
14
+ end
@@ -2,9 +2,7 @@ class Predicate
2
2
  module Identifier
3
3
  include Expr
4
4
 
5
- def priority
6
- 100
7
- end
5
+ def priority; 100; end
8
6
 
9
7
  def name
10
8
  self[1]
@@ -2,9 +2,7 @@ class Predicate
2
2
  module In
3
3
  include Expr
4
4
 
5
- def priority
6
- 80
7
- end
5
+ def priority; 80; end
8
6
 
9
7
  def left
10
8
  self[1]
@@ -61,9 +59,7 @@ class Predicate
61
59
  end
62
60
  end
63
61
 
64
- def dyadic_priority
65
- 800
66
- end
62
+ def dyadic_priority; 800; end
67
63
 
68
64
  def evaluate(tuple)
69
65
  values = right.evaluate(tuple)
@@ -75,5 +71,10 @@ class Predicate
75
71
  left.identifier? && right.literal? && !right.has_placeholder?
76
72
  end
77
73
 
74
+ def to_hash
75
+ return super unless var_against_literal_value?
76
+ { identifier.name => right.value }
77
+ end
78
+
78
79
  end
79
80
  end
@@ -1,30 +1,10 @@
1
1
  class Predicate
2
2
  module Intersect
3
- include Expr
4
-
5
- def priority
6
- 80
7
- end
8
-
9
- def identifier
10
- self[1]
11
- end
12
-
13
- def values
14
- self[2]
15
- end
16
-
17
- def free_variables
18
- @free_variables ||= identifier.free_variables
19
- end
20
-
21
- def constant_variables
22
- []
23
- end
3
+ include SetOp
24
4
 
25
5
  def evaluate(tuple)
26
- t_x = identifier.evaluate(tuple)
27
- t_x && !(t_x & values).empty?
6
+ x, y = left.evaluate(tuple), right.evaluate(tuple)
7
+ x && y && !(x & y).empty?
28
8
  end
29
9
 
30
10
  end
@@ -2,9 +2,7 @@ class Predicate
2
2
  module Literal
3
3
  include Expr
4
4
 
5
- def priority
6
- 100
7
- end
5
+ def priority; 100; end
8
6
 
9
7
  def free_variables
10
8
  @free_variables ||= []
@@ -1,23 +1,11 @@
1
1
  class Predicate
2
2
  module Match
3
- include Expr
3
+ include BinaryFunc
4
4
 
5
5
  DEFAULT_OPTIONS = {
6
6
  case_sensitive: true
7
7
  }
8
8
 
9
- def priority
10
- 80
11
- end
12
-
13
- def left
14
- self[1]
15
- end
16
-
17
- def right
18
- self[2]
19
- end
20
-
21
9
  def options
22
10
  @options ||= DEFAULT_OPTIONS.merge(self[3] || {})
23
11
  end
@@ -26,14 +14,6 @@ class Predicate
26
14
  options[:case_sensitive]
27
15
  end
28
16
 
29
- def free_variables
30
- @free_variables ||= left.free_variables | right.free_variables
31
- end
32
-
33
- def dyadic_priority
34
- 800
35
- end
36
-
37
17
  def evaluate(tuple)
38
18
  l = left.evaluate(tuple)
39
19
  r = right.evaluate(tuple)
@@ -2,9 +2,7 @@ class Predicate
2
2
  module NadicBool
3
3
  include Expr
4
4
 
5
- def priority
6
- 60
7
- end
5
+ def priority; 60; end
8
6
 
9
7
  def free_variables
10
8
  @free_variables ||= sexpr_body.inject([]){|list,term|
@@ -2,9 +2,7 @@ class Predicate
2
2
  module Native
3
3
  include Expr
4
4
 
5
- def priority
6
- 90
7
- end
5
+ def priority; 90; end
8
6
 
9
7
  def proc
10
8
  self[1]
@@ -6,9 +6,7 @@ class Predicate
6
6
  :'!'
7
7
  end
8
8
 
9
- def priority
10
- 90
11
- end
9
+ def priority; 90; end
12
10
 
13
11
  def !
14
12
  last
@@ -2,9 +2,7 @@ class Predicate
2
2
  module Opaque
3
3
  include Expr
4
4
 
5
- def priority
6
- 100
7
- end
5
+ def priority; 100; end
8
6
 
9
7
  def free_variables
10
8
  @free_variables ||= []