Lately I’ve been digging into the elixir AST for learning purposes. There is a section in the elixir docs(Syntax reference — Elixir v1.16.0) that describes the ast and gives some examples of it.
It mentions that the ast is made of:
- atoms - such as
:foo- integers - such as
42- floats - such as
13.1- strings - such as
"hello"- lists - such as
[1, 2, 3]- tuples with two elements - such as
{"hello", :world}- tuples with three elements, representing calls or variables
Regarding the last point, it then says:
the first element is an atom (or another tuple), the second element is a list of two-element tuples with metadata (such as line numbers) and the third is a list of arguments.
What I didn’t find so far is what is meant by “or another tuple”. Moreover, when that element is a tuple there seem to be some cases where elixir gives them a special meaning.
For example, consider the “dot syntax”:
quote do
foo.bar(:baz)
end
{{:., [], [{:foo, [], Elixir}, :bar]}, [], [:baz]}
The first element there is the tuple {:., [], [{:foo, [], Elixir}, :bar]} that represents foo . :bar, so here the dot is a binary operator. If that is used as the first element in another three-tuple ast node, then it turns into foo.bar(), and any arguments will be put inside the parens, in this case foo.bar(:baz).
This does not happen with other operators. For example, this node:
{{:+, [], [{:foo, [], Elixir}, :bar]}, [], []}
Gets turned into foo + :bar(). So this tells me the dot expression is a special case. This in itself is not a surprise, but how many other special cases do exist?
By playing around I found another special case with the multi alias syntax. This expression:
Foo.{Bar, Baz}
is represented by this ast:
{{:., [],
[
{:__aliases__, [], [:Foo]},
:{}
]}, [],
[
{:__aliases__, [], [:Bar]},
{:__aliases__, [], [:Baz]}
]}
The first element is again the dot operator tuple:
{:., [], [{:__aliases__, [], [:Foo]}, :{}]}
which in this case means Foo . :{}. The difference is that now if that tuple is used as the first element in another three-element tuple node, the arguments are put inside of the curly braces:
Foo.{Bar, Baz}
No matter how bizarre the arguments are:
{{:., [], [ {:__aliases__, [], [:Foo]}, :{} ]}, [], [ {:__aliases__, [], [:Bar]}, :baz, {:+, [], [1, 2]} ]}
#=> Foo.{Baz, :baz, 1 + 2}
So again, the dot operator when the right hand side is the :{} atom has special meaning.
I’m finding all of this by playing around, since the elixir docs don’t cover these cases.
The question is: is there a reference of the Elixir AST, or some section/comments/issue that documents all the cases where ast nodes are given special meaning?





















