factbase 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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'