factbase 0.0.26 → 0.0.28
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/lib/factbase/syntax.rb +2 -1
- data/lib/factbase/term.rb +39 -27
- data/lib/factbase.rb +1 -1
- data/test/factbase/test_query.rb +2 -0
- data/test/factbase/test_syntax.rb +2 -0
- data/test/factbase/test_term.rb +11 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ffdf62af221a65ab9efa6097b01dab23edba0399bc8551757d450ff828f14367
|
4
|
+
data.tar.gz: 175dd8ead3a933305d46c8c4bb657a46efc507db3ad1045bb7495614dedfc1c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ccade318b2db8568b72fcd29dd8d8cc301a791911a749bba8154485e8e95d1a00c2466477ff7e798f8a5146e87e03c69af8493fd05ae38c9463a8ffc9e29da62
|
7
|
+
data.tar.gz: 30730a5e848923b73c98f188142f30f56fd8eec95d8839561a6be01956922f60d9fe46a9dcf361b2f6b4bffca993fd20471bd51f1e2840659ba7bc252c9853b2
|
data/lib/factbase/syntax.rb
CHANGED
@@ -43,6 +43,7 @@ class Factbase::Syntax
|
|
43
43
|
@ast ||= to_ast(@tokens, 0)
|
44
44
|
term = @ast[0]
|
45
45
|
raise 'No terms found' if term.nil?
|
46
|
+
raise 'Not a term' unless term.is_a?(Factbase::Term)
|
46
47
|
term
|
47
48
|
end
|
48
49
|
|
@@ -81,7 +82,7 @@ class Factbase::Syntax
|
|
81
82
|
list = []
|
82
83
|
acc = ''
|
83
84
|
string = false
|
84
|
-
@query.to_s.chars.each do |c|
|
85
|
+
@query.to_s.gsub(/#.*$/, '').chars.each do |c|
|
85
86
|
if ['\'', '"'].include?(c)
|
86
87
|
if string && acc[acc.length - 1] == '\\'
|
87
88
|
acc = acc[0..-2]
|
data/lib/factbase/term.rb
CHANGED
@@ -97,18 +97,12 @@ class Factbase::Term
|
|
97
97
|
|
98
98
|
def exists(fact)
|
99
99
|
assert_args(1)
|
100
|
-
|
101
|
-
raise "A symbol expected: #{o}" unless o.is_a?(Symbol)
|
102
|
-
k = o.to_s
|
103
|
-
!fact[k].nil?
|
100
|
+
!by_symbol(0, fact).nil?
|
104
101
|
end
|
105
102
|
|
106
103
|
def absent(fact)
|
107
104
|
assert_args(1)
|
108
|
-
|
109
|
-
raise "A symbol expected: #{o}" unless o.is_a?(Symbol)
|
110
|
-
k = o.to_s
|
111
|
-
fact[k].nil?
|
105
|
+
by_symbol(0, fact).nil?
|
112
106
|
end
|
113
107
|
|
114
108
|
def eq(fact)
|
@@ -125,29 +119,31 @@ class Factbase::Term
|
|
125
119
|
|
126
120
|
def size(fact)
|
127
121
|
assert_args(1)
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
122
|
+
v = by_symbol(0, fact)
|
123
|
+
return 0 if v.nil?
|
124
|
+
return 1 unless v.is_a?(Array)
|
125
|
+
v.size
|
126
|
+
end
|
127
|
+
|
128
|
+
def type(fact)
|
129
|
+
assert_args(1)
|
130
|
+
v = by_symbol(0, fact)
|
131
|
+
return 'nil' if v.nil?
|
132
|
+
v.class.to_s
|
134
133
|
end
|
135
134
|
|
136
135
|
def arithmetic(op, fact)
|
137
136
|
assert_args(2)
|
138
|
-
|
139
|
-
if
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
v.any? do |vv|
|
149
|
-
vv = vv.floor if vv.is_a?(Time) && op == :==
|
150
|
-
vv.send(op, @operands[1])
|
137
|
+
lefts = the_value(0, fact)
|
138
|
+
return false if lefts.nil?
|
139
|
+
rights = the_value(1, fact)
|
140
|
+
return false if rights.nil?
|
141
|
+
lefts.any? do |l|
|
142
|
+
l = l.floor if l.is_a?(Time) && op == :==
|
143
|
+
rights.any? do |r|
|
144
|
+
r = r.floor if r.is_a?(Time) && op == :==
|
145
|
+
l.send(op, r)
|
146
|
+
end
|
151
147
|
end
|
152
148
|
end
|
153
149
|
|
@@ -156,4 +152,20 @@ class Factbase::Term
|
|
156
152
|
raise "Too many (#{c}) operands for '#{@op}' (#{num} expected)" if c > num
|
157
153
|
raise "Too few (#{c}) operands for '#{@op}' (#{num} expected)" if c < num
|
158
154
|
end
|
155
|
+
|
156
|
+
def by_symbol(pos, fact)
|
157
|
+
o = @operands[pos]
|
158
|
+
raise "A symbol expected at ##{pos}, but provided: #{o}" unless o.is_a?(Symbol)
|
159
|
+
k = o.to_s
|
160
|
+
fact[k]
|
161
|
+
end
|
162
|
+
|
163
|
+
def the_value(pos, fact)
|
164
|
+
v = @operands[pos]
|
165
|
+
v = v.eval(fact) if v.is_a?(Factbase::Term)
|
166
|
+
v = fact[v.to_s] if v.is_a?(Symbol)
|
167
|
+
return v if v.nil?
|
168
|
+
v = [v] unless v.is_a?(Array)
|
169
|
+
v
|
170
|
+
end
|
159
171
|
end
|
data/lib/factbase.rb
CHANGED
data/test/factbase/test_query.rb
CHANGED
@@ -54,9 +54,11 @@ class TestQuery < Minitest::Test
|
|
54
54
|
"(and (lt pi 100) \n\n (gt num 1000))" => 0,
|
55
55
|
'(exists pi)' => 1,
|
56
56
|
'(not (exists hello))' => 3,
|
57
|
+
'(eq "Integer" (type num))' => 2,
|
57
58
|
'(gt (size num) 2)' => 1,
|
58
59
|
'(lt (size num) 2)' => 2,
|
59
60
|
'(eq (size hello) 0)' => 3,
|
61
|
+
'(eq num pi)' => 0,
|
60
62
|
'(absent time)' => 2,
|
61
63
|
'(and (absent time) (exists pi))' => 1,
|
62
64
|
"(and (exists time) (not (\t\texists pi)))" => 1,
|
@@ -45,6 +45,7 @@ class TestSyntax < Minitest::Test
|
|
45
45
|
'(foo)',
|
46
46
|
'(foo (bar) (zz 77) )',
|
47
47
|
"(eq foo \n\n 'Hello, world!'\n)\n",
|
48
|
+
"# this is a comment\n(eq foo # test\n 42)\n\n# another comment\n",
|
48
49
|
"(or ( a 4) (b 5) () (and () (c 5) \t\t(r 7 8s 8is 'Foo')))"
|
49
50
|
].each do |q|
|
50
51
|
Factbase::Syntax.new(q).to_term
|
@@ -90,6 +91,7 @@ class TestSyntax < Minitest::Test
|
|
90
91
|
[
|
91
92
|
'',
|
92
93
|
'(foo',
|
94
|
+
'some text',
|
93
95
|
'"hello, world!',
|
94
96
|
'(foo 7',
|
95
97
|
"(foo 7 'Dude'",
|
data/test/factbase/test_term.rb
CHANGED
@@ -111,6 +111,16 @@ class TestTerm < Minitest::Test
|
|
111
111
|
assert(!t.eval(fact('foo' => 100)))
|
112
112
|
end
|
113
113
|
|
114
|
+
def test_type_matching
|
115
|
+
t = Factbase::Term.new(:type, [:foo])
|
116
|
+
assert_equal('Integer', t.eval(fact('foo' => 42)))
|
117
|
+
assert_equal('Array', t.eval(fact('foo' => [1, 2, 3])))
|
118
|
+
assert_equal('String', t.eval(fact('foo' => 'Hello, world!')))
|
119
|
+
assert_equal('Float', t.eval(fact('foo' => 3.14)))
|
120
|
+
assert_equal('Time', t.eval(fact('foo' => Time.now)))
|
121
|
+
assert_equal('nil', t.eval(fact))
|
122
|
+
end
|
123
|
+
|
114
124
|
def test_or_matching
|
115
125
|
t = Factbase::Term.new(
|
116
126
|
:or,
|
@@ -139,7 +149,7 @@ class TestTerm < Minitest::Test
|
|
139
149
|
|
140
150
|
private
|
141
151
|
|
142
|
-
def fact(map)
|
152
|
+
def fact(map = {})
|
143
153
|
Factbase::Fact.new(Mutex.new, map)
|
144
154
|
end
|
145
155
|
end
|