You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/src/reference.md
+28-14Lines changed: 28 additions & 14 deletions
Original file line number
Diff line number
Diff line change
@@ -43,7 +43,7 @@ the source text more closely.
43
43
* The right hand side of `x where {T}` retains the `K"braces"` node around the `T` to distinguish it from `x where T`.
44
44
* Ternary syntax is not immediately lowered to an `if` node: `a ? b : c` parses as `(? a b c)` rather than `Expr(:if, :a, :b, :c)` (#85)
45
45
*`global const` and `const global` are not normalized by the parser. This is done in `Expr` conversion (#130)
46
-
*The AST for `do` is flatter and not lowered to a lambda by the parser: `f(x) do y ; body end` is parsed as `(do (call f x) (tuple y) (block body))` (#98)
46
+
*[`do`syntax](#Do-blocks)is nested as the last child of the call which the `do` lambda will be passed to (#98, #322)
47
47
*`@.` is not lowered to `@__dot__` inside the parser (#146)
48
48
* Docstrings use the `K"doc"` kind, and are not lowered to `Core.@doc` until later (#217)
49
49
* Juxtaposition uses the `K"juxtapose"` kind rather than lowering immediately to `*` (#220)
@@ -77,7 +77,6 @@ class of tokenization errors and lets the parser deal with them.
77
77
* We use flags rather than child nodes to represent the difference between `struct` and `mutable struct`, `module` and `baremodule` (#220)
78
78
* Multiple iterations within the header of a `for`, as in `for a=as, b=bs body end` are represented with a `cartesian_iterator` head rather than a `block`, as these lists of iterators are neither semantically nor syntactically a sequence of statements. Unlike other uses of `block` (see also generators).
79
79
80
-
81
80
## More detail on tree differences
82
81
83
82
### Generators
@@ -195,23 +194,38 @@ The same goes for command strings which are always wrapped in `K"cmdstring"`
195
194
regardless of whether they have multiple pieces (due to triple-quoted
196
195
dedenting) or otherwise.
197
196
198
-
### No desugaring of the closure in do blocks
197
+
### Do blocks
199
198
200
-
The reference parser represents `do` syntax with a closure for the second
201
-
argument. That is,
199
+
`do` syntax is represented in the `Expr` AST with the `do` outside the call.
200
+
This makes some sense syntactically (do appears as "an operator" after the
201
+
function call).
202
202
203
-
```julia
204
-
f(x) do y
205
-
body
206
-
end
207
-
```
203
+
However semantically this nesting is awkward because the lambda represented by
204
+
the do block is passed to the call. This same problem occurs for the macro form
205
+
`@f(x) do \n body end` where the macro expander needs a special rule to expand
206
+
nestings of the form `Expr(:do, Expr(:macrocall ...), ...)`, rearranging the
207
+
expression which are passed to this macro call rather than passing the
208
+
expressions up the tree.
209
+
210
+
The implied closure is also lowered to a nested `Expr(:->)` expression, though
211
+
it this somewhat premature to do this during parsing.
212
+
213
+
To resolve these problems we parse
214
+
215
+
@f(x, y) do a, b\n body\n end
216
+
f(x, y) do a, b\n body\n end
208
217
209
-
becomes `(do (call f x) (-> (tuple y) (block body)))` in the reference parser.
218
+
by tacking the `do` onto the end of the call argument list:
210
219
211
-
However, the nested closure with `->` head is implied here rather than present
212
-
in the surface syntax, which suggests this is a premature desugaring step.
213
-
Instead we emit the flatter structure `(do (call f x) (tuple y) (block body))`.
220
+
(macrocall @f x y (do (tuple a b) body))
221
+
(call f x y (do (tuple a b) body))
214
222
223
+
This achieves the following desirable properties
224
+
1. Content of `do` is nested inside the call which improves the match between AST and semantics
225
+
2. Macro can be passed the syntax as-is rather than the macro expander rearranging syntax before passing it to the macro
226
+
3. In the future, a macro can detect when it's being passed do syntax rather than lambda syntax
227
+
4.`do` head is used uniformly for both call and macrocall
228
+
5. We preserve the source ordering properties we need for the green tree.
0 commit comments