Using a macro to generate case statements

I’m trying to use a macro to convert text like this:

foo_stmt
bar_stmt

into:

case x do
  "foo" -> foo_stmt
   "bar" -> bar_stmt
end

I’ve got the stage where I can generate a list containing the AST for “foo” -> foo_stmt, “bar” -> bar_stmt but how do I put that into a case statement.

quote do
  case unquote(lexeme) do
    unquote_splicing(funcs) #what goes here?
  end
end

Assume ‘funcs’ is a list with the following AST.
[[{:->, [], [[“choice”], {:choice_stmt, [line: 58], nil}]}],
[{:->, [], [[“leaf”], {:leaf_stmt, [line: 58], nil}]}]]

2 Likes

I ended up writing the ast for the case statement directly (i.e. I didn’t use a quote statement)

result = {:case, [],
    [lexeme, [do: List.flatten([funcs])]]}
1 Like

Hey @sashang, have you tried just unquoting the clauses inside the case?

clauses = [{:->, [], [["foo"], :foo]},
           {:->, [], [["bar"], :bar]}]
Code.eval_quoted(quote(do: case "foo" do unquote(clauses) end))
#=> {:foo, []}
4 Likes

Thanks. Yes I did try that but it didn’t work because for some reason when generating my clauses, they were generated inside another list. I had something like this:

clauses = [[{:->, [], [["foo"], :foo]}],
       [{:->, [], [["bar"], :bar]}]]]

ANyway I fixed that and it works as you demonstrated. Thanks very much.

2 Likes