How to insert an AST as the code for a function body ?

51 views
Skip to first unread message

Kip Cole

unread,
Jul 28, 2016, 9:39:19 PM7/28/16
to elixir-lang-talk
I have a macro to define a function where one of the parameters is the AST of the function body.  But I can't work out how to insert the AST. Example:

      defmacro define_do_cardinal(rules, locale) do
        quote do
          defp do_cardinal(unquote(locale), n, i, v, w, f, t), do: unquote(rules)
        end
      end
  
unquote(rules) won't do it since unquoting doesn't add the code to the function it just inserts the AST as a literal.  I could, I suppose, hand craft the function header AST and insert the function body AST but that seems more work than I would expect.

Is there a way to insert an AST as the code for a function body?

José Valim

unread,
Jul 29, 2016, 5:50:33 AM7/29/16
to elixir-l...@googlegroups.com
Well, quoted expressions are meant to represent the code unless it is escaped, then you get the AST literal. So maybe the question is where the AST is being escaped?
--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-talk/34402692-3d20-447f-aca4-7e815d7badcc%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--


José Valim
Skype: jv.ptec
Founder and Director of R&D

Kip Cole

unread,
Jul 29, 2016, 8:10:20 AM7/29/16
to elixir-l...@googlegroups.com
José, thank you as always for your engagement.

I am basically hand-crafting the AST, mostly via leex/yecc with a few after-parsing transformations.  So I’m left with an AST in literal form (i.e. as a list of tuples - is that the right expression?).  What I’ve worked on in the mean time that does what I want  is:

  # Generate the functions to process plural rules
  @spec do_cardinal(binary, number, number, number, number, number, number) 
    :: :one | :two | :few | :many | :other
  Enum.each Cldr.known_locales, fn (locale) ->
    function_body = cardinal_rules[locale] |> rules_to_condition_statement(__MODULE__)
    function = quote do
      defp do_cardinal(unquote(locale), n, i, v, w, f, t), do: unquote(function_body)
    end
    Code.eval_quoted(function, [], __ENV__)
  end

In this case there’s no macro involved but I feel a little “unclean” about doing the Code.eval_quoted/3 part.


You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-talk" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-talk/kaJJGQVWdMs/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elixir-lang-ta...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-talk/CAGnRm4%2B_Nn2_01a-2FJHSDrwdLayWzQdyD1i%2BNmxdUrrjL%3D8xg%40mail.gmail.com.

José Valim

unread,
Jul 29, 2016, 8:12:18 AM7/29/16
to elixir-l...@googlegroups.com
Elixir supports something called unquote fragments, which means you can get rid of quote and the eval and it should just work. If not, please provide a sample file and I can take a look when j get back home.

For more options, visit https://groups.google.com/d/optout.

Kip Cole

unread,
Jul 29, 2016, 9:18:53 AM7/29/16
to elixir-l...@googlegroups.com
José, thanks, I’ll put a simple case together.  I have tried the unquote fragment approach first.  Like:

  Enum.each Cldr.known_locales, fn (locale) ->
    function_body = cardinal_rules[locale] |> rules_to_condition_statement(__MODULE__)
    defp do_cardinal(unquote(locale), n, i, v, w, f, t), do: unquote(function_body)
  end

But in that case the `unquote(body)` became an AST literal for the function body rather than the AST being merged into the function definition.


Reply all
Reply to author
Forward
0 new messages