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.
- checksums.yaml +7 -0
- data/.0pdd.yml +25 -0
- data/.gitattributes +7 -0
- data/.github/workflows/actionlint.yml +41 -0
- data/.github/workflows/codecov.yml +40 -0
- data/.github/workflows/markdown-lint.yml +38 -0
- data/.github/workflows/pdd.yml +15 -0
- data/.github/workflows/rake.yml +24 -0
- data/.github/workflows/xcop.yml +11 -0
- data/.github/workflows/yamllint.yml +36 -0
- data/.gitignore +9 -0
- data/.pdd +7 -0
- data/.rubocop.yml +47 -0
- data/.rultor.yml +42 -0
- data/.simplecov +41 -0
- data/.yamllint.yml +24 -0
- data/Gemfile +32 -0
- data/LICENSE.txt +21 -0
- data/README.md +55 -0
- data/Rakefile +67 -0
- data/factbase.gemspec +46 -0
- data/lib/factbase/fact.rb +58 -0
- data/lib/factbase/query.rb +56 -0
- data/lib/factbase/syntax.rb +101 -0
- data/lib/factbase/term.rb +109 -0
- data/lib/factbase.rb +83 -0
- data/renovate.json +6 -0
- data/test/factbase/test_fact.rb +40 -0
- data/test/factbase/test_query.rb +40 -0
- data/test/factbase/test_syntax.rb +72 -0
- data/test/factbase/test_term.rb +68 -0
- data/test/test__helper.rb +30 -0
- data/test/test_factbase.rb +56 -0
- metadata +78 -0
@@ -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 'ObjectThinking')
|
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,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, 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, 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'
|