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.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -1
  3. data/Gemfile.lock +25 -20
  4. data/README.md +28 -27
  5. data/Rakefile +14 -6
  6. data/lib/factbase/cached/cached_query.rb +2 -0
  7. data/lib/factbase/indexed/indexed_absent.rb +25 -0
  8. data/lib/factbase/indexed/indexed_and.rb +79 -0
  9. data/lib/factbase/indexed/indexed_eq.rb +46 -0
  10. data/lib/factbase/indexed/indexed_exists.rb +25 -0
  11. data/lib/factbase/indexed/indexed_factbase.rb +46 -0
  12. data/lib/factbase/indexed/indexed_gt.rb +41 -0
  13. data/lib/factbase/indexed/indexed_lt.rb +41 -0
  14. data/lib/factbase/indexed/indexed_not.rb +32 -0
  15. data/lib/factbase/indexed/indexed_one.rb +25 -0
  16. data/lib/factbase/indexed/indexed_or.rb +28 -0
  17. data/lib/factbase/indexed/indexed_query.rb +2 -0
  18. data/lib/factbase/indexed/indexed_term.rb +29 -185
  19. data/lib/factbase/indexed/indexed_unique.rb +25 -0
  20. data/lib/factbase/query.rb +22 -8
  21. data/lib/factbase/sync/sync_factbase.rb +11 -11
  22. data/lib/factbase/sync/sync_query.rb +7 -8
  23. data/lib/factbase/term.rb +110 -91
  24. data/lib/factbase/terms/absent.rb +26 -0
  25. data/lib/factbase/terms/aggregates.rb +0 -13
  26. data/lib/factbase/terms/always.rb +27 -0
  27. data/lib/factbase/terms/and.rb +28 -0
  28. data/lib/factbase/terms/arithmetic.rb +55 -0
  29. data/lib/factbase/terms/as.rb +31 -0
  30. data/lib/factbase/terms/{debug.rb → assert.rb} +17 -15
  31. data/lib/factbase/terms/base.rb +17 -0
  32. data/lib/factbase/terms/boolean.rb +28 -0
  33. data/lib/factbase/terms/compare.rb +38 -0
  34. data/lib/factbase/terms/concat.rb +26 -0
  35. data/lib/factbase/terms/count.rb +25 -0
  36. data/lib/factbase/terms/defn.rb +16 -15
  37. data/lib/factbase/terms/div.rb +25 -0
  38. data/lib/factbase/terms/either.rb +31 -0
  39. data/lib/factbase/terms/env.rb +28 -0
  40. data/lib/factbase/terms/eq.rb +28 -0
  41. data/lib/factbase/terms/exists.rb +27 -0
  42. data/lib/factbase/terms/first.rb +30 -0
  43. data/lib/factbase/terms/gt.rb +28 -0
  44. data/lib/factbase/terms/gte.rb +27 -0
  45. data/lib/factbase/terms/head.rb +37 -0
  46. data/lib/factbase/terms/inverted.rb +34 -0
  47. data/lib/factbase/terms/{aliases.rb → join.rb} +15 -15
  48. data/lib/factbase/terms/logical.rb +0 -83
  49. data/lib/factbase/terms/lt.rb +28 -0
  50. data/lib/factbase/terms/lte.rb +28 -0
  51. data/lib/factbase/terms/many.rb +29 -0
  52. data/lib/factbase/terms/{strings.rb → matches.rb} +12 -12
  53. data/lib/factbase/terms/minus.rb +25 -0
  54. data/lib/factbase/terms/never.rb +26 -0
  55. data/lib/factbase/terms/nil.rb +26 -0
  56. data/lib/factbase/terms/not.rb +27 -0
  57. data/lib/factbase/terms/one.rb +30 -0
  58. data/lib/factbase/terms/or.rb +28 -0
  59. data/lib/factbase/terms/plus.rb +27 -0
  60. data/lib/factbase/terms/prev.rb +29 -0
  61. data/lib/factbase/terms/shared.rb +69 -0
  62. data/lib/factbase/terms/size.rb +30 -0
  63. data/lib/factbase/terms/sorted.rb +38 -0
  64. data/lib/factbase/terms/sprintf.rb +29 -0
  65. data/lib/factbase/terms/times.rb +25 -0
  66. data/lib/factbase/terms/to_float.rb +28 -0
  67. data/lib/factbase/terms/to_integer.rb +28 -0
  68. data/lib/factbase/terms/to_string.rb +28 -0
  69. data/lib/factbase/terms/to_time.rb +28 -0
  70. data/lib/factbase/terms/traced.rb +33 -0
  71. data/lib/factbase/terms/type.rb +31 -0
  72. data/lib/factbase/terms/undef.rb +33 -0
  73. data/lib/factbase/terms/unique.rb +34 -0
  74. data/lib/factbase/terms/when.rb +29 -0
  75. data/lib/factbase/terms/zero.rb +28 -0
  76. data/lib/factbase/version.rb +1 -1
  77. data/lib/factbase.rb +10 -1
  78. metadata +60 -10
  79. data/lib/factbase/terms/casting.rb +0 -41
  80. data/lib/factbase/terms/lists.rb +0 -57
  81. data/lib/factbase/terms/math.rb +0 -103
  82. data/lib/factbase/terms/meta.rb +0 -58
  83. data/lib/factbase/terms/ordering.rb +0 -34
  84. 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 '../../factbase'
6
+ require_relative 'base'
7
7
 
8
- # Debug terms.
9
- #
10
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
11
- # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
12
- # License:: MIT
13
- module Factbase::Debug
14
- def traced(fact, maps, fb)
15
- assert_args(1)
16
- t = @operands[0]
17
- raise "A term is expected, but '#{t}' provided" unless t.is_a?(Factbase::Term)
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
- def assert(fact, maps, fb)
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
@@ -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 '../../factbase'
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
- module Factbase::Defn
14
- def defn(_fact, _maps, _fb)
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