Skip to content

Commit

Permalink
feat: single var filter
Browse files Browse the repository at this point in the history
  • Loading branch information
ulfurinn committed Aug 26, 2023
1 parent 244befc commit 4dc4aa2
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 6 deletions.
7 changes: 7 additions & 0 deletions lib/wongi/engine/dsl.ex
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,13 @@ defmodule Wongi.Engine.DSL do
"""
def filter(func), do: Filter.new(Function.new(func))

@doc """
A filter that passes if the value is a unary function that returns true.
The function will receive the variable as its argument.
"""
def filter(var, func), do: Filter.new(Function.new(var, func))

@doc """
A matcher that computes some value across all its incoming tokens, across all
execution paths.
Expand Down
14 changes: 11 additions & 3 deletions lib/wongi/engine/filter/function.ex
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
defmodule Wongi.Engine.Filter.Function do
@moduledoc false
defstruct [:func]
defstruct [:var, :func]

def new(func) do
%__MODULE__{func: func}
end

def new(var, func) do
%__MODULE__{var: var, func: func}
end

defimpl Wongi.Engine.Filter do
def pass?(%@for{func: func}, _token) when is_function(func, 0) do
def pass?(%@for{var: nil, func: func}, _token) when is_function(func, 0) do
func.()
end

def pass?(%@for{func: func}, token) when is_function(func, 1) do
def pass?(%@for{var: nil, func: func}, token) when is_function(func, 1) do
func.(token)
end

def pass?(%@for{var: var, func: func}, token) when is_function(func, 1) do
func.(token[var])
end
end
end
25 changes: 22 additions & 3 deletions test/wongi/engine/filter/function_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule Wongi.Engine.Filter.FunctionTest do
rule(
forall: [
has(:a, :b, var(:x)),
filter(&__MODULE__.true?/1)
filter(&__MODULE__.x_is_true?/1)
]
)
)
Expand All @@ -24,7 +24,7 @@ defmodule Wongi.Engine.Filter.FunctionTest do
rule(
forall: [
has(:a, :b, var(:x)),
filter(&__MODULE__.true?/1)
filter(&__MODULE__.x_is_true?/1)
]
)
)
Expand All @@ -33,5 +33,24 @@ defmodule Wongi.Engine.Filter.FunctionTest do
assert [] = tokens(rete, ref) |> Enum.to_list()
end

def true?(token), do: token[:x]
test "accepts a single variable" do
{rete, ref} =
new()
|> compile_and_get_ref(
rule(
forall: [
has(:a, :b, var(:x)),
filter(:x, &__MODULE__.true?/1)
]
)
)

rete = rete |> assert(:a, :b, false)
assert [] = tokens(rete, ref) |> Enum.to_list()
end

def x_is_true?(token), do: token[:x]

def true?(true), do: true
def true?(false), do: false
end

0 comments on commit 4dc4aa2

Please sign in to comment.