Skip to content

Commit dbe3c99

Browse files
committed
fix macro expansion of property destructuring
This got a bit messier than I would have liked, since macro expansion can't simply rename the property without changing the meaning. This introduces an internal form `:renamed` which still encodes the original name.
1 parent c82aeb7 commit dbe3c99

File tree

3 files changed

+46
-13
lines changed

3 files changed

+46
-13
lines changed

src/julia-syntax.scm

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2236,6 +2236,19 @@
22362236
(gensy))
22372237
(else (make-ssavalue))))
22382238

2239+
(define (extract-dest-prop field lhs)
2240+
(cond ((symbol? field) (list field field))
2241+
((and (pair? field) (eq? (car field) '|::|))
2242+
(extract-prop (cadr field)))
2243+
((globalref? field)
2244+
(list field (caddr field)))
2245+
((outerref? field)
2246+
(list field (cadr field)))
2247+
((and (pair? field) (eq? (car field) 'renamed))
2248+
(cdr field))
2249+
(else
2250+
(error (string "invalid assignment location \"" (deparse `(tuple ,lhs)) "\"")))))
2251+
22392252
(define (expand-property-destruct lhs x)
22402253
(if (not (length= lhs 1))
22412254
(error (string "invalid assignment location \"" (deparse `(tuple ,lhs)) "\"")))
@@ -2246,12 +2259,8 @@
22462259
,@ini
22472260
,@(map
22482261
(lambda (field)
2249-
(let ((prop (cond ((symbol? field) field)
2250-
((and (pair? field) (eq? (car field) '|::|) (symbol? (cadr field)))
2251-
(cadr field))
2252-
(else
2253-
(error (string "invalid assignment location \"" (deparse `(tuple ,lhs)) "\""))))))
2254-
(expand-forms `(= ,field (call (top getproperty) ,xx (quote ,prop))))))
2262+
(let ((dest-prop (extract-dest-prop field lhs)))
2263+
(expand-forms `(= ,(car dest-prop) (call (top getproperty) ,xx (quote ,(cadr dest-prop)))))))
22552264
lhss)
22562265
(unnecessary ,xx))))
22572266

src/macroexpand.scm

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -385,11 +385,16 @@
385385
((parameters)
386386
(cons 'parameters
387387
(map (lambda (x)
388-
;; `x` by itself after ; means `x=x`
389-
(let ((x (if (and (not inarg) (symbol? x))
390-
`(kw ,x ,x)
391-
x)))
392-
(resolve-expansion-vars- x env m parent-scope #f)))
388+
(if (and inarg (try-arg-name x))
389+
(let ((resolved (resolve-expansion-vars- x env m parent-scope inarg)))
390+
(if (equal? resolved x)
391+
x
392+
`(renamed ,resolved ,(arg-name x))))
393+
;; `x` by itself after ; means `x=x`
394+
(let ((x (if (and (not inarg) (symbol? x))
395+
`(kw ,x ,x)
396+
x)))
397+
(resolve-expansion-vars- x env m parent-scope inarg))))
393398
(cdr e))))
394399

395400
((->)
@@ -401,9 +406,10 @@
401406
;; in (kw x 1) inside an arglist, the x isn't actually a kwarg
402407
`(,(car e) ,(resolve-in-function-lhs (cadr e) env m parent-scope inarg)
403408
,(resolve-expansion-vars-with-new-env (caddr e) env m parent-scope inarg))
404-
`(,(car e) ,@(map (lambda (x)
409+
`(,(car e) ,(resolve-expansion-vars-with-new-env (cadr e) env m parent-scope #t)
410+
,@(map (lambda (x)
405411
(resolve-expansion-vars-with-new-env x env m parent-scope inarg))
406-
(cdr e)))))
412+
(cddr e)))))
407413

408414
((kw)
409415
(cond

test/syntax.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3465,3 +3465,21 @@ end
34653465
@test @_macroexpand(global (; x::S, $(esc(:y))::$(esc(:T))) = a) ==
34663466
:(global (; x::$(GlobalRef(m, :S)), y::T) = $(GlobalRef(m, :a)))
34673467
end
3468+
3469+
macro prop_destruct_macroexpand1()
3470+
:((; foo_prop_destruct1) = (foo_prop_destruct1 = 7,))
3471+
end
3472+
macro prop_destruct_macroexpand2()
3473+
:(let (; foo_prop_destruct2) = (foo_prop_destruct2 = 8,)
3474+
foo_prop_destruct2
3475+
end)
3476+
end
3477+
3478+
@testset "macro expansion of property destructuring" begin
3479+
m = @__MODULE__
3480+
@test @prop_destruct_macroexpand1() == (foo_prop_destruct1 = 7,)
3481+
@test m.foo_prop_destruct1 == 7
3482+
3483+
@test @prop_destruct_macroexpand2() == 8
3484+
@test !isdefined(m, :foo_prop_destruct2)
3485+
end

0 commit comments

Comments
 (0)