Disclaimer:  Prior one still holds.  ^.^

On Tuesday, April 16, 2019 at 12:03:03 PM UTC-6, José Valim wrote:
>
> I have to disagree on some points:
>
> 1.  Traversing the AST is not as complex as it sounds. You literally need 
> four clauses (and the first two can be written as proxy to the third):
>
> def traverse({left, meta, right})
>
> def traverse({one, two})
> def traverse([_ | _] = list)
>
> def traverse(other)
>
>
Just simply traversing the ast to read it is not a case I often do by 
itself in macro's, rather I tend to do steps like this:

1. Traverse AST to gather information.
2. Traverse a case to modify and transform nodes based on prior collected 
information (this is where I have wrap primitives and lists in 
`:__block__`'s and unpack 2-tuples into the proper generic tuple form so I 
can store additional metadata on them).
3. Often step 2 has to be repeated a few times for a few other passes, 
generate code based on multi-level metadata, move AST nodes around, etc...
4. I don't both stripping my added metadata as the engine seems to ignore 
it, so now I finally just return it.

On Tuesday, April 16, 2019 at 12:03:03 PM UTC-6, José Valim wrote:

> 2. If we converted everything to 3 element tuples, the issue is not only 
> Macro.keywordify as there are also macros that match on atoms too (and on 
> strings too albeit less common). For instance, every Phoenix application 
> does it . So making everything a three-element tuple would hurt that.
>

Exactly, those macro's can match on the AST form of an atom or atoms 
themselves, a macro can even make such matches a simple thing such as added 
a 'guard' of the form like `AST.is_atom/1` that matches an atom or a 
supposed `{:atom, [], "a"}`.  Or if it always wants it in one form or the 
other then it can just transform it before working on it.

On Tuesday, April 16, 2019 at 12:03:03 PM UTC-6, José Valim wrote: 

> 3. Note that {:integer, [], 1} and {:atom, [], "foo"} would be their own 
> AST nodes too, as there are now new rules for what the 3 element actually 
> is. Sure, it is more consistent in terms of metadata, but you are not 
> really reducing the number of nodes. You could make them {:integer, meta, 
> [1]} and similar but that would mean introducing new special forms.
>

Yep yep, I never meant to imply it would reduce node count, quite likely it 
would even increase it if bindings were made their own as well (which would 
clarify things so much in some cases, right now don't know if a binding 
scope has to be an atom or if any term is allowed for example).  In general 
if it were regular as proposed then every single node is as-is, only nodes 
with the last element being a list need to be recursed into (so function 
calls, `:tuple`, `:list`, etc...), even the primitives could easily just be 
a singular `{:prim, [], 42}` node (it would be wonderful to contain the 
original string representation of it in the metadata/context as well, so we 
know if an integer was typed as `42` or as `4_2` or whatever, in addition 
to comments, line/column information, etc...).  In general if you wanted to 
fully traverse it then it would just reduce to:
```elixir
defmodule AST do
  def postwalk(ast, f)
  def postwalk({t, md, list} = ast, f) when is_list(list) do
    f.({t, md, Enum.map(list, &postwalk(&1, f))})
  end
  def postwalk(ast, f) do
    f.(ast)
  end
end
```

On Tuesday, April 16, 2019 at 12:03:03 PM UTC-6, José Valim wrote:

> I definitely agree that having a fixed place for metadata would improve 
> certain cases but the trade-offs are much more nuanced than implied. The 
> current AST was not optimized for reconstruction but for developer 
> ergonomics and I believe the proposed standardisation would make certain 
> features much more bureaucratic.
>

Even for developer ergonomics it is quite a pain to work with though in 
macro's because of these issues. 

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/6accdd08-a34c-4632-b74b-3f25e11551b4%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to