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.
- checksums.yaml +4 -4
- data/Gemfile +4 -0
- data/LICENSE.md +17 -19
- data/README.md +435 -0
- data/bin/g +2 -0
- data/lib/predicate/dsl.rb +138 -0
- data/lib/predicate/factory.rb +142 -37
- data/lib/predicate/grammar.rb +11 -2
- data/lib/predicate/grammar.sexp.yml +29 -0
- data/lib/predicate/nodes/${op_name}.rb.jeny +12 -0
- data/lib/predicate/nodes/and.rb +9 -0
- data/lib/predicate/nodes/binary_func.rb +20 -0
- data/lib/predicate/nodes/contradiction.rb +2 -7
- data/lib/predicate/nodes/dyadic_comp.rb +1 -3
- data/lib/predicate/nodes/empty.rb +14 -0
- data/lib/predicate/nodes/eq.rb +11 -3
- data/lib/predicate/nodes/expr.rb +9 -3
- data/lib/predicate/nodes/has_size.rb +14 -0
- data/lib/predicate/nodes/identifier.rb +1 -3
- data/lib/predicate/nodes/in.rb +7 -6
- data/lib/predicate/nodes/intersect.rb +3 -23
- data/lib/predicate/nodes/literal.rb +1 -3
- data/lib/predicate/nodes/match.rb +1 -21
- data/lib/predicate/nodes/nadic_bool.rb +1 -3
- data/lib/predicate/nodes/native.rb +1 -3
- data/lib/predicate/nodes/not.rb +1 -3
- data/lib/predicate/nodes/opaque.rb +1 -3
- data/lib/predicate/nodes/qualified_identifier.rb +1 -3
- data/lib/predicate/nodes/set_op.rb +26 -0
- data/lib/predicate/nodes/subset.rb +11 -0
- data/lib/predicate/nodes/superset.rb +11 -0
- data/lib/predicate/nodes/tautology.rb +6 -7
- data/lib/predicate/nodes/unary_func.rb +16 -0
- data/lib/predicate/nodes/var.rb +46 -0
- data/lib/predicate/processors/qualifier.rb +4 -0
- data/lib/predicate/processors/renamer.rb +4 -0
- data/lib/predicate/processors/to_s.rb +28 -0
- data/lib/predicate/processors/unqualifier.rb +21 -0
- data/lib/predicate/processors.rb +1 -0
- data/lib/predicate/sequel/to_sequel.rb +4 -1
- data/lib/predicate/sugar.rb +47 -0
- data/lib/predicate/version.rb +2 -2
- data/lib/predicate.rb +26 -2
- data/spec/dsl/test_dsl.rb +204 -0
- data/spec/dsl/test_evaluate.rb +65 -0
- data/spec/dsl/test_respond_to_missing.rb +35 -0
- data/spec/dsl/test_to_skake_case.rb +38 -0
- data/spec/factory/shared/a_comparison_factory_method.rb +1 -0
- data/spec/factory/test_${op_name}.rb.jeny +12 -0
- data/spec/factory/test_comp.rb +28 -5
- data/spec/factory/test_empty.rb +11 -0
- data/spec/factory/test_has_size.rb +11 -0
- data/spec/factory/test_match.rb +1 -0
- data/spec/factory/test_set_ops.rb +18 -0
- data/spec/factory/test_var.rb +22 -0
- data/spec/factory/test_vars.rb +27 -0
- data/spec/nodes/${op_name}.jeny/test_evaluate.rb.jeny +19 -0
- data/spec/nodes/empty/test_evaluate.rb +42 -0
- data/spec/nodes/has_size/test_evaluate.rb +44 -0
- data/spec/predicate/test_and_split.rb +18 -0
- data/spec/predicate/test_attr_split.rb +18 -0
- data/spec/predicate/test_constant_variables.rb +24 -2
- data/spec/predicate/test_constants.rb +24 -0
- data/spec/predicate/test_evaluate.rb +205 -3
- data/spec/predicate/test_free_variables.rb +1 -1
- data/spec/predicate/test_to_hash.rb +40 -0
- data/spec/predicate/test_to_s.rb +37 -0
- data/spec/predicate/test_unqualify.rb +18 -0
- data/spec/sequel/test_to_sequel.rb +25 -0
- data/spec/shared/a_predicate.rb +30 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/test_predicate.rb +78 -33
- data/spec/test_readme.rb +80 -0
- data/spec/test_sugar.rb +48 -0
- data/tasks/test.rake +3 -3
- metadata +45 -14
- data/spec/factory/test_between.rb +0 -12
- data/spec/factory/test_intersect.rb +0 -12
data/lib/predicate/factory.rb
CHANGED
@@ -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
|
-
|
38
|
-
|
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
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
52
|
-
|
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
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
-
|
63
|
-
|
64
|
-
|
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
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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)
|
data/lib/predicate/grammar.rb
CHANGED
@@ -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"
|
data/lib/predicate/nodes/and.rb
CHANGED
@@ -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
|
data/lib/predicate/nodes/eq.rb
CHANGED
@@ -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
|
data/lib/predicate/nodes/expr.rb
CHANGED
@@ -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
|
data/lib/predicate/nodes/in.rb
CHANGED
@@ -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
|
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
|
-
|
27
|
-
|
6
|
+
x, y = left.evaluate(tuple), right.evaluate(tuple)
|
7
|
+
x && y && !(x & y).empty?
|
28
8
|
end
|
29
9
|
|
30
10
|
end
|
@@ -1,23 +1,11 @@
|
|
1
1
|
class Predicate
|
2
2
|
module Match
|
3
|
-
include
|
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)
|
data/lib/predicate/nodes/not.rb
CHANGED