diff --git a/src/BangBang.jl b/src/BangBang.jl index 9529a163..299f979d 100644 --- a/src/BangBang.jl +++ b/src/BangBang.jl @@ -4,6 +4,7 @@ module BangBang @doc read(joinpath(dirname(@__DIR__), "README.md"), String) BangBang export + @!, append!!, delete!!, empty!!, @@ -29,6 +30,7 @@ include("core.jl") include("base.jl") include("linearalgebra.jl") include("initials.jl") +include("macro.jl") function __init__() @require StaticArrays="90137ffa-7385-5640-81b9-e52037218182" begin diff --git a/src/core.jl b/src/core.jl index 1afc9e92..71fb9d9f 100644 --- a/src/core.jl +++ b/src/core.jl @@ -16,6 +16,16 @@ pure(::typeof(pushfirst!)) = NoBang.pushfirst pure(::typeof(_setproperty!)) = NoBang.setproperty pure(::typeof(mul!)) = NoBang.mul +_maybb(mutate) = something(_asbb(mutate), mutate) +_asbb(::Any) = nothing + +_asbb(::typeof(push!)) = push!! +_asbb(::typeof(append!)) = append!! +_asbb(::typeof(pushfirst!)) = pushfirst!! +_asbb(::typeof(mul!)) = mul!! +_asbb(::typeof(delete!)) = delete!! +_asbb(::typeof(empty!)) = empty!! + const MaybeMutableContainer = Union{ AbstractArray, AbstractDict, diff --git a/src/macro.jl b/src/macro.jl new file mode 100644 index 00000000..622d4543 --- /dev/null +++ b/src/macro.jl @@ -0,0 +1,24 @@ +""" + @! expr + +Convert all supported mutating calls to double bang equivalent. + +# Examples +```jldoctest +julia> using BangBang + +julia> @! push!(empty!((0, 1)), 2, 3) +(2, 3) +``` +""" +macro !(expr) + foldexpr(expr) do x + if Meta.isexpr(x, :call) + return Expr(:call, Expr(:call, _maybb, x.args[1]), x.args[2:end]...) + end + return x + end |> esc +end + +foldexpr(f, x) = x +foldexpr(f, ex::Expr) = f(Expr(ex.head, foldexpr.(f, ex.args)...)) diff --git a/test/test_macro.jl b/test/test_macro.jl new file mode 100644 index 00000000..829d37af --- /dev/null +++ b/test/test_macro.jl @@ -0,0 +1,10 @@ +module TestMacro + +include("preamble.jl") + +@testset begin + @test (@! push!(empty!([0, 1]), 2, 3)) == [2, 3] + @test (@! push!(empty!((0, 1)), 2, 3)) == (2, 3) +end + +end # module