diff --git a/src/ArgCheck.jl b/src/ArgCheck.jl index 7276554..ace6a97 100644 --- a/src/ArgCheck.jl +++ b/src/ArgCheck.jl @@ -17,17 +17,13 @@ function myfunction(k,n,A,B) end ``` """ -macro argcheck(code,args...) - argcheck(code, args...) -end - -function argcheck(ex, args...) +macro argcheck(ex, options...) if isexpr(ex, :comparison) - argcheck_comparison(ex, args...) + argcheck_comparison(ex, options...) elseif is_simple_call(ex) - argcheck_call(ex, args...) + argcheck_call(ex, options...) else - argcheck_fallback(ex, args...) + argcheck_fallback(ex, options...) end end @@ -41,16 +37,18 @@ function is_simple_call(ex) true end -function argcheck_fallback(ex, args...) +function argcheck_fallback(ex, options...) quote - if !$(esc(ex)) - err = ArgCheck.build_error($(QuoteNode(ex)), $(esc.(args)...)) + if $(esc(ex)) + nothing + else + err = ArgCheck.build_error($(QuoteNode(ex)), $(esc.(options)...)) throw(err) end end end -function argcheck_call(ex, args...) +function argcheck_call(ex, options...) variables = [gensym() for _ in 1:length(ex.args)] assignments = map(variables, ex.args) do vi, exi Expr(:(=), vi, esc(exi)) @@ -62,7 +60,7 @@ function argcheck_call(ex, args...) QuoteNode(ex), QuoteNode(ex.args), values, - esc.(args)... + esc.(options)... ) quote $(assignments...) @@ -74,7 +72,7 @@ function argcheck_call(ex, args...) end end -function argcheck_comparison(ex, args...) +function argcheck_comparison(ex, options...) exprs = ex.args[1:2:end] ops = ex.args[2:2:end] variables = [gensym() for _ in 1:length(exprs)] @@ -94,7 +92,7 @@ function argcheck_comparison(ex, args...) code = Expr(:call, op, lhs, rhs) err = Expr(:call, :(ArgCheck.build_error_comparison), QuoteNode(code), QuoteNode(lhs), QuoteNode(rhs), - vlhs, vrhs, esc.(args)...) + vlhs, vrhs, esc.(options)...) reti = quote $assignment if $condition @@ -108,9 +106,9 @@ function argcheck_comparison(ex, args...) Expr(:block, ret...) end -function build_error(code, T::Type{<:Exception}, args...) - ret = T(args...) - warn("`@argcheck condition $T $(join(args, ' ')...)` is deprecated. Use `@argcheck condition $ret` instead") +function build_error(code, T::Type{<:Exception}, options...) + ret = T(options...) + warn("`@argcheck condition $T $(join(options, ' ')...)` is deprecated. Use `@argcheck condition $ret` instead") ret end function build_error(code, msg::AbstractString) @@ -119,12 +117,12 @@ end build_error(code, T::Type{<:Exception}=ArgumentError) = T("$code must hold.") build_error(code, err::Exception) = err -build_error_comparison(code, lhs, rhs, vlhs, vrhs, args...) = build_error(code, args...) +build_error_comparison(code, lhs, rhs, vlhs, vrhs, options...) = build_error(code, options...) @noinline function build_error_comparison(code, lhs, rhs, vlhs, vrhs, T::Type{<:Exception}=ArgumentError) build_error_with_fancy_message(code, [lhs, rhs], [vlhs, vrhs], T) end -build_error_with_fancy_message(code, variables, values, args...) = build_error(code, args...) +build_error_with_fancy_message(code, variables, values, options...) = build_error(code, options...) @noinline function build_error_with_fancy_message(code, variables, values, T::Type{<:Exception}=ArgumentError) msg = fancy_error_message(code, variables, values) @@ -148,25 +146,4 @@ function fancy_error_message(code, exprs, values) unshift!(lines, firstline) join(lines, '\n') end - -function is_comparison_call(ex) - isexpr(ex, :call) && - length(ex.args) == 3 && - is_comparison_op(ex.args[1]) -end -is_comparison_op(op) = false -function is_comparison_op(op::Symbol) - precedence = 6 # does this catch all comparisons? - Base.operator_precedence(op) == precedence -end - -canonicalize(x) = x -function canonicalize(ex::Expr) - if is_comparison_call(ex) - op, lhs, rhs = ex.args - Expr(:comparison, lhs, op, rhs) - else - ex - end -end end diff --git a/test/runtests.jl b/test/runtests.jl index a4d1aae..58a55ed 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -20,22 +20,6 @@ macro catch_exception_object(code) end end -import ArgCheck: is_comparison_call, canonicalize -@testset "helper functions" begin - @test is_comparison_call(:(1==2)) - @test is_comparison_call(:(f(2x) + 1 ≈ f(x))) - @test is_comparison_call(:(<(2,3))) - @test is_comparison_call(:(1 ≦ 2)) - @test !is_comparison_call(:(f(1,1))) - - ex = :(x1 < x2) - @test canonicalize(ex) != ex - @test canonicalize(ex) == Expr(:comparison, :x1, :(<), :x2) - - ex = :(det(x) < y < z) - @test canonicalize(ex) == ex -end - @testset "Chained comparisons" begin #6 x=y=z = 1