Skip to content

Commit

Permalink
Handle .= in @!
Browse files Browse the repository at this point in the history
  • Loading branch information
tkf committed Aug 27, 2019
1 parent 6c73b66 commit 36f7080
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ possible(::typeof(_setproperty!), x, ::Any, ::Any) = ismutablestruct(x)
materialize!!(dest, x)
"""
materialize!!(dest, x) = may(materialize!, dest, x)
# TODO: maybe instantiate `x` and be aware of `x`'s style

pure(::typeof(materialize!)) = NoBang.materialize
possible(::typeof(materialize!), x, ::Any) = ismutable(x)
3 changes: 3 additions & 0 deletions src/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,6 @@ ismutablestruct(::Type{<:NamedTuple}) = false

# trymutate(::typeof(push!)) = push!!
# trymutate(::typeof(append!)) = append!!

struct Undefined end
ismutable(::Undefined) = false
8 changes: 8 additions & 0 deletions src/macro.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@ julia> @! push!(empty!((0, 1)), 2, 3)
macro !(expr)
foldexpr(expr) do x
if Meta.isexpr(x, :call)
# TODO: handle `x .* y`
return Expr(:call, Expr(:call, _maybb, x.args[1]), x.args[2:end]...)
elseif Meta.isexpr(x, :.=) && x.args[1] isa Symbol
@assert length(x.args) == 2
lhs, rhs = x.args
return :($lhs = $materialize!!(
$Base.@isdefined($lhs) ? $lhs : $(Undefined()),
$rhs,
))
end
return x
end |> esc
Expand Down
25 changes: 25 additions & 0 deletions test/test_macro.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,29 @@ include("preamble.jl")
@test (@! push!(empty!((0, 1)), 2, 3)) == (2, 3)
end

@testset ".=" begin
@test !@isdefined y
@test begin
x = SVector(1, 2)
@! y .= (*).(x, 2)
end === SVector(2, 4)

@test !@isdefined y
@test begin
x = SVector(1, 2)
y = SVector(0, 0)
@! y .= (*).(x, 2)
end === SVector(2, 4)

let x = [1, 2]
y = [0, 0]
@test (@! y .= (*).(x, 2))::Vector{Int} == [2, 4]
end

let x = [1, 2]
y = SVector(0, 0)
@test (@! y .= (*).(x, 2))::Vector{Int} == [2, 4]
end
end

end # module

0 comments on commit 36f7080

Please sign in to comment.