Skip to content

Commit

Permalink
Clearer thinking: is_memory_for_type should use == rather than <:.
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkNahabedian committed Jan 4, 2025
1 parent 24bb484 commit 5b4e6a5
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 6 deletions.
11 changes: 8 additions & 3 deletions src/memory_nodes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,12 @@ label(node::IsaMemoryNode{T}) where {T} = "isa $T memory"
is_memory_for_type(node, typ::Type)::Bool
returns `true` if `node` stores objects of the specified type.
`typ` must batch the type stured by `node`, not merely be a subtype.
Used by [`find_memory_for_type`](@ref).
"""
is_memory_for_type(node::IsaMemoryNode, typ::Type)::Bool =
typeof(node).parameters[1] <: typ
typeof(node).parameters[1] == typ


Rete.is_memory_for_type(::AbstractMemoryNode, ::Any) = false
Expand Down Expand Up @@ -77,8 +78,12 @@ end
"""
askc(continuation, root::AbstractReteRootNode, t::Type)
calls `continuation` on every fact of the specified type (or its
subtypes) that are stored in the network rooted at `root`.
calls `continuation` on every fact of the specified type that are
stored in the network rooted at `root`.
Does not consider subtypes because that could lead to `continuation`
being called on the same fact more than once (from the memory node for
the type itself and from the memory nodes of subtypes).
Assumes all memory nodes are direct outputs of `root`.
Expand Down
3 changes: 3 additions & 0 deletions src/node_abstraction.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ determine if it stores that type of fact.
A memory node should remember exactly one copy of each fact it
receives and return each fact it has remembered exactly once for any
given call to [`askc`](@ref).
A memory node should only remember facts which match the type that the
memory node is defined to store. Not any of its subtypes.
"""
abstract type AbstractMemoryNode <: AbstractReteNode end

Expand Down
6 changes: 4 additions & 2 deletions test/rule_example_2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ inputs \toutputs \tfacts \tlabel
sort(["abc", "bcd", "cde", "def", "efg"])
# Test askc for subtypes:
count_by_type = DefaultDict{Type, Int}(0)
askc(root, Any) do fact
count_by_type[typeof(fact)] += 1
for o in root.outputs
askc(o) do fact
count_by_type[typeof(fact)] += 1
end
end
@test Set(collect(count_by_type)) ==
Set([Char => 7,
Expand Down
2 changes: 1 addition & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -176,4 +176,4 @@ include("rule_grouping.jl")
include("three_parameter_rule_example.jl")
include("test_rule_decls.jl")
include("test_copy_facts.jl")

include("test_thing_subthing.jl")
37 changes: 37 additions & 0 deletions test/test_thing_subthing.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

abstract type AbstractThing end

struct Thing1 <: AbstractThing
c::Char
end

struct Thing2 <: AbstractThing
c::Char
end

@rule JuxtaposeAbstractThingsRule(t1::AbstractThing, t2::AbstractThing, ::Tuple) begin
emit((t1.c, t2.c))
end

@rule JuxtaposeThings12Rule(t1::Thing1, t2::Thing2, ::String) begin
emit("$(t1.c)$(t2.c)")
end

@testset "test thing/subthing" begin
root = ReteRootNode("root")
install(root, JuxtaposeAbstractThingsRule)
install(root, JuxtaposeThings12Rule)
for c in 'a':'c'
receive(root, Thing1(c))
end
for c in 'd':'e'
receive(root, Thing2(c))
end
@test askc(Counter(), root, Thing1) == 3
@test askc(Counter(), root, Thing2) == 2
@test askc(Counter(), root, AbstractThing) == 5
@test askc(Counter(), root, String) == 6
@test askc(Counter(), root, Tuple) == 25
end


0 comments on commit 5b4e6a5

Please sign in to comment.