Created
November 28, 2023 17:37
-
-
Save vjache/9310838977ee7427ff7e73b0882b810a to your computer and use it in GitHub Desktop.
Behaviour Tree macro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule EcssManagementSystem.Driver.Bt do | |
@moduledoc """ | |
Example:` | |
defmodule BtScript do | |
use Bt | |
def run do | |
a = 1 | |
all do | |
any do | |
a > 0 | |
version_expired() | |
db_changed() | |
end | |
update_component() | |
end | |
end | |
defp version_expired do | |
"version_expired" |> IO.puts() | |
:false | |
end | |
defp db_changed do | |
"db_changed" |> IO.puts() | |
:true | |
end | |
defp update_component do | |
"update_component" |> IO.puts() | |
:success | |
end | |
end | |
""" | |
@doc false | |
defmacro __using__(opts) do | |
quote location: :keep, bind_quoted: [opts: opts] do | |
import EcssManagementSystem.Driver.Bt | |
end | |
end | |
defmacro any(do: block) do | |
expr = case block do | |
{bt, _, _} = x when bt == :any or bt == :all -> | |
call = Macro.expand(x, __ENV__) | |
quote do | |
continue_on_failure(unquote(call)) | |
end | |
{:__block__, _, calls} -> | |
{:__block__, [], calls |> Enum.map(fn call -> | |
call = case call do | |
{:any, _, _} = x -> Macro.expand(x, __ENV__) | |
{:all, _, _} = x -> Macro.expand(x, __ENV__) | |
_ -> call | |
end | |
quote do | |
continue_on_failure(unquote(call)) | |
end | |
end)} | |
end | |
s = quote do | |
try(do: unquote(expr), catch: (_, :success -> :success)) | |
end | |
s |> Macro.to_string() |> IO.puts() | |
s | |
end | |
defmacro all(do: block) do | |
expr = case block do | |
{bt, _, _} = x when bt == :any or bt == :all -> | |
call = Macro.expand(x, __ENV__) | |
quote do | |
continue_on_success(unquote(call)) | |
end | |
{:__block__, _, calls} -> | |
{:__block__, [], calls |> Enum.map(fn call -> | |
call = case call do | |
{:any, _, _} = x -> Macro.expand(x, __ENV__) | |
{:all, _, _} = x -> Macro.expand(x, __ENV__) | |
_ -> call | |
end | |
quote do | |
continue_on_success(unquote(call)) | |
end | |
end)} | |
end | |
s = quote do | |
try(do: unquote(expr), catch: (_, :failure -> :failure)) | |
end | |
s |> Macro.to_string() |> IO.puts() | |
s | |
end | |
def continue_on_failure(:success) do | |
throw(:success) | |
end | |
def continue_on_failure(:true) do | |
throw(:success) | |
end | |
def continue_on_failure(:ok) do | |
throw(:success) | |
end | |
def continue_on_failure(:failure) do | |
:failure | |
end | |
def continue_on_failure(:error) do | |
:failure | |
end | |
def continue_on_failure(:false) do | |
:failure | |
end | |
def continue_on_failure({:error, _}) do | |
:failure | |
end | |
def continue_on_success(:success) do | |
:success | |
end | |
def continue_on_success(:true) do | |
:success | |
end | |
def continue_on_success(:ok) do | |
:success | |
end | |
def continue_on_success(:failure) do | |
throw(:failure) | |
end | |
def continue_on_success(:error) do | |
throw(:failure) | |
end | |
def continue_on_success(:false) do | |
throw(:failure) | |
end | |
def continue_on_success({:error, _}) do | |
throw(:failure) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment