Skip to content

Commit f0ddeb8

Browse files
authored
Merge pull request #339 from volodya-lombrozo/302-refactor-term-classes
feat(#302): create separate classes for 'as' and 'join' terms in Factbase
2 parents d94970a + 860df1a commit f0ddeb8

File tree

5 files changed

+90
-41
lines changed

5 files changed

+90
-41
lines changed

lib/factbase/term.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
require_relative 'terms/env'
1818
require_relative 'terms/defn'
1919
require_relative 'terms/undef'
20+
require_relative 'terms/as'
21+
require_relative 'terms/join'
2022

2123
# Term.
2224
#
@@ -72,9 +74,6 @@ class Factbase::Term
7274
require_relative 'terms/meta'
7375
include Factbase::Meta
7476

75-
require_relative 'terms/aliases'
76-
include Factbase::Aliases
77-
7877
require_relative 'terms/shared'
7978
include Factbase::TermShared
8079

@@ -94,7 +93,9 @@ def initialize(operator, operands)
9493
assert: Factbase::Assert.new(operands),
9594
env: Factbase::Env.new(operands),
9695
defn: Factbase::Defn.new(operands),
97-
undef: Factbase::Undef.new(operands)
96+
undef: Factbase::Undef.new(operands),
97+
as: Factbase::As.new(operands),
98+
join: Factbase::Join.new(operands)
9899
}
99100
end
100101

lib/factbase/terms/as.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

lib/factbase/terms/aliases.rb renamed to lib/factbase/terms/join.rb

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,24 @@
33
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
44
# SPDX-License-Identifier: MIT
55

6-
require_relative '../../factbase'
6+
require_relative 'base'
77

8-
# Aliases terms.
9-
#
10-
# Author:: Yegor Bugayenko (yegor256@gmail.com)
11-
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
12-
# License:: MIT
13-
module Factbase::Aliases
14-
def as(fact, maps, fb)
15-
assert_args(2)
16-
a = @operands[0]
17-
raise "A symbol is expected as first argument of 'as'" unless a.is_a?(Symbol)
18-
vv = _values(1, fact, maps, fb)
19-
vv&.each { |v| fact.send(:"#{a}=", v) }
20-
true
8+
# The Factbase::Join class is a specialized term that performs
9+
# join operations between facts based on specified attribute mappings.
10+
class Factbase::Join < Factbase::TermBase
11+
# Constructor.
12+
# @param [Array] operands Operands
13+
def initialize(operands)
14+
super()
15+
@operands = operands
2116
end
2217

23-
def join(fact, maps, fb)
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)
2424
assert_args(2)
2525
jumps = @operands[0]
2626
raise "A string is expected as first argument of 'join'" unless jumps.is_a?(String)

test/factbase/terms/test_as.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# frozen_string_literal: true
2+
3+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
4+
# SPDX-License-Identifier: MIT
5+
6+
require_relative '../../test__helper'
7+
require_relative '../../../lib/factbase/term'
8+
require_relative '../../../lib/factbase/terms/as'
9+
require_relative '../../../lib/factbase/syntax'
10+
require_relative '../../../lib/factbase/accum'
11+
12+
# Test for 'as' term.
13+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
14+
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
15+
# License:: MIT
16+
class TestAs < Factbase::Test
17+
def test_aliases
18+
maps = [
19+
{ 'x' => [1], 'y' => [0], 't1' => [Time.now], 't2' => [Time.now] },
20+
{ 'x' => [2], 'y' => [42], 't' => [Time.now] }
21+
]
22+
{
23+
'(as foo (plus x 1))' => '(exists foo)',
24+
'(as foo (plus x y))' => '(gt foo 0)',
25+
'(as foo (plus bar 1))' => '(absent foo)',
26+
'(as foo (minus t1 t2))' => '(when (exists foo) (eq "Float" (type foo)))'
27+
}.each do |q, r|
28+
t = Factbase::Syntax.new(q).to_term
29+
maps.each do |m|
30+
f = Factbase::Accum.new(fact(m), {}, false)
31+
next unless t.evaluate(f, maps, Factbase.new)
32+
assert(Factbase::Syntax.new(r).to_term.evaluate(f, [], Factbase.new), "#{q} -> #{f}")
33+
end
34+
end
35+
end
36+
end

test/factbase/terms/test_aliases.rb renamed to test/factbase/terms/test_join.rb

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,15 @@
66
require 'loog'
77
require_relative '../../test__helper'
88
require_relative '../../../lib/factbase/term'
9+
require_relative '../../../lib/factbase/terms/join'
910
require_relative '../../../lib/factbase/syntax'
1011
require_relative '../../../lib/factbase/accum'
1112

12-
# Aliases test.
13+
# Test for 'as' term.
1314
# Author:: Yegor Bugayenko (yegor256@gmail.com)
1415
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
1516
# License:: MIT
16-
class TestAliases < Factbase::Test
17-
def test_aliases
18-
maps = [
19-
{ 'x' => [1], 'y' => [0], 't1' => [Time.now], 't2' => [Time.now] },
20-
{ 'x' => [2], 'y' => [42], 't' => [Time.now] }
21-
]
22-
{
23-
'(as foo (plus x 1))' => '(exists foo)',
24-
'(as foo (plus x y))' => '(gt foo 0)',
25-
'(as foo (plus bar 1))' => '(absent foo)',
26-
'(as foo (minus t1 t2))' => '(when (exists foo) (eq "Float" (type foo)))'
27-
}.each do |q, r|
28-
t = Factbase::Syntax.new(q).to_term
29-
maps.each do |m|
30-
f = Factbase::Accum.new(fact(m), {}, false)
31-
next unless t.evaluate(f, maps, Factbase.new)
32-
assert(Factbase::Syntax.new(r).to_term.evaluate(f, [], Factbase.new), "#{q} -> #{f}")
33-
end
34-
end
35-
end
36-
17+
class TestJoin < Factbase::Test
3718
def test_join
3819
maps = [
3920
{ 'x' => 1, 'y' => 0, 'z' => 4 },

0 commit comments

Comments
 (0)