factbase 0.16.7 → 0.17.0
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/Gemfile +2 -1
- data/Gemfile.lock +25 -20
- data/README.md +28 -27
- data/Rakefile +14 -6
- data/lib/factbase/cached/cached_query.rb +2 -0
- data/lib/factbase/indexed/indexed_absent.rb +25 -0
- data/lib/factbase/indexed/indexed_and.rb +79 -0
- data/lib/factbase/indexed/indexed_eq.rb +46 -0
- data/lib/factbase/indexed/indexed_exists.rb +25 -0
- data/lib/factbase/indexed/indexed_factbase.rb +46 -0
- data/lib/factbase/indexed/indexed_gt.rb +41 -0
- data/lib/factbase/indexed/indexed_lt.rb +41 -0
- data/lib/factbase/indexed/indexed_not.rb +32 -0
- data/lib/factbase/indexed/indexed_one.rb +25 -0
- data/lib/factbase/indexed/indexed_or.rb +28 -0
- data/lib/factbase/indexed/indexed_query.rb +2 -0
- data/lib/factbase/indexed/indexed_term.rb +29 -185
- data/lib/factbase/indexed/indexed_unique.rb +25 -0
- data/lib/factbase/query.rb +22 -8
- data/lib/factbase/sync/sync_factbase.rb +11 -11
- data/lib/factbase/sync/sync_query.rb +7 -8
- data/lib/factbase/term.rb +110 -91
- data/lib/factbase/terms/absent.rb +26 -0
- data/lib/factbase/terms/aggregates.rb +0 -13
- data/lib/factbase/terms/always.rb +27 -0
- data/lib/factbase/terms/and.rb +28 -0
- data/lib/factbase/terms/arithmetic.rb +55 -0
- data/lib/factbase/terms/as.rb +31 -0
- data/lib/factbase/terms/{debug.rb → assert.rb} +17 -15
- data/lib/factbase/terms/base.rb +17 -0
- data/lib/factbase/terms/boolean.rb +28 -0
- data/lib/factbase/terms/compare.rb +38 -0
- data/lib/factbase/terms/concat.rb +26 -0
- data/lib/factbase/terms/count.rb +25 -0
- data/lib/factbase/terms/defn.rb +16 -15
- data/lib/factbase/terms/div.rb +25 -0
- data/lib/factbase/terms/either.rb +31 -0
- data/lib/factbase/terms/env.rb +28 -0
- data/lib/factbase/terms/eq.rb +28 -0
- data/lib/factbase/terms/exists.rb +27 -0
- data/lib/factbase/terms/first.rb +30 -0
- data/lib/factbase/terms/gt.rb +28 -0
- data/lib/factbase/terms/gte.rb +27 -0
- data/lib/factbase/terms/head.rb +37 -0
- data/lib/factbase/terms/inverted.rb +34 -0
- data/lib/factbase/terms/{aliases.rb → join.rb} +15 -15
- data/lib/factbase/terms/logical.rb +0 -83
- data/lib/factbase/terms/lt.rb +28 -0
- data/lib/factbase/terms/lte.rb +28 -0
- data/lib/factbase/terms/many.rb +29 -0
- data/lib/factbase/terms/{strings.rb → matches.rb} +12 -12
- data/lib/factbase/terms/minus.rb +25 -0
- data/lib/factbase/terms/never.rb +26 -0
- data/lib/factbase/terms/nil.rb +26 -0
- data/lib/factbase/terms/not.rb +27 -0
- data/lib/factbase/terms/one.rb +30 -0
- data/lib/factbase/terms/or.rb +28 -0
- data/lib/factbase/terms/plus.rb +27 -0
- data/lib/factbase/terms/prev.rb +29 -0
- data/lib/factbase/terms/shared.rb +69 -0
- data/lib/factbase/terms/size.rb +30 -0
- data/lib/factbase/terms/sorted.rb +38 -0
- data/lib/factbase/terms/sprintf.rb +29 -0
- data/lib/factbase/terms/times.rb +25 -0
- data/lib/factbase/terms/to_float.rb +28 -0
- data/lib/factbase/terms/to_integer.rb +28 -0
- data/lib/factbase/terms/to_string.rb +28 -0
- data/lib/factbase/terms/to_time.rb +28 -0
- data/lib/factbase/terms/traced.rb +33 -0
- data/lib/factbase/terms/type.rb +31 -0
- data/lib/factbase/terms/undef.rb +33 -0
- data/lib/factbase/terms/unique.rb +34 -0
- data/lib/factbase/terms/when.rb +29 -0
- data/lib/factbase/terms/zero.rb +28 -0
- data/lib/factbase/version.rb +1 -1
- data/lib/factbase.rb +10 -1
- metadata +60 -10
- data/lib/factbase/terms/casting.rb +0 -41
- data/lib/factbase/terms/lists.rb +0 -57
- data/lib/factbase/terms/math.rb +0 -103
- data/lib/factbase/terms/meta.rb +0 -58
- data/lib/factbase/terms/ordering.rb +0 -34
- data/lib/factbase/terms/system.rb +0 -19
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
|
|
8
|
+
# Represents a term that evaluates to true if the specified operand is absent in the fact.
|
|
9
|
+
class Factbase::Absent < Factbase::TermBase
|
|
10
|
+
# Constructor.
|
|
11
|
+
# @param [Array] operands Operands
|
|
12
|
+
def initialize(operands)
|
|
13
|
+
super()
|
|
14
|
+
@operands = operands
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Evaluate term on a fact.
|
|
18
|
+
# @param [Factbase::Fact] fact The fact
|
|
19
|
+
# @param [Array<Factbase::Fact>] _maps All maps available
|
|
20
|
+
# @param [Factbase] _fb Factbase to use for sub-queries
|
|
21
|
+
# @return [Boolean] True if absent
|
|
22
|
+
def evaluate(fact, _maps, _fb)
|
|
23
|
+
assert_args(1)
|
|
24
|
+
_by_symbol(0, fact).nil?
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -21,10 +21,6 @@ module Factbase::Aggregates
|
|
|
21
21
|
_best(maps) { |v, b| v > b }
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def count(_fact, maps, _fb)
|
|
25
|
-
maps.size
|
|
26
|
-
end
|
|
27
|
-
|
|
28
24
|
def nth(_fact, maps, _fb)
|
|
29
25
|
assert_args(2)
|
|
30
26
|
pos = @operands[0]
|
|
@@ -36,15 +32,6 @@ module Factbase::Aggregates
|
|
|
36
32
|
m[k.to_s]
|
|
37
33
|
end
|
|
38
34
|
|
|
39
|
-
def first(_fact, maps, _fb)
|
|
40
|
-
assert_args(1)
|
|
41
|
-
k = @operands[0]
|
|
42
|
-
raise "A symbol is expected, but #{k} provided" unless k.is_a?(Symbol)
|
|
43
|
-
first = maps[0]
|
|
44
|
-
return nil if first.nil?
|
|
45
|
-
first[k.to_s]
|
|
46
|
-
end
|
|
47
|
-
|
|
48
35
|
def sum(_fact, maps, _fb)
|
|
49
36
|
k = @operands[0]
|
|
50
37
|
raise "A symbol is expected, but '#{k}' provided" unless k.is_a?(Symbol)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
# The term 'always' that always evaluates to true.
|
|
8
|
+
# If you want to return all the facts you might use '(always)' query.
|
|
9
|
+
class Factbase::Always < Factbase::TermBase
|
|
10
|
+
# Constructor.
|
|
11
|
+
# @param [Array] operands Operands
|
|
12
|
+
def initialize(operands = [])
|
|
13
|
+
super()
|
|
14
|
+
@operands = operands
|
|
15
|
+
@op = :always
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Evaluate term on a fact.
|
|
19
|
+
# @param [Factbase::Fact] _fact The fact
|
|
20
|
+
# @param [Array<Factbase::Fact>] _maps All maps available
|
|
21
|
+
# @param [Factbase] _fb Factbase to use for sub-queries
|
|
22
|
+
# @return [Boolean] Always returns true
|
|
23
|
+
def evaluate(_fact, _maps, _fb)
|
|
24
|
+
assert_args(0)
|
|
25
|
+
true
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
require_relative 'boolean'
|
|
8
|
+
# The 'and' term that represents a logical AND operation between multiple operands.
|
|
9
|
+
class Factbase::And < Factbase::TermBase
|
|
10
|
+
# Constructor.
|
|
11
|
+
# @param [Array] operands Operands
|
|
12
|
+
def initialize(operands)
|
|
13
|
+
super()
|
|
14
|
+
@operands = operands
|
|
15
|
+
@op = :and
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Evaluate term on a fact.
|
|
19
|
+
# @param [Factbase::Fact] fact The fact
|
|
20
|
+
# @param [Array<Factbase::Fact>] maps All maps available
|
|
21
|
+
# @return [Boolean] True if all operands evaluate to true, false otherwise
|
|
22
|
+
def evaluate(fact, maps, fb)
|
|
23
|
+
(0..(@operands.size - 1)).each do |i|
|
|
24
|
+
return false unless Factbase::Boolean.new(_values(i, fact, maps, fb), @operands[i]).bool?
|
|
25
|
+
end
|
|
26
|
+
true
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
|
|
8
|
+
# Factbase::Arithmetic is a class for performing arithmetic operations.
|
|
9
|
+
class Factbase::Arithmetic < Factbase::TermBase
|
|
10
|
+
# Constructor.
|
|
11
|
+
# @param [Symbol] operation The arithmetic operation (e.g., :+, :-, :*, :/)
|
|
12
|
+
# @param [Array] operands Operands
|
|
13
|
+
def initialize(operation, operands)
|
|
14
|
+
super()
|
|
15
|
+
@op = operation
|
|
16
|
+
@operands = operands
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Evaluate term on a fact.
|
|
20
|
+
# @param [Factbase::Fact] fact The fact
|
|
21
|
+
# @param [Array<Factbase::Fact>] maps All maps available
|
|
22
|
+
# @param [Factbase] fb Factbase to use for sub-queries
|
|
23
|
+
# @return [Object] The result of the arithmetic operation
|
|
24
|
+
def evaluate(fact, maps, fb)
|
|
25
|
+
assert_args(2)
|
|
26
|
+
lefts = _values(0, fact, maps, fb)
|
|
27
|
+
return nil if lefts.nil?
|
|
28
|
+
raise 'Too many values at first position, one expected' unless lefts.size == 1
|
|
29
|
+
rights = _values(1, fact, maps, fb)
|
|
30
|
+
return nil if rights.nil?
|
|
31
|
+
raise 'Too many values at second position, one expected' unless rights.size == 1
|
|
32
|
+
v = lefts[0]
|
|
33
|
+
r = rights[0]
|
|
34
|
+
if v.is_a?(Time) && r.is_a?(String)
|
|
35
|
+
(num, units) = r.split
|
|
36
|
+
num = num.to_i
|
|
37
|
+
r =
|
|
38
|
+
case units
|
|
39
|
+
when 'seconds', 'second'
|
|
40
|
+
num
|
|
41
|
+
when 'minutes', 'minute'
|
|
42
|
+
num * 60
|
|
43
|
+
when 'hours', 'hour'
|
|
44
|
+
num * 60 * 60
|
|
45
|
+
when 'days', 'day'
|
|
46
|
+
num * 60 * 60 * 24
|
|
47
|
+
when 'weeks', 'week'
|
|
48
|
+
num * 60 * 60 * 24 * 7
|
|
49
|
+
else
|
|
50
|
+
raise "Unknown time unit '#{units}' in '#{r}"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
v.send(@op, r)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
#
|
|
8
|
+
# The Factbase::As class is a specialized term that evaluates
|
|
9
|
+
# and assigns values to a specific attribute of a fact.
|
|
10
|
+
class Factbase::As < Factbase::TermBase
|
|
11
|
+
# Constructor.
|
|
12
|
+
# @param [Array] operands Operands
|
|
13
|
+
def initialize(operands)
|
|
14
|
+
super()
|
|
15
|
+
@operands = operands
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Evaluate term on a fact.
|
|
19
|
+
# @param [Factbase::Fact] fact The fact
|
|
20
|
+
# @param [Array<Factbase::Fact>] maps All maps available
|
|
21
|
+
# @param [Factbase] fb Factbase to use for sub-queries
|
|
22
|
+
# @return [Boolean] True if succeeded
|
|
23
|
+
def evaluate(fact, maps, fb)
|
|
24
|
+
assert_args(2)
|
|
25
|
+
a = @operands[0]
|
|
26
|
+
raise "A symbol is expected as first argument of 'as'" unless a.is_a?(Symbol)
|
|
27
|
+
vv = _values(1, fact, maps, fb)
|
|
28
|
+
vv&.each { |v| fact.send(:"#{a}=", v) }
|
|
29
|
+
true
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -3,24 +3,26 @@
|
|
|
3
3
|
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
|
-
require_relative '
|
|
6
|
+
require_relative 'base'
|
|
7
7
|
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
|
|
12
|
-
#
|
|
13
|
-
|
|
14
|
-
def
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
r = t.evaluate(fact, maps, fb)
|
|
19
|
-
puts "#{self} -> #{r}"
|
|
20
|
-
r
|
|
8
|
+
# The `Factbase::Assert` class represents an assertion term in the Factbase system.
|
|
9
|
+
# It verifies that a given condition evaluates to true, raising an error with
|
|
10
|
+
# a specified message if the assertion fails.
|
|
11
|
+
class Factbase::Assert < Factbase::TermBase
|
|
12
|
+
# Constructor.
|
|
13
|
+
# @param [Array] operands Operands
|
|
14
|
+
def initialize(operands)
|
|
15
|
+
super()
|
|
16
|
+
@operands = operands
|
|
17
|
+
@op = 'assert'
|
|
21
18
|
end
|
|
22
19
|
|
|
23
|
-
|
|
20
|
+
# Evaluate term on a fact.
|
|
21
|
+
# @param [Factbase::Fact] fact The fact
|
|
22
|
+
# @param [Array<Factbase::Fact>] maps All maps available
|
|
23
|
+
# @param [Factbase] fb Factbase to use for sub-queries
|
|
24
|
+
# @return [Boolean] Returns true if the assertion passes, otherwise raises an error with the provided message
|
|
25
|
+
def evaluate(fact, maps, fb)
|
|
24
26
|
assert_args(2)
|
|
25
27
|
message = @operands[0]
|
|
26
28
|
unless message.is_a?(String)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
# Test for unique term.
|
|
7
|
+
# Author:: Volodya Lombrozo (volodya.lombrozo@gmail.com)
|
|
8
|
+
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
9
|
+
# License:: MIT
|
|
10
|
+
|
|
11
|
+
# Base class for all terms.
|
|
12
|
+
class Factbase::TermBase
|
|
13
|
+
require_relative 'shared'
|
|
14
|
+
include Factbase::TermShared
|
|
15
|
+
|
|
16
|
+
protected :assert_args, :_by_symbol, :_values, :to_s
|
|
17
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
# Boolean value checker.
|
|
8
|
+
class Factbase::Boolean
|
|
9
|
+
# Constructor.
|
|
10
|
+
# @param [Object] val The value to check
|
|
11
|
+
# @param [Object] from The source of the value (for error messages)
|
|
12
|
+
# @return [Boolean] The boolean value
|
|
13
|
+
# @raise [RuntimeError] If value is not a boolean
|
|
14
|
+
def initialize(val, from)
|
|
15
|
+
@val = val
|
|
16
|
+
@from = from
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @return [Boolean] The boolean value
|
|
20
|
+
# @raise [RuntimeError] If value is not a boolean
|
|
21
|
+
def bool?
|
|
22
|
+
val = @val
|
|
23
|
+
val = val[0] if val.respond_to?(:each)
|
|
24
|
+
return false if val.nil?
|
|
25
|
+
return val if val.is_a?(TrueClass) || val.is_a?(FalseClass)
|
|
26
|
+
raise "Boolean is expected, while #{val.class} received from #{@from}"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
# Term 'compare'.
|
|
8
|
+
# Compares two values using a specified operation.
|
|
9
|
+
class Factbase::Compare < Factbase::TermBase
|
|
10
|
+
# Constructor.
|
|
11
|
+
# @param [Symbol] operation Operation to perform, e.g. :>, :<, :<=, :>=, :==
|
|
12
|
+
# @param [Array] operands Operands
|
|
13
|
+
def initialize(operation, operands)
|
|
14
|
+
super()
|
|
15
|
+
@op = operation
|
|
16
|
+
@operands = operands
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Evaluate term on a fact.
|
|
20
|
+
# @param [Factbase::Fact] fact The fact
|
|
21
|
+
# @param [Array<Factbase::Fact>] maps All maps available
|
|
22
|
+
# @param [Factbase] fb Factbase to use for sub-queries
|
|
23
|
+
# @return [Boolean] The result of the comparison
|
|
24
|
+
def evaluate(fact, maps, fb)
|
|
25
|
+
assert_args(2)
|
|
26
|
+
lefts = _values(0, fact, maps, fb)
|
|
27
|
+
return false if lefts.nil?
|
|
28
|
+
rights = _values(1, fact, maps, fb)
|
|
29
|
+
return false if rights.nil?
|
|
30
|
+
lefts.any? do |l|
|
|
31
|
+
l = l.floor if l.is_a?(Time) && @op == :==
|
|
32
|
+
rights.any? do |r|
|
|
33
|
+
r = r.floor if r.is_a?(Time) && @op == :==
|
|
34
|
+
l.send(@op, r)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
# Concat term.
|
|
8
|
+
#
|
|
9
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
10
|
+
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
11
|
+
# License:: MIT
|
|
12
|
+
class Factbase::Concat < Factbase::TermBase
|
|
13
|
+
def initialize(operands)
|
|
14
|
+
super()
|
|
15
|
+
@operands = operands
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Evaluate term on a fact.
|
|
19
|
+
# @param [Factbase::Fact] fact The fact
|
|
20
|
+
# @param [Array<Factbase::Fact>] maps All maps available
|
|
21
|
+
# @param [Factbase] fb Factbase to use for sub-queries
|
|
22
|
+
# @return [String] The concatenated string
|
|
23
|
+
def evaluate(fact, maps, fb)
|
|
24
|
+
(0..(@operands.length - 1)).map { |i| _values(i, fact, maps, fb)&.first }.join
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
# The 'count' term is used to perform a count operation on a set of maps.
|
|
8
|
+
class Factbase::Count < Factbase::TermBase
|
|
9
|
+
# Constructor.
|
|
10
|
+
# @param [Array] operands Operands
|
|
11
|
+
def initialize(operands)
|
|
12
|
+
super()
|
|
13
|
+
@operands = operands
|
|
14
|
+
@op = :count
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Evaluate term on a fact.
|
|
18
|
+
# @param [Factbase::Fact] _fact The fact
|
|
19
|
+
# @param [Array<Factbase::Fact>] maps All maps available
|
|
20
|
+
# @param [Factbase] _fb Factbase to use for sub-queries
|
|
21
|
+
# @return [Integer] The count of maps
|
|
22
|
+
def evaluate(_fact, maps, _fb)
|
|
23
|
+
maps.size
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/factbase/terms/defn.rb
CHANGED
|
@@ -3,15 +3,26 @@
|
|
|
3
3
|
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
4
|
# SPDX-License-Identifier: MIT
|
|
5
5
|
|
|
6
|
-
require_relative '
|
|
6
|
+
require_relative 'base'
|
|
7
7
|
|
|
8
|
-
# Defn terms.
|
|
9
|
-
#
|
|
8
|
+
# Factbase::Defn is responsible for defining new terms in the Factbase system.
|
|
10
9
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
11
10
|
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
12
11
|
# License:: MIT
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
class Factbase::Defn < Factbase::TermBase
|
|
13
|
+
# Constructor.
|
|
14
|
+
# @param [Array] operands Operands
|
|
15
|
+
def initialize(operands)
|
|
16
|
+
super()
|
|
17
|
+
@operands = operands
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Evaluate term on a fact.
|
|
21
|
+
# @param [Factbase::Fact] _fact The fact
|
|
22
|
+
# @param [Array<Factbase::Fact>] _maps All maps available
|
|
23
|
+
# @param [Factbase] _fb Factbase to use for sub-queries
|
|
24
|
+
# @return [Object] Term definition result
|
|
25
|
+
def evaluate(_fact, _maps, _fb)
|
|
15
26
|
assert_args(2)
|
|
16
27
|
fn = @operands[0]
|
|
17
28
|
raise "A symbol expected as first argument of 'defn'" unless fn.is_a?(Symbol)
|
|
@@ -24,14 +35,4 @@ module Factbase::Defn
|
|
|
24
35
|
# rubocop:enable Security/Eval
|
|
25
36
|
true
|
|
26
37
|
end
|
|
27
|
-
|
|
28
|
-
def undef(_fact, _maps, _fb)
|
|
29
|
-
assert_args(1)
|
|
30
|
-
fn = @operands[0]
|
|
31
|
-
raise "A symbol expected as first argument of 'undef'" unless fn.is_a?(Symbol)
|
|
32
|
-
if Factbase::Term.private_instance_methods(false).include?(fn)
|
|
33
|
-
Factbase::Term.class_eval("undef :#{fn}", __FILE__, __LINE__ - 1) # undef :foo
|
|
34
|
-
end
|
|
35
|
-
true
|
|
36
|
-
end
|
|
37
38
|
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
# This class represents a 'div' term within the Factbase.
|
|
8
|
+
# It performs a division operation over the given operands.
|
|
9
|
+
class Factbase::Div < Factbase::TermBase
|
|
10
|
+
# Constructor.
|
|
11
|
+
# @param [Array] operands Operands
|
|
12
|
+
def initialize(operands)
|
|
13
|
+
super()
|
|
14
|
+
@div = Factbase::Arithmetic.new(:/, operands)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Evaluate term on a fact.
|
|
18
|
+
# @param [Factbase::Fact] fact The fact
|
|
19
|
+
# @param [Array<Factbase::Fact>] maps All maps available
|
|
20
|
+
# @param [Factbase] fb Factbase to use for sub-queries
|
|
21
|
+
# @return [Object] Result of the division
|
|
22
|
+
def evaluate(fact, maps, fb)
|
|
23
|
+
@div.evaluate(fact, maps, fb)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
|
|
8
|
+
# Represents a logical "either" term.
|
|
9
|
+
# The term evaluates its operands and returns the first non-nil value.
|
|
10
|
+
class Factbase::Either < Factbase::TermBase
|
|
11
|
+
# Constructor.
|
|
12
|
+
# @param [Array] operands Operands
|
|
13
|
+
def initialize(operands)
|
|
14
|
+
super()
|
|
15
|
+
@operands = operands
|
|
16
|
+
@op = :either
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Evaluate term on a fact.
|
|
20
|
+
# @param [Factbase::Fact] fact The fact
|
|
21
|
+
# @param [Array<Factbase::Fact>] maps All maps available
|
|
22
|
+
# @param [Factbase] fb Factbase to use for sub-queries
|
|
23
|
+
# @return [Object] First operand if not nil, otherwise second operand
|
|
24
|
+
# @return [Boolean] True if first operand is false OR both are true
|
|
25
|
+
def evaluate(fact, maps, fb)
|
|
26
|
+
assert_args(2)
|
|
27
|
+
v = _values(0, fact, maps, fb)
|
|
28
|
+
return v unless v.nil?
|
|
29
|
+
_values(1, fact, maps, fb)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
|
|
8
|
+
# The `Factbase::Env` class is used to evaluate terms based on environment variables.
|
|
9
|
+
# It retrieves the value of an environment variable or returns a default value if the variable is not set.
|
|
10
|
+
class Factbase::Env < Factbase::TermBase
|
|
11
|
+
# Constructor.
|
|
12
|
+
# @param [Array] operands Operands
|
|
13
|
+
def initialize(operands)
|
|
14
|
+
super()
|
|
15
|
+
@operands = operands
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Evaluate term on a fact.
|
|
19
|
+
# @param [Factbase::Fact] fact The fact
|
|
20
|
+
# @param [Array<Factbase::Fact>] maps All maps available
|
|
21
|
+
# @param [Factbase] fb Factbase to use for sub-queries
|
|
22
|
+
# @return [String] The value of the environment variable or the default
|
|
23
|
+
def evaluate(fact, maps, fb)
|
|
24
|
+
assert_args(2)
|
|
25
|
+
n = _values(0, fact, maps, fb)[0]
|
|
26
|
+
ENV.fetch(n.upcase) { _values(1, fact, maps, fb)[0] }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
require_relative 'compare'
|
|
8
|
+
|
|
9
|
+
# Represents an equality term in the Factbase.
|
|
10
|
+
# This class encapsulates the evaluation of equality comparisons
|
|
11
|
+
# between operands within the context of a Factbase.
|
|
12
|
+
class Factbase::Eq < Factbase::TermBase
|
|
13
|
+
# Constructor.
|
|
14
|
+
# @param [Array] operands Operands
|
|
15
|
+
def initialize(operands)
|
|
16
|
+
super()
|
|
17
|
+
@op = Factbase::Compare.new(:==, operands)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Evaluate term on a fact.
|
|
21
|
+
# @param [Factbase::Fact] fact The fact
|
|
22
|
+
# @param [Array<Factbase::Fact>] maps All maps available
|
|
23
|
+
# @param [Factbase] fb Factbase to use for sub-queries
|
|
24
|
+
# @return [Boolean] The result of the equality comparison
|
|
25
|
+
def evaluate(fact, maps, fb)
|
|
26
|
+
@op.evaluate(fact, maps, fb)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
|
|
8
|
+
# Represents a term that checks if a certain condition exists within the factbase.
|
|
9
|
+
# This class evaluates whether a specific term exists in the given context of facts.
|
|
10
|
+
class Factbase::Exists < Factbase::TermBase
|
|
11
|
+
# Constructor.
|
|
12
|
+
# @param [Array] operands Operands
|
|
13
|
+
def initialize(operands)
|
|
14
|
+
super()
|
|
15
|
+
@operands = operands
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Evaluate term on a fact.
|
|
19
|
+
# @param [Factbase::Fact] fact The fact
|
|
20
|
+
# @param [Array<Factbase::Fact>] _maps All maps available
|
|
21
|
+
# @param [Factbase] _fb Factbase to use for sub-queries
|
|
22
|
+
# @return [Boolean] True if exists
|
|
23
|
+
def evaluate(fact, _maps, _fb)
|
|
24
|
+
assert_args(1)
|
|
25
|
+
!_by_symbol(0, fact).nil?
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
# The 'first' term is used to retrieve the value of a specified key from the first map in a set of maps.
|
|
8
|
+
class Factbase::First < Factbase::TermBase
|
|
9
|
+
# Constructor.
|
|
10
|
+
# @param [Array] operands Operands
|
|
11
|
+
def initialize(operands)
|
|
12
|
+
super()
|
|
13
|
+
@operands = operands
|
|
14
|
+
@op = :first
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Evaluate term on a fact.
|
|
18
|
+
# @param [Factbase::Fact] _fact The fact
|
|
19
|
+
# @param [Array<Factbase::Fact>] maps All maps available
|
|
20
|
+
# @param [Factbase] _fb Factbase to use for sub-queries
|
|
21
|
+
# @return [Object] The value of the specified key from the first map
|
|
22
|
+
def evaluate(_fact, maps, _fb)
|
|
23
|
+
assert_args(1)
|
|
24
|
+
k = @operands[0]
|
|
25
|
+
raise "A symbol is expected, but #{k} provided" unless k.is_a?(Symbol)
|
|
26
|
+
first = maps[0]
|
|
27
|
+
return nil if first.nil?
|
|
28
|
+
first[k.to_s]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
require_relative 'compare'
|
|
8
|
+
|
|
9
|
+
# Represents a greater-than comparison term in the Factbase.
|
|
10
|
+
# This class is used to evaluate whether a given fact satisfies
|
|
11
|
+
# the greater-than condition with the provided operands.
|
|
12
|
+
class Factbase::Gt < Factbase::TermBase
|
|
13
|
+
# Constructor.
|
|
14
|
+
# @param [Array] operands Operands
|
|
15
|
+
def initialize(operands)
|
|
16
|
+
super()
|
|
17
|
+
@op = Factbase::Compare.new(:>, operands)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Evaluate term on a fact.
|
|
21
|
+
# @param [Factbase::Fact] fact The fact
|
|
22
|
+
# @param [Array<Factbase::Fact>] maps All maps available
|
|
23
|
+
# @param [Factbase] fb Factbase to use for sub-queries
|
|
24
|
+
# @return [Boolean] The result of the greater-than comparison
|
|
25
|
+
def evaluate(fact, maps, fb)
|
|
26
|
+
@op.evaluate(fact, maps, fb)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
require_relative 'base'
|
|
7
|
+
require_relative 'compare'
|
|
8
|
+
|
|
9
|
+
# It represents a term for evaluating whether a set of operands satisfies
|
|
10
|
+
# the "greater-than-or-equal-to" (>=) condition within the context of a factbase.
|
|
11
|
+
class Factbase::Gte < Factbase::TermBase
|
|
12
|
+
# Constructor.
|
|
13
|
+
# @param [Array] operands Operands
|
|
14
|
+
def initialize(operands)
|
|
15
|
+
super()
|
|
16
|
+
@op = Factbase::Compare.new(:>=, operands)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Evaluate term on a fact.
|
|
20
|
+
# @param [Factbase::Fact] fact The fact
|
|
21
|
+
# @param [Array<Factbase::Fact>] maps All maps available
|
|
22
|
+
# @param [Factbase] fb Factbase to use for sub-queries
|
|
23
|
+
# @return [Boolean] The result of the greater-than-or-equal comparison
|
|
24
|
+
def evaluate(fact, maps, fb)
|
|
25
|
+
@op.evaluate(fact, maps, fb)
|
|
26
|
+
end
|
|
27
|
+
end
|