The syntax tree is only the first half of the syntax story. The second half happens in lowering, and that’s where the magic occurs:
julia> Meta.@lower z=x.*y
:($(Expr(:thunk, CodeInfo(
1 ─ %1 = (Base.getproperty)(Base.Broadcast, :materialize) │
│ %2 = (Base.getproperty)(Base.Broadcast, :broadcasted) │
│ %3 = (%2)(*, x, y) │
│ %4 = (%1)(%3) │
│ z = %4 │
└── return %4 │
))))
This belies a good deal of complexity, but that’s the entrance to the rabbit hole.