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.