factbase 0.0.1

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.
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ # Fact.
24
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
25
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
26
+ # License:: MIT
27
+ class Factbase::Fact
28
+ def initialize(mutex, map)
29
+ @mutex = mutex
30
+ @map = map
31
+ end
32
+
33
+ def method_missing(*args)
34
+ k = args[0].to_s
35
+ if k.end_with?('=')
36
+ k = k[0..-2]
37
+ @mutex.synchronize do
38
+ @map[k] = [] if @map[k].nil?
39
+ @map[k] << args[1]
40
+ end
41
+ nil
42
+ else
43
+ v = @map[k]
44
+ raise "Can't find '#{k}'" if v.nil?
45
+ v[0]
46
+ end
47
+ end
48
+
49
+ # rubocop:disable Style/OptionalBooleanParameter
50
+ def respond_to?(_method, _include_private = false)
51
+ # rubocop:enable Style/OptionalBooleanParameter
52
+ true
53
+ end
54
+
55
+ def respond_to_missing?(_method, _include_private = false)
56
+ true
57
+ end
58
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require_relative 'syntax'
24
+ require_relative 'fact'
25
+
26
+ # Query.
27
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
29
+ # License:: MIT
30
+ class Factbase::Query
31
+ def initialize(maps, mutex, query)
32
+ @maps = maps
33
+ @mutex = mutex
34
+ @query = query
35
+ end
36
+
37
+ # Iterate them one by one.
38
+ # @yield [Fact] Facts one-by-one
39
+ def each
40
+ term = Factbase::Syntax.new(@query).to_term
41
+ @maps.each do |m|
42
+ next unless term.matches?(m)
43
+ yield Factbase::Fact.new(@mutex, m)
44
+ end
45
+ end
46
+
47
+ # Turn it into an array.
48
+ # @return [Array] All facts in an array
49
+ # rubocop:disable Style/MapIntoArray
50
+ def to_a
51
+ array = []
52
+ each { |f| array << f }
53
+ array
54
+ end
55
+ # rubocop:enable Style/MapIntoArray
56
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'cgi'
24
+ require_relative 'fact'
25
+ require_relative 'term'
26
+
27
+ # Syntax.
28
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
30
+ # License:: MIT
31
+ class Factbase::Syntax
32
+ def initialize(query)
33
+ @query = query
34
+ end
35
+
36
+ # Convert it to a term.
37
+ # @return [Term] The term detected
38
+ def to_term
39
+ @tokens ||= to_tokens
40
+ @ast ||= to_ast(@tokens, 0)
41
+ @ast[0]
42
+ end
43
+
44
+ private
45
+
46
+ # Reads the stream of tokens, starting at the +at+ position. If the
47
+ # token at the position is not a literal (like 42 or "Hello") but a term,
48
+ # the function recursively calls itself.
49
+ #
50
+ # The function returns an two-elements array, where the first element
51
+ # is the term/literal and the second one is the position where the
52
+ # scanning should continue.
53
+ def to_ast(tokens, at)
54
+ return [tokens[at], at + 1] unless tokens[at] == :open
55
+ at += 1
56
+ op = tokens[at]
57
+ return [Factbase::Term.new(:nil, []), at + 1] if op == :close
58
+ operands = []
59
+ at += 1
60
+ loop do
61
+ break if tokens[at] == :close
62
+ (operand, at1) = to_ast(tokens, at)
63
+ at = at1
64
+ operands << operand
65
+ break if tokens[at] == :close
66
+ end
67
+ [Factbase::Term.new(op, operands), at + 1]
68
+ end
69
+
70
+ def to_tokens
71
+ list = []
72
+ acc = ''
73
+ @query.to_s.chars.each do |c|
74
+ if !acc.empty? && [' ', ')'].include?(c)
75
+ list << acc
76
+ acc = ''
77
+ end
78
+ case c
79
+ when '('
80
+ list << :open
81
+ when ')'
82
+ list << :close
83
+ when ' '
84
+ # ignore it
85
+ else
86
+ acc += c
87
+ end
88
+ end
89
+ list.map do |t|
90
+ if t.is_a?(Symbol)
91
+ t
92
+ elsif t.start_with?('\'')
93
+ CGI.unescapeHTML(t[1..-2])
94
+ elsif t.match?(/^[0-9]+$/)
95
+ t.to_i
96
+ else
97
+ t.to_sym
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require_relative 'fact'
24
+
25
+ # Term.
26
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
27
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # License:: MIT
29
+ class Factbase::Term
30
+ def initialize(operator, operands)
31
+ @op = operator
32
+ @operands = operands
33
+ end
34
+
35
+ # Does it match the map?
36
+ # @param [Map] The map
37
+ # @return [bool] TRUE if matches
38
+ def matches?(map)
39
+ send(@op, map)
40
+ end
41
+
42
+ def to_s
43
+ items = []
44
+ items << @op
45
+ items += @operands.map do |o|
46
+ if o.is_a?(String)
47
+ "'#{o}'"
48
+ else
49
+ o.to_s
50
+ end
51
+ end
52
+ "(#{items.join(' ')})"
53
+ end
54
+
55
+ private
56
+
57
+ def nil(_map)
58
+ true
59
+ end
60
+
61
+ def not(map)
62
+ !@operands[0].matches?(map)
63
+ end
64
+
65
+ def or(map)
66
+ @operands.each do |o|
67
+ return true if o.matches?(map)
68
+ end
69
+ false
70
+ end
71
+
72
+ def and(map)
73
+ @operands.each do |o|
74
+ return false unless o.matches?(map)
75
+ end
76
+ true
77
+ end
78
+
79
+ def exists(map)
80
+ k = @operands[0].to_s
81
+ !map[k].nil?
82
+ end
83
+
84
+ def absent(map)
85
+ k = @operands[0].to_s
86
+ map[k].nil?
87
+ end
88
+
89
+ def eq(map)
90
+ k = @operands[0].to_s
91
+ v = map[k]
92
+ return false if v.nil?
93
+ v[0] == @operands[1]
94
+ end
95
+
96
+ def lt(map)
97
+ k = @operands[0].to_s
98
+ v = map[k]
99
+ return false if v.nil?
100
+ v[0] < @operands[1]
101
+ end
102
+
103
+ def gt(map)
104
+ k = @operands[0].to_s
105
+ v = map[k]
106
+ return false if v.nil?
107
+ v[0] > @operands[1]
108
+ end
109
+ end
data/lib/factbase.rb ADDED
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ # Factbase.
24
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
25
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
26
+ # License:: MIT
27
+ class Factbase
28
+ # Current version of the library and of this class.
29
+ VERSION = '0.0.1'
30
+
31
+ # Constructor.
32
+ def initialize
33
+ @maps = []
34
+ @mutex = Mutex.new
35
+ end
36
+
37
+ # Insert a new fact.
38
+ # @return [Factbase::Fact] The fact just inserted
39
+ def insert
40
+ map = {}
41
+ @mutex.synchronize do
42
+ f = Factbase::Fact.new(Mutex.new, map)
43
+ f.id = @maps.size + 1
44
+ @maps << map
45
+ end
46
+ Factbase::Fact.new(@mutex, map)
47
+ end
48
+
49
+ # Create a query capable of iterating.
50
+ #
51
+ # There is a Lisp-like syntax, for example (all string literals
52
+ # must be HTML-escaped):
53
+ #
54
+ # (eq title 'Object&#20;Thinking')
55
+ # (gt time '2024-03-23T03:21:43')
56
+ # (gt cost 42)
57
+ # (exists seenBy)
58
+ # (and
59
+ # (eq foo '42')
60
+ # (or
61
+ # (gt bar 200)
62
+ # (absent zzz)))
63
+ #
64
+ # @param [String] query The query to use for selections
65
+ def query(query)
66
+ Factbase::Query.new(@maps, @mutex, query)
67
+ end
68
+
69
+ # Export it into a chain of bytes.
70
+ def export
71
+ Marshal.dump(@maps)
72
+ end
73
+
74
+ # Import from a chain of bytes.
75
+ def import(bytes)
76
+ # rubocop:disable Security/MarshalLoad
77
+ @maps += Marshal.load(bytes)
78
+ # rubocop:enable Security/MarshalLoad
79
+ end
80
+ end
81
+
82
+ require_relative 'factbase/fact'
83
+ require_relative 'factbase/query'
data/renovate.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3
+ "extends": [
4
+ "config:base"
5
+ ]
6
+ }
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2024 Yegor Bugayenko
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the 'Software'), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ require 'minitest/autorun'
25
+ require_relative '../../lib/factbase'
26
+
27
+ # Fact test.
28
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
30
+ # License:: MIT
31
+ class TestFact < Minitest::Test
32
+ def test_simple_resetting
33
+ map = {}
34
+ f = Factbase::Fact.new(Mutex.new, map)
35
+ f.foo = 42
36
+ assert_equal(42, f.foo)
37
+ f.foo = 256
38
+ assert_equal(42, f.foo)
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2024 Yegor Bugayenko
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the 'Software'), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ require 'minitest/autorun'
25
+ require_relative '../../lib/factbase'
26
+
27
+ # Query test.
28
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
30
+ # License:: MIT
31
+ class TestQuery < Minitest::Test
32
+ def test_simple_parsing
33
+ maps = []
34
+ maps << { 'foo' => [42] }
35
+ q = Factbase::Query.new(maps, Mutex.new, '(eq foo 42)')
36
+ q.each do |f|
37
+ assert_equal(42, f.foo)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2024 Yegor Bugayenko
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the 'Software'), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ require 'minitest/autorun'
25
+ require_relative '../../lib/factbase/syntax'
26
+
27
+ # Syntax test.
28
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
30
+ # License:: MIT
31
+ class TestSyntax < Minitest::Test
32
+ def test_simple_parsing
33
+ [
34
+ '()',
35
+ '(foo)',
36
+ '(foo (bar) (zz 77) )',
37
+ "(eq foo 'Hello,&#x20;world!')",
38
+ "(or ( a 4) (b 5) () (and () (c 5) (r 7 8s 8is 'Foo')))"
39
+ ].each do |q|
40
+ Factbase::Syntax.new(q).to_term
41
+ end
42
+ end
43
+
44
+ def test_exact_parsing
45
+ [
46
+ '(foo)',
47
+ '(foo 7)',
48
+ "(foo 7 'Dude')",
49
+ '(foo x y z)',
50
+ "(foo x y z t f 42 'Hi!' 33)",
51
+ '(foo (x) y z)',
52
+ "(foo (x (f (t (y 42 'Hey'))) (f) (r 3)) y z)"
53
+ ].each do |q|
54
+ assert_equal(q, Factbase::Syntax.new(q).to_term.to_s)
55
+ end
56
+ end
57
+
58
+ def test_simple_matching
59
+ m = {
60
+ 'foo' => ['Hello, world!'],
61
+ 'bar' => [42],
62
+ 'z' => [1, 2, 3, 4]
63
+ }
64
+ {
65
+ '(eq z 1)' => true,
66
+ '(or (eq bar 888) (eq z 1))' => true,
67
+ "(or (gt bar 100) (eq foo 'Hello,&#x20;world!'))" => true
68
+ }.each do |k, v|
69
+ assert_equal(v, Factbase::Syntax.new(k).to_term.matches?(m), k)
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2024 Yegor Bugayenko
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the 'Software'), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ require 'minitest/autorun'
25
+ require_relative '../../lib/factbase/term'
26
+
27
+ # Term test.
28
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
30
+ # License:: MIT
31
+ class TestTerm < Minitest::Test
32
+ def test_simple_matching
33
+ t = Factbase::Term.new(:eq, ['foo', 42])
34
+ assert(t.matches?({ 'foo' => [42] }))
35
+ assert(!t.matches?({ 'foo' => ['Hello!'] }))
36
+ assert(!t.matches?({ 'bar' => ['Hello!'] }))
37
+ end
38
+
39
+ def test_lt_matching
40
+ t = Factbase::Term.new(:lt, ['foo', 42])
41
+ assert(t.matches?({ 'foo' => [10] }))
42
+ assert(!t.matches?({ 'foo' => [100] }))
43
+ end
44
+
45
+ def test_gt_matching
46
+ t = Factbase::Term.new(:gt, ['foo', 42])
47
+ assert(t.matches?({ 'foo' => [100] }))
48
+ assert(!t.matches?({ 'foo' => [10] }))
49
+ end
50
+
51
+ def test_not_matching
52
+ t = Factbase::Term.new(:not, [Factbase::Term.new(:nil, [])])
53
+ assert(!t.matches?({ 'foo' => [100] }))
54
+ end
55
+
56
+ def test_or_matching
57
+ t = Factbase::Term.new(
58
+ :or,
59
+ [
60
+ Factbase::Term.new(:eq, ['foo', 4]),
61
+ Factbase::Term.new(:eq, ['bar', 5])
62
+ ]
63
+ )
64
+ assert(t.matches?({ 'foo' => [4] }))
65
+ assert(t.matches?({ 'bar' => [5] }))
66
+ assert(!t.matches?({ 'bar' => [42] }))
67
+ end
68
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2024 Yegor Bugayenko
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the 'Software'), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in all
14
+ # copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ # SOFTWARE.
23
+
24
+ $stdout.sync = true
25
+
26
+ require 'simplecov'
27
+ SimpleCov.start
28
+
29
+ require 'minitest/autorun'
30
+ require_relative '../lib/factbase'