Skip to content

Conversation

@c42f
Copy link
Member

@c42f c42f commented Nov 20, 2022

Dotted call syntax parses into various forms which aren't really consistent. Especially, Expr is inconsistent about dotted infix calls vs dotted prefix calls. In this change we adopt a more consistent (and hopefully less mysterious!) parsing where dotted calls get their own dotcall head which is otherwise like the call head:

f.(a, b)  ==>  (dotcall f a b)
a .+ b    ==>  (dotcall-i a + b)
.+ b      ==>  (dotcall-pre + b)

In other cases where a dotted operator appears as an atom we split the dot from an operator, so .+ becomes (. +). Thus, for comparison chains and prefix calls, we have the following parsings:

a .< b < c  ==>  (comparison a (. <) b < c)
.*(a,b)     ==>  (call (. *) a b)

TODO: Unambiguously reconstructing the associated Expr in the latter cases is more challenging than expected and still requires some work.

Fix #90
Also incidentally fix #38

@c42f c42f force-pushed the c42f/dotcall-head branch from a25ed7d to 58392aa Compare November 21, 2022 09:55
@c42f
Copy link
Member Author

c42f commented Nov 21, 2022

To quote the latest rebased commit message, I've punted on some non-dotcall related dotted operator splitting for now:

"There's other cases where it would also be consistent to split the dot
from the operator, but these are more challenging to convert back to a
compatible Expr so I've punted on these for now. For example, we'd like

.*(a,b)     ==>  (call (. *) a b)
.+(a,)      ==>  (call (. +) a)

but these are not yet implemented as we need to be able to distinguish
them from the likes of (.+)(a,) which the reference parser treats
differently from .+(a,)"

Dotted call syntax parses into various forms which aren't really
consistent. Especially, Expr is inconsistent about dotted infix calls vs
dotted prefix calls. In this change we adopt a more consistent (and
hopefully less mysterious!) parsing where dotted calls get their own
`dotcall` head which is otherwise like the `call` head:

    f.(a, b)  ==>  (dotcall f a b)
    a .+ b    ==>  (dotcall-i a + b)
    .+ b      ==>  (dotcall-pre + b)
    .+(b)     ==>  (dotcall-pre + b)

Also, in comparison chains where a dotted operator appears as an atom we
split the dot from an operator, so `.+` becomes `(. +)`:

    a .< b < c  ==>  (comparison a (. <) b < c)

There's other cases where it would also be consistent to split the dot
from the operator, but these are more challenging to convert back to a
compatible Expr so I've punted on these for now. For example, we'd like

    .*(a,b)     ==>  (call (. *) a b)
    .+(a,)      ==>  (call (. +) a)

but these are not yet implemented as we need to be able to distinguish
them from the likes of `(.+)(a,)` which the reference parser treats
differently from `.+(a,)`
@c42f c42f force-pushed the c42f/dotcall-head branch from 58392aa to 942c984 Compare November 22, 2022 02:03
@c42f c42f merged commit 70977a6 into main Nov 22, 2022
@c42f c42f deleted the c42f/dotcall-head branch November 22, 2022 02:17
c42f added a commit to JuliaLang/julia that referenced this pull request Oct 17, 2025
Dotted call syntax parses into various forms which aren't really
consistent. Especially, Expr is inconsistent about dotted infix calls vs
dotted prefix calls. In this change we adopt a more consistent (and
hopefully less mysterious!) parsing where dotted calls get their own
`dotcall` head which is otherwise like the `call` head:

    f.(a, b)  ==>  (dotcall f a b)
    a .+ b    ==>  (dotcall-i a + b)
    .+ b      ==>  (dotcall-pre + b)
    .+(b)     ==>  (dotcall-pre + b)

Also, in comparison chains where a dotted operator appears as an atom we
split the dot from an operator, so `.+` becomes `(. +)`:

    a .< b < c  ==>  (comparison a (. <) b < c)

There's other cases where it would also be consistent to split the dot
from the operator, but these are more challenging to convert back to a
compatible Expr so I've punted on these for now. For example, we'd like

    .*(a,b)     ==>  (call (. *) a b)
    .+(a,)      ==>  (call (. +) a)

but these are not yet implemented as we need to be able to distinguish
them from the likes of `(.+)(a,)` which the reference parser treats
differently from `.+(a,)`
topolarity pushed a commit to JuliaLang/julia that referenced this pull request Nov 14, 2025
Dotted call syntax parses into various forms which aren't really
consistent. Especially, Expr is inconsistent about dotted infix calls vs
dotted prefix calls. In this change we adopt a more consistent (and
hopefully less mysterious!) parsing where dotted calls get their own
`dotcall` head which is otherwise like the `call` head:

    f.(a, b)  ==>  (dotcall f a b)
    a .+ b    ==>  (dotcall-i a + b)
    .+ b      ==>  (dotcall-pre + b)
    .+(b)     ==>  (dotcall-pre + b)

Also, in comparison chains where a dotted operator appears as an atom we
split the dot from an operator, so `.+` becomes `(. +)`:

    a .< b < c  ==>  (comparison a (. <) b < c)

There's other cases where it would also be consistent to split the dot
from the operator, but these are more challenging to convert back to a
compatible Expr so I've punted on these for now. For example, we'd like

    .*(a,b)     ==>  (call (. *) a b)
    .+(a,)      ==>  (call (. +) a)

but these are not yet implemented as we need to be able to distinguish
them from the likes of `(.+)(a,)` which the reference parser treats
differently from `.+(a,)`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rework handling of . tokenization and dotted operator calls .<: and .>: should not be parsed as unary operators

1 participant