Calling a macro when using

Hello everyone,

I am using https://github.com/sasa1977/fsm to dynamically generate a state machine for a chat bot, in the same fashion as the example:

defmodule DynamicFsm do
  use Fsm, initial_state: :stopped

  # define states and transition
  fsm = [
    stopped: [run: :running],
    running: [stop: :stopped]
  ]

  # loop through definition and dynamically call defstate/defevent
  for {state, transitions} <- fsm do
    defstate unquote(state) do
      for {event, target_state} <- transitions do
        defevent unquote(event) do
          next_state(unquote(target_state))
        end
      end
    end
  end
end

The chat bot consists of multiple state machines for the various functions it performs. I would like to have the macro that generates it in a base module and reuse that in the various scripts. For example:

defmodule App.Script do
  defmacro __using__(fsm: fsm) do
    quote do
      use Fsm

      # loop through definition and dynamically call defstate/defevent
      for {state, transitions} <- fsm do
        defstate unquote(state) do
          for {event, target_state} <- transitions do
            defevent unquote(event) do
              next_state(unquote(target_state))
            end
          end
        end
      end
    end
  end
end

Then I would like to use it as follows:

defmodule App.CarScript do
  use App.Script, fsm: [
    stopped: [run: :running],
    running: [stop: :stopped]
  ]
end

Is this even possible? How would I get this to work?

Too short on time for a detailed answer, but yes that is not only possible but you are very close to it (and kind of surprised your proposed one is not already there if you just binded the ‘fsm’ variable to the outer scope, although I might have generated the AST directly then returned it myself)

Thanks for the quick response Overmind! I’m banging my head here, just adding bind_quoted with the fsm variable indeed did the trick :slight_smile:

1 Like