Skip to content

Commit

Permalink
add @precondition, like @Assert but thows ArgumentError, e.g.
Browse files Browse the repository at this point in the history
    function split{T}(c::T, n::Int)
        @require n > 0
        return SplitIterator{T}(c, n)
    end

    split("xxx", 0)

    ERROR: ArgumentError: split(::ASCIIString, ::Int64) requires n > 0
  • Loading branch information
samoconnor committed Mar 25, 2016
1 parent 77936d0 commit 412584e
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 0 deletions.
22 changes: 22 additions & 0 deletions base/contracts.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# This file is a part of Julia. License is MIT: http://julialang.org/license


@noinline function precondition_error(msg)
io = IOBuffer()
StackTraces.show_spec_linfo(io, StackTraces.lookup(backtrace()[3]))
throw(ArgumentError("$(takebuf_string(io)) requires $msg"))
end


"""
@require precondition [message]
Throw `ArgumentError` if `precondition` is false.
"""
macro require(precondition, msgs...)
msg = isempty(msgs) ? string(precondition) : msgs[1]
:(if ! $(esc(precondition)) precondition_error($msg) end)
end
# FIXME
# Should this have a branch-prediction hint? (same for @assert?)
# http://llvm.org/docs/BranchWeightMetadata.html#built-in-expect-instructions
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,7 @@ export
@noinline,

@assert,
@require,
@enum,
@label,
@goto,
Expand Down
2 changes: 2 additions & 0 deletions base/sysimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ include("arraymath.jl")
include("simdloop.jl")
importall .SimdLoop

include("contracts.jl")

# map-reduce operators
include("reduce.jl")

Expand Down
6 changes: 6 additions & 0 deletions doc/stdlib/base.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1068,6 +1068,12 @@ Errors
Throw an ``AssertionError`` if ``cond`` is ``false``\ . Preferred syntax for writing assertions. Message ``text`` is optionally displayed upon assertion failure.

.. function:: @require precondition [message]

.. Docstring generated from Julia source
Throw ``ArgumentError`` if ``precondition`` is false.

.. function:: ArgumentError(msg)

.. Docstring generated from Julia source
Expand Down
25 changes: 25 additions & 0 deletions test/misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,31 @@ let deepthought(x, y) = 42
end
end

# test @require
let
f1(n) = begin @require n > 0; n end
f2(n) = begin @require n != 0 "non-zero n"; n end

@test f1(1) == 1
@test f2(1) == 1

try
f1(0)
error("unexpected")
catch ex
@test isa(ex, ArgumentError)
@test ismatch(r"f1(.*) requires n > 0", ex.msg)
end

try
f2(0)
error("unexpected")
catch ex
@test isa(ex, ArgumentError)
@test ismatch(r"f2(.*) requires non-zero n", ex.msg)
end
end

let # test the process title functions, issue #9957
oldtitle = Sys.get_process_title()
Sys.set_process_title("julia0x1")
Expand Down

0 comments on commit 412584e

Please sign in to comment.