factbase 0.4.0 → 0.5.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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/.0pdd.yml +1 -1
  3. data/.github/workflows/actionlint.yml +1 -1
  4. data/.github/workflows/benchmark.yml +64 -0
  5. data/.github/workflows/codecov.yml +4 -2
  6. data/.github/workflows/copyrights.yml +2 -2
  7. data/.github/workflows/markdown-lint.yml +1 -1
  8. data/.github/workflows/pdd.yml +1 -1
  9. data/.github/workflows/rake.yml +2 -2
  10. data/.github/workflows/xcop.yml +1 -1
  11. data/.github/workflows/yamllint.yml +1 -1
  12. data/.gitignore +1 -1
  13. data/.rubocop.yml +6 -1
  14. data/.rultor.yml +2 -2
  15. data/.simplecov +1 -1
  16. data/.yamllint.yml +9 -4
  17. data/Gemfile +9 -7
  18. data/Gemfile.lock +99 -78
  19. data/LICENSE.txt +1 -1
  20. data/README.md +33 -0
  21. data/Rakefile +6 -1
  22. data/benchmarks/simple.rb +96 -0
  23. data/factbase.gemspec +1 -1
  24. data/lib/factbase/accum.rb +2 -2
  25. data/lib/factbase/fact.rb +6 -4
  26. data/lib/factbase/flatten.rb +2 -2
  27. data/lib/factbase/inv.rb +2 -2
  28. data/lib/factbase/looged.rb +6 -5
  29. data/lib/factbase/pre.rb +2 -2
  30. data/lib/factbase/query.rb +16 -8
  31. data/lib/factbase/query_once.rb +71 -0
  32. data/lib/factbase/rules.rb +3 -3
  33. data/lib/factbase/syntax.rb +13 -8
  34. data/lib/factbase/tee.rb +2 -2
  35. data/lib/factbase/term.rb +33 -5
  36. data/lib/factbase/term_once.rb +84 -0
  37. data/lib/factbase/terms/aggregates.rb +4 -4
  38. data/lib/factbase/terms/aliases.rb +5 -5
  39. data/lib/factbase/terms/casting.rb +2 -2
  40. data/lib/factbase/terms/debug.rb +2 -2
  41. data/lib/factbase/terms/defn.rb +2 -2
  42. data/lib/factbase/terms/logical.rb +3 -3
  43. data/lib/factbase/terms/math.rb +2 -2
  44. data/lib/factbase/terms/meta.rb +2 -2
  45. data/lib/factbase/terms/ordering.rb +2 -2
  46. data/lib/factbase/terms/strings.rb +2 -2
  47. data/lib/factbase/terms/system.rb +2 -2
  48. data/lib/factbase/to_json.rb +2 -2
  49. data/lib/factbase/to_xml.rb +2 -2
  50. data/lib/factbase/to_yaml.rb +2 -2
  51. data/lib/factbase.rb +16 -6
  52. data/test/factbase/terms/test_aggregates.rb +6 -6
  53. data/test/factbase/terms/test_aliases.rb +6 -6
  54. data/test/factbase/terms/test_casting.rb +6 -6
  55. data/test/factbase/terms/test_debug.rb +53 -0
  56. data/test/factbase/terms/test_defn.rb +15 -15
  57. data/test/factbase/terms/test_logical.rb +15 -13
  58. data/test/factbase/terms/test_math.rb +42 -42
  59. data/test/factbase/terms/test_meta.rb +87 -0
  60. data/test/factbase/terms/test_ordering.rb +45 -0
  61. data/test/factbase/terms/test_strings.rb +8 -8
  62. data/test/factbase/terms/test_system.rb +6 -6
  63. data/test/factbase/test_accum.rb +9 -9
  64. data/test/factbase/test_fact.rb +22 -22
  65. data/test/factbase/test_flatten.rb +6 -6
  66. data/test/factbase/test_inv.rb +3 -3
  67. data/test/factbase/test_looged.rb +13 -13
  68. data/test/factbase/test_pre.rb +2 -2
  69. data/test/factbase/test_query.rb +17 -17
  70. data/test/factbase/test_rules.rb +8 -8
  71. data/test/factbase/test_syntax.rb +29 -9
  72. data/test/factbase/test_tee.rb +11 -11
  73. data/test/factbase/test_term.rb +18 -18
  74. data/test/factbase/test_to_json.rb +4 -4
  75. data/test/factbase/test_to_xml.rb +12 -14
  76. data/test/factbase/test_to_yaml.rb +3 -3
  77. data/test/test__helper.rb +2 -2
  78. data/test/test_factbase.rb +198 -18
  79. metadata +12 -5
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -25,7 +25,7 @@ require_relative '../../factbase'
25
25
  # Aggregating terms.
26
26
  #
27
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  module Factbase::Term::Aggregates
31
31
  def min(_fact, maps)
@@ -81,7 +81,7 @@ module Factbase::Term::Aggregates
81
81
  raise "A term expected, but '#{selector}' provided" unless selector.is_a?(Factbase::Term)
82
82
  term = @operands[1]
83
83
  raise "A term expected, but '#{term}' provided" unless term.is_a?(Factbase::Term)
84
- subset = Factbase::Query.new(maps, Mutex.new, selector.to_s).each(fact).to_a
84
+ subset = @fb.query(selector.to_s, maps).each(fact).to_a
85
85
  term.evaluate(nil, subset)
86
86
  end
87
87
 
@@ -89,7 +89,7 @@ module Factbase::Term::Aggregates
89
89
  assert_args(1)
90
90
  term = @operands[0]
91
91
  raise "A term expected, but '#{term}' provided" unless term.is_a?(Factbase::Term)
92
- Factbase::Query.new(maps, Mutex.new, term.to_s).each(fact).to_a.empty?
92
+ @fb.query(term.to_s, maps).each(fact).to_a.empty?
93
93
  end
94
94
 
95
95
  def best(maps)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -25,7 +25,7 @@ require_relative '../../factbase'
25
25
  # Aliases terms.
26
26
  #
27
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  module Factbase::Term::Aliases
31
31
  def as(fact, maps)
@@ -33,7 +33,7 @@ module Factbase::Term::Aliases
33
33
  a = @operands[0]
34
34
  raise "A symbol expected as first argument of 'as'" unless a.is_a?(Symbol)
35
35
  vv = the_values(1, fact, maps)
36
- vv&.each { |v| fact.send("#{a}=", v) }
36
+ vv&.each { |v| fact.send(:"#{a}=", v) }
37
37
  true
38
38
  end
39
39
 
@@ -47,11 +47,11 @@ module Factbase::Term::Aliases
47
47
  .map { |j| j.size == 1 ? [j[0], j[0]] : j }
48
48
  term = @operands[1]
49
49
  raise "A term expected, but '#{term}' provided" unless term.is_a?(Factbase::Term)
50
- subset = Factbase::Query.new(maps, Mutex.new, term.to_s).each(fact).to_a
50
+ subset = @fb.query(term.to_s, maps).each(fact).to_a
51
51
  subset.each do |s|
52
52
  jumps.each do |to, from|
53
53
  s[from]&.each do |v|
54
- fact.send("#{to}=", v)
54
+ fact.send(:"#{to}=", v)
55
55
  end
56
56
  end
57
57
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -25,7 +25,7 @@ require_relative '../../factbase'
25
25
  # Casting terms.
26
26
  #
27
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  module Factbase::Term::Casting
31
31
  def to_string(fact, maps)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -25,7 +25,7 @@ require_relative '../../factbase'
25
25
  # Debug terms.
26
26
  #
27
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  module Factbase::Term::Debug
31
31
  def traced(fact, maps)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -25,7 +25,7 @@ require_relative '../../factbase'
25
25
  # Defn terms.
26
26
  #
27
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  module Factbase::Term::Defn
31
31
  def defn(_fact, _maps)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -25,7 +25,7 @@ require_relative '../../factbase'
25
25
  # Logical terms.
26
26
  #
27
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  module Factbase::Term::Logical
31
31
  def always(_fact, _maps)
@@ -82,7 +82,7 @@ module Factbase::Term::Logical
82
82
  ops << o
83
83
  end
84
84
  return ops[0] if ops.size == 1
85
- Factbase::Term.new(@op, ops)
85
+ Factbase::Term.new(@fb, @op, ops)
86
86
  end
87
87
 
88
88
  def and_simplify
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -25,7 +25,7 @@ require_relative '../../factbase'
25
25
  # Math terms.
26
26
  #
27
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  module Factbase::Term::Math
31
31
  def plus(fact, maps)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -25,7 +25,7 @@ require_relative '../../factbase'
25
25
  # Meta terms.
26
26
  #
27
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  module Factbase::Term::Meta
31
31
  def exists(fact, _maps)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -25,7 +25,7 @@ require_relative '../../factbase'
25
25
  # Ordering terms.
26
26
  #
27
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  module Factbase::Term::Ordering
31
31
  def prev(fact, maps)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -25,7 +25,7 @@ require_relative '../../factbase'
25
25
  # String terms.
26
26
  #
27
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  module Factbase::Term::Strings
31
31
  def concat(fact, maps)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -25,7 +25,7 @@ require_relative '../../factbase'
25
25
  # System-level terms.
26
26
  #
27
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  module Factbase::Term::System
31
31
  def env(fact, maps)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -33,7 +33,7 @@ require_relative '../factbase/flatten'
33
33
  # puts Factbase::ToJSON.new(fb).json
34
34
  #
35
35
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
36
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
36
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
37
37
  # License:: MIT
38
38
  class Factbase::ToJSON
39
39
  # Constructor.
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -34,7 +34,7 @@ require_relative '../factbase/flatten'
34
34
  # puts Factbase::ToXML.new(fb).xml
35
35
  #
36
36
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
37
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
37
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
38
38
  # License:: MIT
39
39
  class Factbase::ToXML
40
40
  # Constructor.
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -33,7 +33,7 @@ require_relative '../factbase/flatten'
33
33
  # puts Factbase::ToYAML.new(fb).yaml
34
34
  #
35
35
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
36
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
36
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
37
37
  # License:: MIT
38
38
  class Factbase::ToYAML
39
39
  # Constructor.
data/lib/factbase.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -77,20 +77,23 @@ require 'yaml'
77
77
  # It is NOT thread-safe!
78
78
  #
79
79
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
80
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
80
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
81
81
  # License:: MIT
82
82
  class Factbase
83
83
  # Current version of the gem (changed by .rultor.yml on every release)
84
- VERSION = '0.4.0'
84
+ VERSION = '0.5.0'
85
85
 
86
86
  # An exception that may be thrown in a transaction, to roll it back.
87
87
  class Rollback < StandardError; end
88
88
 
89
+ attr_reader :cache
90
+
89
91
  # Constructor.
90
92
  # @param [Array<Hash>] facts Array of facts to start with
91
93
  def initialize(facts = [])
92
94
  @maps = facts
93
95
  @mutex = Mutex.new
96
+ @cache = {}
94
97
  end
95
98
 
96
99
  # Make a deep duplicate of this factbase.
@@ -118,8 +121,9 @@ class Factbase
118
121
  @mutex.synchronize do
119
122
  @maps << map
120
123
  end
124
+ @cache.clear
121
125
  require_relative 'factbase/fact'
122
- Factbase::Fact.new(@mutex, map)
126
+ Factbase::Fact.new(self, @mutex, map)
123
127
  end
124
128
 
125
129
  # Create a query capable of iterating.
@@ -140,9 +144,15 @@ class Factbase
140
144
  # +README.md+ file of the repository.
141
145
  #
142
146
  # @param [String] query The query to use for selections
143
- def query(query)
147
+ # @param [Array<Hash>] maps Custom maps
148
+ def query(query, maps = @maps)
144
149
  require_relative 'factbase/query'
145
- Factbase::Query.new(@maps, @mutex, query)
150
+ require_relative 'factbase/query_once'
151
+ Factbase::QueryOnce.new(
152
+ self,
153
+ Factbase::Query.new(self, maps, @mutex, query),
154
+ maps
155
+ )
146
156
  end
147
157
 
148
158
  # Run an ACID transaction, which will either modify the factbase
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -26,7 +26,7 @@ require_relative '../../../lib/factbase/syntax'
26
26
 
27
27
  # Aggregates test.
28
28
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
29
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
30
30
  # License:: MIT
31
31
  class TestAggregates < Minitest::Test
32
32
  def test_aggregation
@@ -47,10 +47,10 @@ class TestAggregates < Minitest::Test
47
47
  '(eq x (agg (eq y 0) (first x)))' => '(eq x 1)',
48
48
  '(agg (eq foo 42) (always))' => '(eq x 1)'
49
49
  }.each do |q, r|
50
- t = Factbase::Syntax.new(q).to_term
50
+ t = Factbase::Syntax.new(Factbase.new, q).to_term
51
51
  f = maps.find { |m| t.evaluate(fact(m), maps) }
52
- assert(!f.nil?, "nothing found by: #{q}")
53
- assert(Factbase::Syntax.new(r).to_term.evaluate(fact(f), []))
52
+ refute_nil(f, "nothing found by: #{q}")
53
+ assert(Factbase::Syntax.new(Factbase.new, r).to_term.evaluate(fact(f), []))
54
54
  end
55
55
  end
56
56
 
@@ -63,7 +63,7 @@ class TestAggregates < Minitest::Test
63
63
  '(empty (eq y 42))' => true,
64
64
  '(empty (eq x 1))' => false
65
65
  }.each do |q, r|
66
- t = Factbase::Syntax.new(q).to_term
66
+ t = Factbase::Syntax.new(Factbase.new, q).to_term
67
67
  assert_equal(r, t.evaluate(nil, maps), q)
68
68
  end
69
69
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -27,7 +27,7 @@ require_relative '../../../lib/factbase/accum'
27
27
 
28
28
  # Aliases test.
29
29
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
30
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
30
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
31
31
  # License:: MIT
32
32
  class TestAliases < Minitest::Test
33
33
  def test_aliases
@@ -41,11 +41,11 @@ class TestAliases < Minitest::Test
41
41
  '(as foo (plus bar 1))' => '(absent foo)',
42
42
  '(as foo (minus t1 t2))' => '(when (exists foo) (eq "Float" (type foo)))'
43
43
  }.each do |q, r|
44
- t = Factbase::Syntax.new(q).to_term
44
+ t = Factbase::Syntax.new(Factbase.new, q).to_term
45
45
  maps.each do |m|
46
46
  f = Factbase::Accum.new(fact(m), {}, false)
47
47
  next unless t.evaluate(f, maps)
48
- assert(Factbase::Syntax.new(r).to_term.evaluate(f, []), "#{q} -> #{f}")
48
+ assert(Factbase::Syntax.new(Factbase.new, r).to_term.evaluate(f, []), "#{q} -> #{f}")
49
49
  end
50
50
  end
51
51
  end
@@ -61,13 +61,13 @@ class TestAliases < Minitest::Test
61
61
  '(join "uuu" (eq x 1))' => '(absent uuu)',
62
62
  '(join "uuu <= fff" (eq fff 1))' => '(absent uuu)'
63
63
  }.each do |q, r|
64
- t = Factbase::Syntax.new(q).to_term
64
+ t = Factbase::Syntax.new(Factbase.new, q).to_term
65
65
  maps.each do |m|
66
66
  f = Factbase::Accum.new(fact(m), {}, false)
67
67
  require_relative '../../../lib/factbase/looged'
68
68
  f = Factbase::Looged::Fact.new(f, Loog::NULL)
69
69
  next unless t.evaluate(f, maps)
70
- assert(Factbase::Syntax.new(r).to_term.evaluate(f, []), "#{q} -> #{f} doesn't match #{r}")
70
+ assert(Factbase::Syntax.new(Factbase.new, r).to_term.evaluate(f, []), "#{q} -> #{f} doesn't match #{r}")
71
71
  end
72
72
  end
73
73
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -26,26 +26,26 @@ require_relative '../../../lib/factbase/term'
26
26
 
27
27
  # Math test.
28
28
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
29
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
29
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
30
30
  # License:: MIT
31
31
  class TestCasting < Minitest::Test
32
32
  def test_to_str
33
- t = Factbase::Term.new(:to_string, [Time.now])
33
+ t = Factbase::Term.new(Factbase.new, :to_string, [Time.now])
34
34
  assert_equal('String', t.evaluate(fact, []).class.to_s)
35
35
  end
36
36
 
37
37
  def test_to_integer
38
- t = Factbase::Term.new(:to_integer, [[42, 'hello']])
38
+ t = Factbase::Term.new(Factbase.new, :to_integer, [[42, 'hello']])
39
39
  assert_equal('Integer', t.evaluate(fact, []).class.to_s)
40
40
  end
41
41
 
42
42
  def test_to_float
43
- t = Factbase::Term.new(:to_float, [[3.14, 'hello']])
43
+ t = Factbase::Term.new(Factbase.new, :to_float, [[3.14, 'hello']])
44
44
  assert_equal('Float', t.evaluate(fact, []).class.to_s)
45
45
  end
46
46
 
47
47
  def test_to_time
48
- t = Factbase::Term.new(:to_time, [%w[2023-01-01 hello]])
48
+ t = Factbase::Term.new(Factbase.new, :to_time, [%w[2023-01-01 hello]])
49
49
  assert_equal('Time', t.evaluate(fact, []).class.to_s)
50
50
  end
51
51
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024-2025 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 'minitest/autorun'
24
+ require_relative '../../../lib/factbase/term'
25
+
26
+ # Debug test.
27
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
+ # License:: MIT
30
+ class TestDebug < Minitest::Test
31
+ def test_traced
32
+ t = Factbase::Term.new(Factbase.new, :traced, [Factbase::Term.new(Factbase.new, :defn, [:test_debug, 'self.to_s'])])
33
+ assert_output("(traced (defn test_debug 'self.to_s')) -> true\n") do
34
+ assert(t.evaluate(fact, []))
35
+ end
36
+ end
37
+
38
+ def test_traced_raises
39
+ e = assert_raises(StandardError) { Factbase::Term.new(Factbase.new, :traced, ['foo']).evaluate(fact, []) }
40
+ assert_match(/A term expected, but 'foo' provided/, e.message)
41
+ end
42
+
43
+ def test_traced_raises_when_too_many_args
44
+ e =
45
+ assert_raises(StandardError) do
46
+ Factbase::Term.new(
47
+ Factbase.new, :traced,
48
+ [Factbase::Term.new(Factbase.new, :defn, [:debug, 'self.to_s']), 'something']
49
+ ).evaluate(fact, [])
50
+ end
51
+ assert_match(/Too many \(\d+\) operands for 'traced' \(\d+ expected\)/, e.message)
52
+ end
53
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2024 Yegor Bugayenko
3
+ # Copyright (c) 2024-2025 Yegor Bugayenko
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  # of this software and associated documentation files (the 'Software'), to deal
@@ -25,41 +25,41 @@ require_relative '../../../lib/factbase/term'
25
25
 
26
26
  # Defn test.
27
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
29
29
  # License:: MIT
30
30
  class TestDefn < Minitest::Test
31
31
  def test_defn_simple
32
- t = Factbase::Term.new(:defn, [:foo, 'self.to_s'])
33
- assert_equal(true, t.evaluate(fact('foo' => 4), []))
34
- t1 = Factbase::Term.new(:foo, ['hello, world!'])
32
+ t = Factbase::Term.new(Factbase.new, :defn, [:foo, 'self.to_s'])
33
+ assert(t.evaluate(fact('foo' => 4), []))
34
+ t1 = Factbase::Term.new(Factbase.new, :foo, ['hello, world!'])
35
35
  assert_equal('(foo \'hello, world!\')', t1.evaluate(fact, []))
36
36
  end
37
37
 
38
38
  def test_defn_again_by_mistake
39
- t = Factbase::Term.new(:defn, [:and, 'self.to_s'])
40
- assert_raises do
39
+ t = Factbase::Term.new(Factbase.new, :defn, [:and, 'self.to_s'])
40
+ assert_raises(StandardError) do
41
41
  t.evaluate(fact, [])
42
42
  end
43
43
  end
44
44
 
45
45
  def test_defn_bad_name_by_mistake
46
- t = Factbase::Term.new(:defn, [:to_s, 'self.to_s'])
47
- assert_raises do
46
+ t = Factbase::Term.new(Factbase.new, :defn, [:to_s, 'self.to_s'])
47
+ assert_raises(StandardError) do
48
48
  t.evaluate(fact, [])
49
49
  end
50
50
  end
51
51
 
52
52
  def test_defn_bad_name_spelling_by_mistake
53
- t = Factbase::Term.new(:defn, [:'some-key', 'self.to_s'])
54
- assert_raises do
53
+ t = Factbase::Term.new(Factbase.new, :defn, [:'some-key', 'self.to_s'])
54
+ assert_raises(StandardError) do
55
55
  t.evaluate(fact, [])
56
56
  end
57
57
  end
58
58
 
59
59
  def test_undef_simple
60
- t = Factbase::Term.new(:defn, [:hello, 'self.to_s'])
61
- assert_equal(true, t.evaluate(fact, []))
62
- t = Factbase::Term.new(:undef, [:hello])
63
- assert_equal(true, t.evaluate(fact, []))
60
+ t = Factbase::Term.new(Factbase.new, :defn, [:hello, 'self.to_s'])
61
+ assert(t.evaluate(fact, []))
62
+ t = Factbase::Term.new(Factbase.new, :undef, [:hello])
63
+ assert(t.evaluate(fact, []))
64
64
  end
65
65
  end