diff --git a/Project.toml b/Project.toml index 9ca25eb..e5b9a3e 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Match" uuid = "7eb4fadd-790c-5f42-8a69-bfa0b872bfbf" -version = "2.1.2" +version = "2.2.0" authors = ["Neal Gafter ", "Kevin Squire "] [deps] diff --git a/README.md b/README.md index 415dfb2..f7b0f75 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ for examples of this and other features. * `x && y` matches values which match both patterns `x` and `y` * `x, if condition end` matches only if `condition` is true (`condition` may use any variables that occur earlier in the pattern eg `(x, y, z where x + y > z)`) * `x where condition` An alternative form for `x, if condition end` +* `if condition end` A boolean computed pattern. `x && if condition end` is another way of writing `x where condition`. * Anything else is treated as a constant and tested for equality * Expressions can be interpolated in as constants via standard interpolation syntax `\$(x)`. Interpolations may use previously bound variables. diff --git a/src/binding.jl b/src/binding.jl index 2ada559..14a7e8f 100644 --- a/src/binding.jl +++ b/src/binding.jl @@ -410,6 +410,14 @@ function bind_pattern!( pattern0, assigned = bind_pattern!(location, subpattern, input, binder, assigned) pattern1 = shred_where_clause(guard, false, location, binder, assigned) pattern = BoundAndPattern(location, source, BoundPattern[pattern0, pattern1]) + + elseif is_expr(source, :if, 2) + # if expr end + if !is_empty_block(source.args[2]) + error("$(location.file):$(location.line): Unrecognized @match guard syntax: `$source`.") + end + guard = source.args[1] + pattern = shred_where_clause(guard, false, location, binder, assigned) elseif is_expr(source, :call) && source.args[1] == :(:) && length(source.args) in 3:4 # A range pattern. We depend on the Range API to make sense of it. diff --git a/test/matchtests.jl b/test/matchtests.jl index 566bb25..29563ed 100644 --- a/test/matchtests.jl +++ b/test/matchtests.jl @@ -1,4 +1,4 @@ -@testset "tests from Match.jl" begin +@testset "tests for Match.jl" begin @testset "Type matching" begin # Type matching @@ -410,4 +410,39 @@ end end +@testset "Test support for ML-style guards, which are patterns of the form `if expr end`" begin + t = true + f = false + @test @match 1 begin + if f end => false + if t end => true + end + # The original feature request was for ML-style guards of the form + # pattern && if condition end => result + # as an alternative to guards of the forms + # pattern, if condition end => result + # pattern where condition => result + @test @match 1 begin + 1 && if !t end => false + 1 && if !f end => true + end +end + +@testset "Test an error when ML-style guards are not used correctly" begin + let line = 0, file = Symbol(@__FILE__) + try + line = (@__LINE__) + 2 + @eval @match Foo(1, 2) begin + if t; nothing; end => true + end + @test false + catch ex + @test ex isa LoadError + e = ex.error + @test e isa ErrorException + @test startswith(e.msg, "$file:$line: Unrecognized @match guard syntax:") + end + end +end + end