dry-logic 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -5
- data/CHANGELOG.md +28 -0
- data/Gemfile +7 -4
- data/dry-logic.gemspec +1 -0
- data/lib/dry/logic.rb +2 -3
- data/lib/dry/logic/appliable.rb +33 -0
- data/lib/dry/logic/evaluator.rb +2 -0
- data/lib/dry/logic/operations.rb +13 -0
- data/lib/dry/logic/operations/abstract.rb +44 -0
- data/lib/dry/logic/operations/and.rb +35 -0
- data/lib/dry/logic/operations/attr.rb +17 -0
- data/lib/dry/logic/operations/binary.rb +26 -0
- data/lib/dry/logic/operations/check.rb +52 -0
- data/lib/dry/logic/operations/each.rb +32 -0
- data/lib/dry/logic/operations/implication.rb +37 -0
- data/lib/dry/logic/operations/key.rb +66 -0
- data/lib/dry/logic/operations/negation.rb +18 -0
- data/lib/dry/logic/operations/or.rb +35 -0
- data/lib/dry/logic/operations/set.rb +35 -0
- data/lib/dry/logic/operations/unary.rb +24 -0
- data/lib/dry/logic/operations/xor.rb +27 -0
- data/lib/dry/logic/operators.rb +25 -0
- data/lib/dry/logic/predicates.rb +143 -136
- data/lib/dry/logic/result.rb +76 -33
- data/lib/dry/logic/rule.rb +62 -46
- data/lib/dry/logic/rule/predicate.rb +28 -0
- data/lib/dry/logic/rule_compiler.rb +16 -17
- data/lib/dry/logic/version.rb +1 -1
- data/spec/integration/result_spec.rb +59 -0
- data/spec/integration/rule_spec.rb +53 -0
- data/spec/shared/predicates.rb +6 -0
- data/spec/shared/rule.rb +67 -0
- data/spec/spec_helper.rb +10 -3
- data/spec/support/mutant.rb +9 -0
- data/spec/unit/operations/and_spec.rb +64 -0
- data/spec/unit/operations/attr_spec.rb +27 -0
- data/spec/unit/operations/check_spec.rb +49 -0
- data/spec/unit/operations/each_spec.rb +47 -0
- data/spec/unit/operations/implication_spec.rb +30 -0
- data/spec/unit/operations/key_spec.rb +119 -0
- data/spec/unit/operations/negation_spec.rb +40 -0
- data/spec/unit/operations/or_spec.rb +73 -0
- data/spec/unit/operations/set_spec.rb +41 -0
- data/spec/unit/operations/xor_spec.rb +61 -0
- data/spec/unit/predicates_spec.rb +23 -0
- data/spec/unit/rule/predicate_spec.rb +53 -0
- data/spec/unit/rule_compiler_spec.rb +38 -38
- data/spec/unit/rule_spec.rb +94 -0
- metadata +67 -40
- data/lib/dry/logic/predicate.rb +0 -100
- data/lib/dry/logic/predicate_set.rb +0 -23
- data/lib/dry/logic/result/each.rb +0 -20
- data/lib/dry/logic/result/multi.rb +0 -14
- data/lib/dry/logic/result/named.rb +0 -17
- data/lib/dry/logic/result/set.rb +0 -10
- data/lib/dry/logic/result/value.rb +0 -17
- data/lib/dry/logic/rule/attr.rb +0 -13
- data/lib/dry/logic/rule/check.rb +0 -40
- data/lib/dry/logic/rule/composite.rb +0 -91
- data/lib/dry/logic/rule/each.rb +0 -13
- data/lib/dry/logic/rule/key.rb +0 -37
- data/lib/dry/logic/rule/negation.rb +0 -15
- data/lib/dry/logic/rule/set.rb +0 -31
- data/lib/dry/logic/rule/value.rb +0 -48
- data/spec/unit/predicate_spec.rb +0 -115
- data/spec/unit/rule/attr_spec.rb +0 -29
- data/spec/unit/rule/check_spec.rb +0 -44
- data/spec/unit/rule/conjunction_spec.rb +0 -30
- data/spec/unit/rule/disjunction_spec.rb +0 -38
- data/spec/unit/rule/each_spec.rb +0 -31
- data/spec/unit/rule/exclusive_disjunction_spec.rb +0 -19
- data/spec/unit/rule/implication_spec.rb +0 -16
- data/spec/unit/rule/key_spec.rb +0 -121
- data/spec/unit/rule/set_spec.rb +0 -30
- data/spec/unit/rule/value_spec.rb +0 -99
@@ -0,0 +1,94 @@
|
|
1
|
+
RSpec.describe Dry::Logic::Rule do
|
2
|
+
subject(:rule) { Rule.new(predicate, options) }
|
3
|
+
|
4
|
+
let(:predicate) { -> { true } }
|
5
|
+
let(:options) { {} }
|
6
|
+
|
7
|
+
it_behaves_like Dry::Logic::Rule
|
8
|
+
|
9
|
+
describe '.new' do
|
10
|
+
it 'accepts an :id' do
|
11
|
+
expect(Rule.new(predicate, id: :check_num).id).to be(:check_num)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'with a function returning truthy value' do
|
16
|
+
it 'is successful for valid input' do
|
17
|
+
expect(Rule.new(-> val { val }).('true')).to be_success
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'is not successful for invalid input' do
|
21
|
+
expect(Rule.new(-> val { val }).(nil)).to be_failure
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#ast' do
|
26
|
+
it 'returns predicate node with :id' do
|
27
|
+
expect(Rule.new(-> value { true }).with(id: :email?).ast('oops')).to eql(
|
28
|
+
[:predicate, [:email?, [[:value, 'oops']]]]
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'returns predicate node with undefined args' do
|
33
|
+
expect(Rule.new(-> value { true }).with(id: :email?).ast).to eql(
|
34
|
+
[:predicate, [:email?, [[:value, Undefined]]]]
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#type' do
|
40
|
+
it 'returns rule type' do
|
41
|
+
expect(rule.type).to be(:rule)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#bind' do
|
46
|
+
let(:bound) { rule.with(id: :bound).bind(object) }
|
47
|
+
|
48
|
+
context 'with an unbound method' do
|
49
|
+
let(:predicate) { klass.instance_method(:test?) }
|
50
|
+
let(:klass) { Class.new { def test?; true; end } }
|
51
|
+
let(:object) { klass.new }
|
52
|
+
|
53
|
+
it 'returns a new rule with its predicate bound to a specific object' do
|
54
|
+
expect(bound.()).to be_success
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'carries id' do
|
58
|
+
expect(bound.id).to be(:bound)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'with an arbitrary block' do
|
63
|
+
let(:predicate) { -> value { value == expected } }
|
64
|
+
let(:object) { Class.new { def expected; 'test'; end }.new }
|
65
|
+
|
66
|
+
it 'returns a new with its predicate executed in the context of the provided object' do
|
67
|
+
expect(bound.('test')).to be_success
|
68
|
+
expect(bound.('oops')).to be_failure
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'carries id' do
|
72
|
+
expect(bound.id).to be(:bound)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'stores arity' do
|
76
|
+
expect(bound.options[:arity]).to be(rule.arity)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'stores parameters' do
|
80
|
+
expect(bound.options[:parameters]).to eql(rule.parameters)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe '#eval_args' do
|
86
|
+
let(:options) { { args: [1, klass.instance_method(:num), :foo] } }
|
87
|
+
let(:klass) { Class.new { def num; 7; end } }
|
88
|
+
let(:object) { klass.new }
|
89
|
+
|
90
|
+
it 'evaluates args in the context of the provided object' do
|
91
|
+
expect(rule.eval_args(object).args).to eql([1, 7, :foo])
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dry-logic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Solnica
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dry-core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.1'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: dry-container
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -107,30 +121,45 @@ files:
|
|
107
121
|
- examples/basic.rb
|
108
122
|
- lib/dry-logic.rb
|
109
123
|
- lib/dry/logic.rb
|
124
|
+
- lib/dry/logic/appliable.rb
|
110
125
|
- lib/dry/logic/evaluator.rb
|
111
|
-
- lib/dry/logic/
|
112
|
-
- lib/dry/logic/
|
126
|
+
- lib/dry/logic/operations.rb
|
127
|
+
- lib/dry/logic/operations/abstract.rb
|
128
|
+
- lib/dry/logic/operations/and.rb
|
129
|
+
- lib/dry/logic/operations/attr.rb
|
130
|
+
- lib/dry/logic/operations/binary.rb
|
131
|
+
- lib/dry/logic/operations/check.rb
|
132
|
+
- lib/dry/logic/operations/each.rb
|
133
|
+
- lib/dry/logic/operations/implication.rb
|
134
|
+
- lib/dry/logic/operations/key.rb
|
135
|
+
- lib/dry/logic/operations/negation.rb
|
136
|
+
- lib/dry/logic/operations/or.rb
|
137
|
+
- lib/dry/logic/operations/set.rb
|
138
|
+
- lib/dry/logic/operations/unary.rb
|
139
|
+
- lib/dry/logic/operations/xor.rb
|
140
|
+
- lib/dry/logic/operators.rb
|
113
141
|
- lib/dry/logic/predicates.rb
|
114
142
|
- lib/dry/logic/result.rb
|
115
|
-
- lib/dry/logic/result/each.rb
|
116
|
-
- lib/dry/logic/result/multi.rb
|
117
|
-
- lib/dry/logic/result/named.rb
|
118
|
-
- lib/dry/logic/result/set.rb
|
119
|
-
- lib/dry/logic/result/value.rb
|
120
143
|
- lib/dry/logic/rule.rb
|
121
|
-
- lib/dry/logic/rule/
|
122
|
-
- lib/dry/logic/rule/check.rb
|
123
|
-
- lib/dry/logic/rule/composite.rb
|
124
|
-
- lib/dry/logic/rule/each.rb
|
125
|
-
- lib/dry/logic/rule/key.rb
|
126
|
-
- lib/dry/logic/rule/negation.rb
|
127
|
-
- lib/dry/logic/rule/set.rb
|
128
|
-
- lib/dry/logic/rule/value.rb
|
144
|
+
- lib/dry/logic/rule/predicate.rb
|
129
145
|
- lib/dry/logic/rule_compiler.rb
|
130
146
|
- lib/dry/logic/version.rb
|
147
|
+
- spec/integration/result_spec.rb
|
148
|
+
- spec/integration/rule_spec.rb
|
131
149
|
- spec/shared/predicates.rb
|
150
|
+
- spec/shared/rule.rb
|
132
151
|
- spec/spec_helper.rb
|
133
|
-
- spec/
|
152
|
+
- spec/support/mutant.rb
|
153
|
+
- spec/unit/operations/and_spec.rb
|
154
|
+
- spec/unit/operations/attr_spec.rb
|
155
|
+
- spec/unit/operations/check_spec.rb
|
156
|
+
- spec/unit/operations/each_spec.rb
|
157
|
+
- spec/unit/operations/implication_spec.rb
|
158
|
+
- spec/unit/operations/key_spec.rb
|
159
|
+
- spec/unit/operations/negation_spec.rb
|
160
|
+
- spec/unit/operations/or_spec.rb
|
161
|
+
- spec/unit/operations/set_spec.rb
|
162
|
+
- spec/unit/operations/xor_spec.rb
|
134
163
|
- spec/unit/predicates/array_spec.rb
|
135
164
|
- spec/unit/predicates/attr_spec.rb
|
136
165
|
- spec/unit/predicates/bool_spec.rb
|
@@ -165,17 +194,10 @@ files:
|
|
165
194
|
- spec/unit/predicates/time_spec.rb
|
166
195
|
- spec/unit/predicates/true_spec.rb
|
167
196
|
- spec/unit/predicates/type_spec.rb
|
168
|
-
- spec/unit/
|
169
|
-
- spec/unit/rule/
|
170
|
-
- spec/unit/rule/conjunction_spec.rb
|
171
|
-
- spec/unit/rule/disjunction_spec.rb
|
172
|
-
- spec/unit/rule/each_spec.rb
|
173
|
-
- spec/unit/rule/exclusive_disjunction_spec.rb
|
174
|
-
- spec/unit/rule/implication_spec.rb
|
175
|
-
- spec/unit/rule/key_spec.rb
|
176
|
-
- spec/unit/rule/set_spec.rb
|
177
|
-
- spec/unit/rule/value_spec.rb
|
197
|
+
- spec/unit/predicates_spec.rb
|
198
|
+
- spec/unit/rule/predicate_spec.rb
|
178
199
|
- spec/unit/rule_compiler_spec.rb
|
200
|
+
- spec/unit/rule_spec.rb
|
179
201
|
homepage: https://github.com/dryrb/dry-logic
|
180
202
|
licenses:
|
181
203
|
- MIT
|
@@ -201,9 +223,22 @@ signing_key:
|
|
201
223
|
specification_version: 4
|
202
224
|
summary: Predicate logic with rule composition
|
203
225
|
test_files:
|
226
|
+
- spec/integration/result_spec.rb
|
227
|
+
- spec/integration/rule_spec.rb
|
204
228
|
- spec/shared/predicates.rb
|
229
|
+
- spec/shared/rule.rb
|
205
230
|
- spec/spec_helper.rb
|
206
|
-
- spec/
|
231
|
+
- spec/support/mutant.rb
|
232
|
+
- spec/unit/operations/and_spec.rb
|
233
|
+
- spec/unit/operations/attr_spec.rb
|
234
|
+
- spec/unit/operations/check_spec.rb
|
235
|
+
- spec/unit/operations/each_spec.rb
|
236
|
+
- spec/unit/operations/implication_spec.rb
|
237
|
+
- spec/unit/operations/key_spec.rb
|
238
|
+
- spec/unit/operations/negation_spec.rb
|
239
|
+
- spec/unit/operations/or_spec.rb
|
240
|
+
- spec/unit/operations/set_spec.rb
|
241
|
+
- spec/unit/operations/xor_spec.rb
|
207
242
|
- spec/unit/predicates/array_spec.rb
|
208
243
|
- spec/unit/predicates/attr_spec.rb
|
209
244
|
- spec/unit/predicates/bool_spec.rb
|
@@ -238,15 +273,7 @@ test_files:
|
|
238
273
|
- spec/unit/predicates/time_spec.rb
|
239
274
|
- spec/unit/predicates/true_spec.rb
|
240
275
|
- spec/unit/predicates/type_spec.rb
|
241
|
-
- spec/unit/
|
242
|
-
- spec/unit/rule/
|
243
|
-
- spec/unit/rule/conjunction_spec.rb
|
244
|
-
- spec/unit/rule/disjunction_spec.rb
|
245
|
-
- spec/unit/rule/each_spec.rb
|
246
|
-
- spec/unit/rule/exclusive_disjunction_spec.rb
|
247
|
-
- spec/unit/rule/implication_spec.rb
|
248
|
-
- spec/unit/rule/key_spec.rb
|
249
|
-
- spec/unit/rule/set_spec.rb
|
250
|
-
- spec/unit/rule/value_spec.rb
|
276
|
+
- spec/unit/predicates_spec.rb
|
277
|
+
- spec/unit/rule/predicate_spec.rb
|
251
278
|
- spec/unit/rule_compiler_spec.rb
|
252
|
-
|
279
|
+
- spec/unit/rule_spec.rb
|
data/lib/dry/logic/predicate.rb
DELETED
@@ -1,100 +0,0 @@
|
|
1
|
-
module Dry
|
2
|
-
module Logic
|
3
|
-
def self.Predicate(block)
|
4
|
-
case block
|
5
|
-
when Method then Predicate.new(block.name, &block)
|
6
|
-
when UnboundMethod then Predicate.new(block.name, fn: block)
|
7
|
-
else raise ArgumentError, 'predicate needs an :id'
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
class Predicate
|
12
|
-
Undefined = Class.new {
|
13
|
-
def inspect
|
14
|
-
"undefined"
|
15
|
-
end
|
16
|
-
alias_method :to_s, :inspect
|
17
|
-
}.new.freeze
|
18
|
-
|
19
|
-
include Dry::Equalizer(:id, :args)
|
20
|
-
|
21
|
-
attr_reader :id, :args, :fn, :arity
|
22
|
-
|
23
|
-
class Curried < Predicate
|
24
|
-
def call(*args)
|
25
|
-
all_args = @args + args
|
26
|
-
|
27
|
-
if all_args.size == arity
|
28
|
-
super(*args)
|
29
|
-
else
|
30
|
-
curry(*args)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
alias_method :[], :call
|
34
|
-
end
|
35
|
-
|
36
|
-
def initialize(id, args: [], fn: nil, arity: nil, &block)
|
37
|
-
@id = id
|
38
|
-
@args = args
|
39
|
-
@fn = fn || block
|
40
|
-
@arity = arity || @fn.arity
|
41
|
-
end
|
42
|
-
|
43
|
-
#as long as we keep track of the args, we don't actually need to curry the proc...
|
44
|
-
#if we never curry the proc then fn.arity & fn.parameters stay intact
|
45
|
-
def curry(*args)
|
46
|
-
if args.size > 0
|
47
|
-
all_args = @args + args
|
48
|
-
size = all_args.size
|
49
|
-
|
50
|
-
if size <= arity
|
51
|
-
Curried.new(id, args: all_args, fn: fn, arity: arity)
|
52
|
-
else
|
53
|
-
raise_arity_error(all_args.size)
|
54
|
-
end
|
55
|
-
else
|
56
|
-
self
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
# @api public
|
61
|
-
def bind(object)
|
62
|
-
self.class.new(id, *args, &fn.bind(object))
|
63
|
-
end
|
64
|
-
|
65
|
-
#enables a rule to call with its params & have them ignored if the
|
66
|
-
#predicate doesn't need them.
|
67
|
-
#if @args.size == arity then we should ignore called args
|
68
|
-
def call(*args)
|
69
|
-
all_args = @args + args
|
70
|
-
size = all_args.size
|
71
|
-
|
72
|
-
if size == arity
|
73
|
-
fn.(*all_args)
|
74
|
-
else
|
75
|
-
raise_arity_error(size)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
alias_method :[], :call
|
79
|
-
|
80
|
-
def parameters
|
81
|
-
fn.parameters
|
82
|
-
end
|
83
|
-
|
84
|
-
def to_ast
|
85
|
-
[:predicate, [id, args_with_names]]
|
86
|
-
end
|
87
|
-
alias_method :to_a, :to_ast
|
88
|
-
|
89
|
-
private
|
90
|
-
|
91
|
-
def args_with_names
|
92
|
-
parameters.map(&:last).zip(args + Array.new(arity - args.size, Undefined))
|
93
|
-
end
|
94
|
-
|
95
|
-
def raise_arity_error(args_size)
|
96
|
-
raise ArgumentError, "wrong number of arguments (#{args_size} for #{arity})"
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'dry/logic/predicate'
|
2
|
-
require 'dry-container'
|
3
|
-
|
4
|
-
module Dry
|
5
|
-
module Logic
|
6
|
-
module PredicateSet
|
7
|
-
module Methods
|
8
|
-
def predicate(name, &block)
|
9
|
-
register(name) { Predicate.new(name, &block) }
|
10
|
-
end
|
11
|
-
|
12
|
-
def import(predicate_set)
|
13
|
-
merge(predicate_set)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.extended(other)
|
18
|
-
super
|
19
|
-
other.extend(Methods, Dry::Container::Mixin)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Dry
|
2
|
-
module Logic
|
3
|
-
class Result::Each < Result::Multi
|
4
|
-
def to_ast
|
5
|
-
failed_rules = failures.map { |idx, el| [:el, [idx, el.to_ast]] }
|
6
|
-
[:result, [input, [:each, failed_rules]]]
|
7
|
-
end
|
8
|
-
|
9
|
-
def success?
|
10
|
-
response.values.all?(&:success?)
|
11
|
-
end
|
12
|
-
|
13
|
-
def failures
|
14
|
-
response.each_with_object({}) { |(idx, res), hash|
|
15
|
-
hash[idx] = res if res.failure?
|
16
|
-
}
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
module Dry
|
2
|
-
module Logic
|
3
|
-
class Result::Multi < Result
|
4
|
-
def success?
|
5
|
-
success.all?(&:success?)
|
6
|
-
end
|
7
|
-
|
8
|
-
def failures
|
9
|
-
indices = success.map { |v| v.failure? ? success.index(v) : nil }.compact
|
10
|
-
success.values_at(*indices)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module Dry
|
2
|
-
module Logic
|
3
|
-
class Result::Named < Result::Value
|
4
|
-
def name
|
5
|
-
rule.name
|
6
|
-
end
|
7
|
-
|
8
|
-
def to_ast
|
9
|
-
if response.respond_to?(:to_ast) && !response.is_a?(Result)
|
10
|
-
response.to_ast
|
11
|
-
else
|
12
|
-
[:input, [rule.name, super]]
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
data/lib/dry/logic/result/set.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
module Dry
|
2
|
-
module Logic
|
3
|
-
class Result::Value < Result
|
4
|
-
def to_ast
|
5
|
-
if response.respond_to?(:to_ast)
|
6
|
-
response.to_ast
|
7
|
-
else
|
8
|
-
[:result, [input, rule.to_ast]]
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def input
|
13
|
-
rule.input != Predicate::Undefined ? rule.input : super
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|