Skip to content

Commit 0bcdba0

Browse files
aviateskclaude
andauthored
Fix quoted property access syntax (e.g., Core.:(!==)) (#89)
* Fix quoted property access syntax (e.g., `Core.:(!==)`) Handle `K"quote"` nodes in property access during macro expansion by unwrapping them before processing. This allows syntax like `Core.:(!==)` to lower correctly, matching the behavior of `Meta.lower`. Co-Authored-By: Claude <[email protected]>
1 parent ad7d2d4 commit 0bcdba0

File tree

3 files changed

+67
-1
lines changed

3 files changed

+67
-1
lines changed

src/macro_expansion.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,13 @@ function expand_forms_1(ctx::MacroExpansionContext, ex::SyntaxTree)
458458
elseif k == K"module" || k == K"toplevel" || k == K"inert"
459459
ex
460460
elseif k == K"." && numchildren(ex) == 2
461-
e2 = expand_forms_1(ctx, ex[2])
461+
# Handle quoted property access like `x.:(foo)` or `Core.:(!==)`
462+
# Unwrap the quote to get the identifier before expansion
463+
rhs = ex[2]
464+
if kind(rhs) == K"quote" && numchildren(rhs) == 1
465+
rhs = rhs[1]
466+
end
467+
e2 = expand_forms_1(ctx, rhs)
462468
if kind(e2) == K"Identifier" || kind(e2) == K"Placeholder"
463469
# FIXME: Do the K"Symbol" transformation in the parser??
464470
e2 = @ast ctx e2 e2=>K"Symbol"

test/quoting.jl

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,33 @@ end
9494
@test kind(ex[2]) == K"Identifier"
9595
@test ex[2].name_val == "a"
9696

97+
# Test quoted property access syntax like `Core.:(foo)` and `Core.:(!==)`
98+
@test JuliaLowering.include_string(test_mod, """
99+
x = (a=1, b=2)
100+
x.:(a)
101+
""") == 1
102+
@test JuliaLowering.include_string(test_mod, """
103+
Core.:(!==)
104+
""") === (!==)
105+
106+
# Test quoted operator function definitions (issue #20)
107+
@test JuliaLowering.include_string(test_mod, """
108+
begin
109+
struct Issue20
110+
x::Int
111+
end
112+
Base.:(==)(a::Issue20, b::Issue20) = a.x == b.x
113+
Issue20(1) == Issue20(1)
114+
end
115+
""") === true
116+
117+
@test JuliaLowering.include_string(test_mod, """
118+
begin
119+
Base.:(<)(a::Issue20, b::Issue20) = a.x < b.x
120+
Issue20(1) < Issue20(2)
121+
end
122+
""") === true
123+
97124
# interpolations at multiple depths
98125
ex = JuliaLowering.include_string(test_mod, raw"""
99126
let

test/quoting_ir.jl

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,36 @@ quote
4242
$$x + 1
4343
# └┘ ── `$` expression outside string or quote block
4444
end
45+
46+
########################################
47+
# Quoted property access with identifier
48+
Core.:(foo)
49+
#---------------------
50+
1 TestMod.Core
51+
2 (call top.getproperty %:foo)
52+
3 (return %₂)
53+
54+
########################################
55+
# Quoted property access with operator
56+
Core.:(!==)
57+
#---------------------
58+
1 TestMod.Core
59+
2 (call top.getproperty %₁ :!==)
60+
3 (return %₂)
61+
62+
########################################
63+
# Quoted operator function definition (issue #20)
64+
function Base.:(==)() end
65+
#---------------------
66+
1 TestMod.Base
67+
2 (call top.getproperty %:==)
68+
3 (call core.Typeof %₂)
69+
4 (call core.svec %₃)
70+
5 (call core.svec)
71+
6 SourceLocation::1:10
72+
7 (call core.svec %%%₆)
73+
8 --- method core.nothing %
74+
slots: [slot₁/#self#(!read)]
75+
1 (return core.nothing)
76+
9 latestworld
77+
10 (return core.nothing)

0 commit comments

Comments
 (0)