Skip to content

Commit f12ac92

Browse files
authored
Fix @! macro for dot-updating operators (#37)
Let the macro `@!` recognize dot-updating operators such as `.+=`, `.*=`, etc. and use the BangBang method for the required broadcasting.
1 parent 1687c3e commit f12ac92

File tree

2 files changed

+37
-5
lines changed

2 files changed

+37
-5
lines changed

src/macro.jl

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,17 @@ macro !(expr)
3030
if Meta.isexpr(x, :call)
3131
isdotoperator(x.args[1]) && return x
3232
return Expr(:call, Expr(:call, _maybb, x.args[1]), x.args[2:end]...)
33-
elseif Meta.isexpr(x, :.=) && x.args[1] isa Symbol
33+
elseif isdotoperator(x.head) && isequalsoperator(x.head) && x.args[1] isa Symbol
3434
@assert length(x.args) == 2
3535
lhs, rhs = x.args
36-
return :($lhs = $materialize!!(
37-
$Base.@isdefined($lhs) ? $lhs : $(Undefined()),
38-
$air.($rhs),
39-
))
36+
op = unequalsoperator(undotoperator(x.head))
37+
if isnothing(op)
38+
return :($lhs = $materialize!!(
39+
$Base.@isdefined($lhs) ? $lhs : $(Undefined()),
40+
$rhs,
41+
))
42+
end
43+
return :($lhs = $(Extras.broadcast_inplace!!)($op, $lhs, $rhs))
4044
end
4145
return x
4246
end |> esc
@@ -47,13 +51,23 @@ foldexpr(f, ex::Expr) = f(Expr(ex.head, foldexpr.(f, ex.args)...))
4751

4852
isdotoperator(x::Symbol) = undotoperator(x) !== nothing
4953

54+
isequalsoperator(x::Symbol) = unequalsoperator(x) !== nothing
55+
5056
function undotoperator(x::Symbol)
5157
startswith(string(x), ".") || return nothing
5258
op = Symbol(string(x)[2:end])
5359
Base.isoperator(op) || return nothing
5460
return op
5561
end
5662

63+
function unequalsoperator(x::Symbol)
64+
endswith(string(x), "=") || return nothing
65+
op = Symbol(string(x)[1:end-1])
66+
Base.isoperator(op) || return nothing
67+
return op
68+
end
69+
70+
# Should not be required anymore. Keep for backwards compatibility?
5771
function air end
5872
struct Aired{T}
5973
value::T

test/test_macro.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ end
4343
let y = SVector(0, 0)
4444
@test (@! y .= 1) === SVector(1, 1)
4545
end
46+
47+
let x = [1, 2]
48+
y = SVector(0, 0)
49+
@test (@! y .+= x)::SizedVector{2, Int} == [1, 2]
50+
end
51+
52+
let y = SVector(0, 0)
53+
@test (@! y .+= 1) === SVector(1, 1)
54+
end
4655
end
4756

4857
@testset "@." begin
@@ -81,6 +90,15 @@ end
8190
let y = SVector(0, 0)
8291
@test (@! @. y = 1) === SVector(1, 1)
8392
end
93+
94+
let x = [1, 2]
95+
y = SVector(0, 0)
96+
@test (@! @. y += x)::SizedVector{2, Int} == [1, 2]
97+
end
98+
99+
let y = SVector(0, 0)
100+
@test (@! @. y += 1) === SVector(1, 1)
101+
end
84102
end
85103

86104
end # module

0 commit comments

Comments
 (0)