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,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
|
+
# This class represents a 'sorted' term in the Factbase.
|
|
8
|
+
# It evaluates whether the given facts satisfy the sorted condition.
|
|
9
|
+
class Factbase::Sorted < Factbase::TermBase
|
|
10
|
+
# Constructor.
|
|
11
|
+
# @param [Array] operands Operands
|
|
12
|
+
def initialize(operands)
|
|
13
|
+
super()
|
|
14
|
+
@operands = operands
|
|
15
|
+
@op = 'sorted'
|
|
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] Whether the value is sorted
|
|
23
|
+
def evaluate(_fact, _maps, _fb)
|
|
24
|
+
true
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def predict(maps, fb, params)
|
|
28
|
+
assert_args(2)
|
|
29
|
+
prop = @operands[0]
|
|
30
|
+
raise "A symbol is expected as first argument of 'sorted'" unless prop.is_a?(Symbol)
|
|
31
|
+
term = @operands[1]
|
|
32
|
+
raise "A term is expected, but '#{term}' provided" unless term.is_a?(Factbase::Term)
|
|
33
|
+
fb.query(term, maps).each(fb, params).to_a
|
|
34
|
+
.reject { |m| m[prop].nil? }
|
|
35
|
+
.sort_by { |m| m[prop].first }
|
|
36
|
+
.map { |m| m.all_properties.to_h { |k| [k, m[k]] } }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
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
|
+
# Format term.
|
|
9
|
+
#
|
|
10
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
11
|
+
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
12
|
+
# License:: MIT
|
|
13
|
+
class Factbase::Sprintf < Factbase::TermBase
|
|
14
|
+
def initialize(operands)
|
|
15
|
+
super()
|
|
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 [String] The formatted string
|
|
24
|
+
def evaluate(fact, maps, fb)
|
|
25
|
+
fmt = _values(0, fact, maps, fb)[0]
|
|
26
|
+
ops = (1..(@operands.length - 1)).map { |i| _values(i, fact, maps, fb)&.first }
|
|
27
|
+
format(*([fmt] + ops))
|
|
28
|
+
end
|
|
29
|
+
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 'times' term within the Factbase.
|
|
8
|
+
# It performs a multiplication operation over the given operands.
|
|
9
|
+
class Factbase::Times < Factbase::TermBase
|
|
10
|
+
# Constructor.
|
|
11
|
+
# @param [Array] operands Operands
|
|
12
|
+
def initialize(operands)
|
|
13
|
+
super()
|
|
14
|
+
@times = 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 multiplication
|
|
22
|
+
def evaluate(fact, maps, fb)
|
|
23
|
+
@times.evaluate(fact, maps, fb)
|
|
24
|
+
end
|
|
25
|
+
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
|
+
# Represents a float conversion term 'to_float'.
|
|
8
|
+
# This class is used to evaluate a term and return its float representation.
|
|
9
|
+
class Factbase::ToFloat < 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 [Float] Float representation of the value
|
|
22
|
+
def evaluate(fact, maps, fb)
|
|
23
|
+
assert_args(1)
|
|
24
|
+
vv = _values(0, fact, maps, fb)
|
|
25
|
+
return nil if vv.nil?
|
|
26
|
+
vv[0].to_f
|
|
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
|
+
# Represents an integer conversion term 'to_integer'.
|
|
8
|
+
# This class is used to evaluate a term and return its integer representation.
|
|
9
|
+
class Factbase::ToInteger < 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 [Integer] Integer representation of the value
|
|
22
|
+
def evaluate(fact, maps, fb)
|
|
23
|
+
assert_args(1)
|
|
24
|
+
vv = _values(0, fact, maps, fb)
|
|
25
|
+
return nil if vv.nil?
|
|
26
|
+
vv[0].to_i
|
|
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
|
+
# Represents a string conversion term 'to_string'.
|
|
8
|
+
# This class is used to evaluate a term and return its string representation.
|
|
9
|
+
class Factbase::ToString < 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 [String] The same value as string
|
|
22
|
+
def evaluate(fact, maps, fb)
|
|
23
|
+
assert_args(1)
|
|
24
|
+
vv = _values(0, fact, maps, fb)
|
|
25
|
+
return nil if vv.nil?
|
|
26
|
+
vv[0].to_s
|
|
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
|
+
# Represents a string conversion term 'to_time'.
|
|
8
|
+
# This class is used to evaluate a term and return its time representation.
|
|
9
|
+
class Factbase::ToTime < 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 [Time] Time representation of the value
|
|
22
|
+
def evaluate(fact, maps, fb)
|
|
23
|
+
assert_args(1)
|
|
24
|
+
vv = _values(0, fact, maps, fb)
|
|
25
|
+
return nil if vv.nil?
|
|
26
|
+
Time.parse(vv[0].to_s)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
# A class representing a traced term in the factbase.
|
|
9
|
+
# This class is responsible for evaluating a term and printing
|
|
10
|
+
# its evaluation result for tracing purposes.
|
|
11
|
+
class Factbase::Traced < Factbase::TermBase
|
|
12
|
+
# Constructor.
|
|
13
|
+
# @param [Array] operands Operands
|
|
14
|
+
def initialize(operands)
|
|
15
|
+
super()
|
|
16
|
+
@operands = operands
|
|
17
|
+
@op = 'traced'
|
|
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] Return value of the traced term
|
|
25
|
+
def evaluate(fact, maps, fb)
|
|
26
|
+
assert_args(1)
|
|
27
|
+
t = @operands[0]
|
|
28
|
+
raise "A term is expected, but '#{t}' provided" unless t.is_a?(Factbase::Term)
|
|
29
|
+
r = t.evaluate(fact, maps, fb)
|
|
30
|
+
puts "#{self} -> #{r}"
|
|
31
|
+
r
|
|
32
|
+
end
|
|
33
|
+
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 type term in the Factbase.
|
|
9
|
+
# This class evaluates the type of the given operand
|
|
10
|
+
# based on the provided fact, maps, and factbase.
|
|
11
|
+
class Factbase::Type < Factbase::TermBase
|
|
12
|
+
# Constructor.
|
|
13
|
+
# @param [Array] operands Operands
|
|
14
|
+
def initialize(operands)
|
|
15
|
+
super()
|
|
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 [String] Type of the operand
|
|
24
|
+
def evaluate(fact, _maps, _fb)
|
|
25
|
+
assert_args(1)
|
|
26
|
+
v = _by_symbol(0, fact)
|
|
27
|
+
return 'nil' if v.nil?
|
|
28
|
+
v = v[0] if v.respond_to?(:each) && v.size == 1
|
|
29
|
+
v.class.to_s
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
# Implements the `undef` term for Factbase, which removes a method from the class.
|
|
8
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
9
|
+
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
10
|
+
# License:: MIT
|
|
11
|
+
class Factbase::Undef < Factbase::TermBase
|
|
12
|
+
# Constructor.
|
|
13
|
+
# @param [Array] operands Operands
|
|
14
|
+
def initialize(operands)
|
|
15
|
+
super()
|
|
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] True if definition is successfully removed.
|
|
24
|
+
def evaluate(_fact, _maps, _fb)
|
|
25
|
+
assert_args(1)
|
|
26
|
+
fn = @operands[0]
|
|
27
|
+
raise "A symbol expected as first argument of 'undef'" unless fn.is_a?(Symbol)
|
|
28
|
+
if Factbase::Term.private_instance_methods(false).include?(fn)
|
|
29
|
+
Factbase::Term.class_eval("undef :#{fn}", __FILE__, __LINE__ - 1) # undef :foo
|
|
30
|
+
end
|
|
31
|
+
true
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
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 Factbase::Unique class provides functionality for evaluating the uniqueness
|
|
8
|
+
# of terms based on provided operands and facts.
|
|
9
|
+
class Factbase::Unique < 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 the value is unique, false otherwise
|
|
22
|
+
def evaluate(fact, maps, fb)
|
|
23
|
+
@seen = Set.new if @seen.nil?
|
|
24
|
+
raise "Too few operands for 'unique' (at least 1 expected)" if @operands.empty?
|
|
25
|
+
vv = (0..(@operands.size - 1)).map { |i| _values(i, fact, maps, fb) }
|
|
26
|
+
return false if vv.any?(nil)
|
|
27
|
+
pass = true
|
|
28
|
+
Enumerator.product(*vv).to_a.each do |t|
|
|
29
|
+
pass = false if @seen.include?(t)
|
|
30
|
+
@seen << t
|
|
31
|
+
end
|
|
32
|
+
pass
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
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 'when' class represents a conditional term in the Factbase.
|
|
8
|
+
# It evaluates the operands based on a logical "when" operation.
|
|
9
|
+
class Factbase::When < Factbase::TermBase
|
|
10
|
+
# Constructor.
|
|
11
|
+
# @param [Array] operands Operands
|
|
12
|
+
def initialize(operands)
|
|
13
|
+
super()
|
|
14
|
+
@operands = operands
|
|
15
|
+
@op = :when
|
|
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 first operand is false OR both are true
|
|
23
|
+
def evaluate(fact, maps, fb)
|
|
24
|
+
assert_args(2)
|
|
25
|
+
a = @operands[0]
|
|
26
|
+
b = @operands[1]
|
|
27
|
+
!a.evaluate(fact, maps, fb) || (a.evaluate(fact, maps, fb) && b.evaluate(fact, maps, fb))
|
|
28
|
+
end
|
|
29
|
+
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 `zero` term that evaluates whether any of the operand values is zero when applied to a fact.
|
|
9
|
+
class Factbase::Zero < 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 any value is zero
|
|
22
|
+
def evaluate(fact, maps, fb)
|
|
23
|
+
assert_args(1)
|
|
24
|
+
vv = _values(0, fact, maps, fb)
|
|
25
|
+
return false if vv.nil?
|
|
26
|
+
vv.any? { |v| (v.is_a?(Integer) || v.is_a?(Float)) && v.zero? }
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/factbase/version.rb
CHANGED
data/lib/factbase.rb
CHANGED
|
@@ -240,9 +240,18 @@ class Factbase
|
|
|
240
240
|
# The facts that existed in the factbase before importing will remain there.
|
|
241
241
|
# The facts from the incoming byte stream will be added to them.
|
|
242
242
|
#
|
|
243
|
+
# This method supports both the original format (Array of maps) and
|
|
244
|
+
# the IndexedFactbase format (Hash with :maps and :idx keys).
|
|
245
|
+
#
|
|
243
246
|
# @param [String] bytes Binary string to import
|
|
244
247
|
def import(bytes)
|
|
245
248
|
raise 'Empty input, cannot load a factbase' if bytes.empty?
|
|
246
|
-
|
|
249
|
+
data = Marshal.load(bytes)
|
|
250
|
+
@maps +=
|
|
251
|
+
if data.is_a?(Hash) && data.key?(:maps)
|
|
252
|
+
Marshal.load(data[:maps])
|
|
253
|
+
else
|
|
254
|
+
data
|
|
255
|
+
end
|
|
247
256
|
end
|
|
248
257
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: factbase
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.17.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yegor Bugayenko
|
|
@@ -180,10 +180,20 @@ files:
|
|
|
180
180
|
- lib/factbase/fact_as_yaml.rb
|
|
181
181
|
- lib/factbase/flatten.rb
|
|
182
182
|
- lib/factbase/impatient.rb
|
|
183
|
+
- lib/factbase/indexed/indexed_absent.rb
|
|
184
|
+
- lib/factbase/indexed/indexed_and.rb
|
|
185
|
+
- lib/factbase/indexed/indexed_eq.rb
|
|
186
|
+
- lib/factbase/indexed/indexed_exists.rb
|
|
183
187
|
- lib/factbase/indexed/indexed_fact.rb
|
|
184
188
|
- lib/factbase/indexed/indexed_factbase.rb
|
|
189
|
+
- lib/factbase/indexed/indexed_gt.rb
|
|
190
|
+
- lib/factbase/indexed/indexed_lt.rb
|
|
191
|
+
- lib/factbase/indexed/indexed_not.rb
|
|
192
|
+
- lib/factbase/indexed/indexed_one.rb
|
|
193
|
+
- lib/factbase/indexed/indexed_or.rb
|
|
185
194
|
- lib/factbase/indexed/indexed_query.rb
|
|
186
195
|
- lib/factbase/indexed/indexed_term.rb
|
|
196
|
+
- lib/factbase/indexed/indexed_unique.rb
|
|
187
197
|
- lib/factbase/inv.rb
|
|
188
198
|
- lib/factbase/light.rb
|
|
189
199
|
- lib/factbase/logged.rb
|
|
@@ -197,18 +207,58 @@ files:
|
|
|
197
207
|
- lib/factbase/taped.rb
|
|
198
208
|
- lib/factbase/tee.rb
|
|
199
209
|
- lib/factbase/term.rb
|
|
210
|
+
- lib/factbase/terms/absent.rb
|
|
200
211
|
- lib/factbase/terms/aggregates.rb
|
|
201
|
-
- lib/factbase/terms/
|
|
202
|
-
- lib/factbase/terms/
|
|
203
|
-
- lib/factbase/terms/
|
|
212
|
+
- lib/factbase/terms/always.rb
|
|
213
|
+
- lib/factbase/terms/and.rb
|
|
214
|
+
- lib/factbase/terms/arithmetic.rb
|
|
215
|
+
- lib/factbase/terms/as.rb
|
|
216
|
+
- lib/factbase/terms/assert.rb
|
|
217
|
+
- lib/factbase/terms/base.rb
|
|
218
|
+
- lib/factbase/terms/boolean.rb
|
|
219
|
+
- lib/factbase/terms/compare.rb
|
|
220
|
+
- lib/factbase/terms/concat.rb
|
|
221
|
+
- lib/factbase/terms/count.rb
|
|
204
222
|
- lib/factbase/terms/defn.rb
|
|
205
|
-
- lib/factbase/terms/
|
|
223
|
+
- lib/factbase/terms/div.rb
|
|
224
|
+
- lib/factbase/terms/either.rb
|
|
225
|
+
- lib/factbase/terms/env.rb
|
|
226
|
+
- lib/factbase/terms/eq.rb
|
|
227
|
+
- lib/factbase/terms/exists.rb
|
|
228
|
+
- lib/factbase/terms/first.rb
|
|
229
|
+
- lib/factbase/terms/gt.rb
|
|
230
|
+
- lib/factbase/terms/gte.rb
|
|
231
|
+
- lib/factbase/terms/head.rb
|
|
232
|
+
- lib/factbase/terms/inverted.rb
|
|
233
|
+
- lib/factbase/terms/join.rb
|
|
206
234
|
- lib/factbase/terms/logical.rb
|
|
207
|
-
- lib/factbase/terms/
|
|
208
|
-
- lib/factbase/terms/
|
|
209
|
-
- lib/factbase/terms/
|
|
210
|
-
- lib/factbase/terms/
|
|
211
|
-
- lib/factbase/terms/
|
|
235
|
+
- lib/factbase/terms/lt.rb
|
|
236
|
+
- lib/factbase/terms/lte.rb
|
|
237
|
+
- lib/factbase/terms/many.rb
|
|
238
|
+
- lib/factbase/terms/matches.rb
|
|
239
|
+
- lib/factbase/terms/minus.rb
|
|
240
|
+
- lib/factbase/terms/never.rb
|
|
241
|
+
- lib/factbase/terms/nil.rb
|
|
242
|
+
- lib/factbase/terms/not.rb
|
|
243
|
+
- lib/factbase/terms/one.rb
|
|
244
|
+
- lib/factbase/terms/or.rb
|
|
245
|
+
- lib/factbase/terms/plus.rb
|
|
246
|
+
- lib/factbase/terms/prev.rb
|
|
247
|
+
- lib/factbase/terms/shared.rb
|
|
248
|
+
- lib/factbase/terms/size.rb
|
|
249
|
+
- lib/factbase/terms/sorted.rb
|
|
250
|
+
- lib/factbase/terms/sprintf.rb
|
|
251
|
+
- lib/factbase/terms/times.rb
|
|
252
|
+
- lib/factbase/terms/to_float.rb
|
|
253
|
+
- lib/factbase/terms/to_integer.rb
|
|
254
|
+
- lib/factbase/terms/to_string.rb
|
|
255
|
+
- lib/factbase/terms/to_time.rb
|
|
256
|
+
- lib/factbase/terms/traced.rb
|
|
257
|
+
- lib/factbase/terms/type.rb
|
|
258
|
+
- lib/factbase/terms/undef.rb
|
|
259
|
+
- lib/factbase/terms/unique.rb
|
|
260
|
+
- lib/factbase/terms/when.rb
|
|
261
|
+
- lib/factbase/terms/zero.rb
|
|
212
262
|
- lib/factbase/to_json.rb
|
|
213
263
|
- lib/factbase/to_xml.rb
|
|
214
264
|
- lib/factbase/to_yaml.rb
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
-
# SPDX-License-Identifier: MIT
|
|
5
|
-
|
|
6
|
-
require_relative '../../factbase'
|
|
7
|
-
|
|
8
|
-
# Casting terms.
|
|
9
|
-
#
|
|
10
|
-
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
11
|
-
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
12
|
-
# License:: MIT
|
|
13
|
-
module Factbase::Casting
|
|
14
|
-
def to_string(fact, maps, fb)
|
|
15
|
-
assert_args(1)
|
|
16
|
-
vv = _values(0, fact, maps, fb)
|
|
17
|
-
return nil if vv.nil?
|
|
18
|
-
vv[0].to_s
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def to_integer(fact, maps, fb)
|
|
22
|
-
assert_args(1)
|
|
23
|
-
vv = _values(0, fact, maps, fb)
|
|
24
|
-
return nil if vv.nil?
|
|
25
|
-
vv[0].to_i
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def to_float(fact, maps, fb)
|
|
29
|
-
assert_args(1)
|
|
30
|
-
vv = _values(0, fact, maps, fb)
|
|
31
|
-
return nil if vv.nil?
|
|
32
|
-
vv[0].to_f
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def to_time(fact, maps, fb)
|
|
36
|
-
assert_args(1)
|
|
37
|
-
vv = _values(0, fact, maps, fb)
|
|
38
|
-
return nil if vv.nil?
|
|
39
|
-
Time.parse(vv[0].to_s)
|
|
40
|
-
end
|
|
41
|
-
end
|
data/lib/factbase/terms/lists.rb
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
4
|
-
# SPDX-License-Identifier: MIT
|
|
5
|
-
|
|
6
|
-
require_relative '../../factbase'
|
|
7
|
-
|
|
8
|
-
# Lists management.
|
|
9
|
-
#
|
|
10
|
-
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
11
|
-
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
|
12
|
-
# License:: MIT
|
|
13
|
-
module Factbase::Lists
|
|
14
|
-
def sorted(_fact, _maps, _fb)
|
|
15
|
-
true
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def sorted_predict(maps, fb, params)
|
|
19
|
-
assert_args(2)
|
|
20
|
-
prop = @operands[0]
|
|
21
|
-
raise "A symbol is expected as first argument of 'sorted'" unless prop.is_a?(Symbol)
|
|
22
|
-
term = @operands[1]
|
|
23
|
-
raise "A term is expected, but '#{term}' provided" unless term.is_a?(Factbase::Term)
|
|
24
|
-
fb.query(term, maps).each(fb, params).to_a
|
|
25
|
-
.reject { |m| m[prop].nil? }
|
|
26
|
-
.sort_by { |m| m[prop].first }
|
|
27
|
-
.map { |m| m.all_properties.to_h { |k| [k, m[k]] } }
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def inverted(_fact, _maps, _fb)
|
|
31
|
-
true
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def inverted_predict(maps, fb, params)
|
|
35
|
-
assert_args(1)
|
|
36
|
-
term = @operands[0]
|
|
37
|
-
raise "A term is expected, but '#{term}' provided" unless term.is_a?(Factbase::Term)
|
|
38
|
-
fb.query(term, maps).each(fb, params).to_a
|
|
39
|
-
.reverse
|
|
40
|
-
.map { |m| m.all_properties.to_h { |k| [k, m[k]] } }
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def head(_fact, _maps, _fb)
|
|
44
|
-
true
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def head_predict(maps, fb, params)
|
|
48
|
-
assert_args(2)
|
|
49
|
-
max = @operands[0]
|
|
50
|
-
raise "An integer is expected as first argument of 'sorted'" unless max.is_a?(Integer)
|
|
51
|
-
term = @operands[1]
|
|
52
|
-
raise "A term is expected, but '#{term}' provided" unless term.is_a?(Factbase::Term)
|
|
53
|
-
fb.query(term, maps).each(fb, params).to_a
|
|
54
|
-
.take(max)
|
|
55
|
-
.map { |m| m.all_properties.to_h { |k| [k, m[k]] } }
|
|
56
|
-
end
|
|
57
|
-
end
|