Last active
May 1, 2019 10:39
-
-
Save inkydragon/0787b44eb41461c3e6c5898f6042a2dd to your computer and use it in GitHub Desktop.
patch for `MLStyle.jl`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# test driven development | |
# TestSet for `@when` + `@otherwise` | |
using MLStyle | |
using Test | |
using Random | |
#= | |
Test help macro/functions | |
=# | |
## PPAP | |
# I have a macro | |
# I have a @test_throws | |
# Eh~ | |
# LoadError! | |
# no more LoadError! Get the real error. | |
macro test_macro_throws(errortype, m) | |
:( | |
@test_throws $errortype try | |
@eval $m | |
catch err | |
while err isa LoadError | |
err = err.error | |
end | |
throw(err) | |
end | |
) | |
end | |
function genRandVal(; | |
hasInt::Bool=true, | |
hasBool::Bool=true, | |
hasFloat::Bool=true, | |
hasNumber::Bool=true, | |
hasString::Bool=true, | |
hasSymbol::Bool=true | |
) | |
if hasNumber; hasInt = hasFloat = true; end | |
rnd = [] | |
if hasInt; push!(rnd, rand(Int)); end | |
if hasBool; push!(rnd, bitrand()[1]); end | |
if hasFloat; push!(rnd, rand()); end | |
if hasString; push!(rnd, randstring()); end | |
if hasSymbol; push!(rnd, randstring('a':'z') |> Symbol); end | |
shuffle(rnd)[1] | |
end | |
macro rand_test_eq(f, times) | |
# TODO | |
end | |
#= | |
TestSet | |
=# | |
@testset "@when" begin | |
@testset "Only @when" begin | |
@test 2 == @when let (a, 1) = (2, 1) | |
a | |
end | |
# @match (2, 1) begin | |
# (a, 1) => a | |
# _ => nothing | |
# end | |
# for more test, see `test\when.jl` | |
end | |
@testset "@when in @when" begin | |
function f1(args) | |
x = Tuple(args) | |
@when (a, 1) = x begin | |
a | |
@when (b, 2) | |
(2, b) | |
end | |
# @match x begin | |
# (a, 1) => a | |
# (b, 2) => (2, b) | |
# _ => nothing | |
# end | |
end | |
# case: a | |
@test f1(111, 1) == 111 | |
@test f1(222, 1) == 222 | |
# case: (2, b) | |
@test f1(111, 2) == (2, 111) | |
@test f1(222, 2) == (2, 222) | |
function f2(args) | |
x = Tuple(args) | |
@when (a, 1) = x begin | |
a | |
@when (b, 2) | |
(:b, b) | |
@when (c, 3) | |
(:c, c) | |
end | |
# @match x begin | |
# (a, 1) => a | |
# (b, 2) => (:b, b) | |
# (c, 3) => (:c, c) | |
# _ => nothing | |
# end | |
end | |
@test f2(10, 1) == 10 # case: a | |
@test f2(20, 2) == (:b, 20) # case: (:b, b) | |
@test f2(30, 3) == (:c, 30) # case: (:c, c) | |
end | |
@testet "@when + @otherwise" begin | |
function f1(args) | |
x = Tuple(args) | |
@when (a, 1) = x begin | |
a | |
@otherwise | |
x | |
end | |
# @match x begin | |
# (a, 1) => a | |
# _ => x | |
# end | |
end | |
@test f1(1) == (1, ) # case: x | |
@test f1(1, 2) == (1, 2)# case: x | |
@test f1(2, 1) == 2 # case: a | |
function f2(args) | |
x = Tuple(args) | |
@when (a, 1) = x begin | |
a | |
@when (b, 2) | |
(:b, b) | |
@when (c, 3) | |
(:c, c) | |
@otherwise | |
x | |
end | |
# @match x begin | |
# (a, 1) => a | |
# (b, 2) => (:b, b) | |
# (c, 3) => (:c, c) | |
# _ => x | |
# end | |
end | |
@test f2(1) == (1, ) # case: x | |
@test f2(1, 2) == (1, 2) # case: x | |
@test f2(10, 1) == 10 # case: a | |
@test f2(20, 2) == (:b, 20) # case: (:b, b) | |
@test f2(30, 3) == (:c, 30) # case: (:c, c) | |
end | |
@testet "@when + @otherwise with many bidings" begin | |
function f1(xy, z) | |
@when let (a, 1) = xy, | |
5 = z | |
a | |
@otherwise | |
0 # default value | |
end | |
# @match xy begin | |
# (a, 1) => begin | |
# @match z begin | |
# 5 => a | |
# _ => 0 # Always return the default value | |
# end | |
# end | |
# _ => 0 # Always return the default value | |
# end | |
end | |
@test f1((123, 1), 5) => 123 # case: a | |
@test f1((123, 3), 5) => 0 # not match `(a, 1) = xy` | |
@test f1((123, 1), 1) => 0 # not match `5 = z` | |
#= | |
TODO: Need discuss!!!! | |
In fact I would like to throw a syntax_err for the following situations. | |
=# | |
function f11(xy, z) | |
@when let (a, 3) = xy, | |
5 = z | |
a | |
@when (a, 4) # ambiguous! | |
4 | |
@otherwise | |
0 | |
end | |
# @syntax_err "Syntax is ambiguous!" | |
end | |
function f2(xy, z) | |
@when let (a, 3) = xy, | |
5 = z | |
a | |
@when (a, 4) = xy | |
4 | |
@otherwise | |
0 | |
end | |
# @match xy begin | |
# (a, 1) => begin | |
# @match z begin | |
# 5 => a | |
# _ => | |
# @match xy begin | |
# (a, 4) => 4 | |
# _ => 0 | |
# end | |
# end | |
# end | |
# (a, 4) => 4 | |
# _ => 0 | |
# end | |
end | |
function f3(xy, z) | |
@when let (a, 3) = xy, | |
5 = z | |
a | |
@when 6 = z | |
6 | |
@otherwise | |
0 | |
end | |
# @match xy begin | |
# (a, 1) => | |
# @match z begin | |
# 5 => a | |
# 6 => 6 | |
# _ => | |
# @match z begin | |
# 6 => 6 | |
# _ => 0 | |
# end | |
# end | |
# _ => | |
# @match z begin | |
# 6 => 6 | |
# _ => 0 | |
# end | |
# end | |
end | |
function f23(xy, z) | |
@when let (a, 3) = xy, | |
5 = z | |
a | |
@when (a, 4) = xy | |
4 | |
@when 6 = z | |
4 | |
@otherwise | |
0 | |
end | |
# Too complex... | |
end | |
function f32(xy, z) | |
@when let (a, 3) = xy, | |
5 = z | |
a | |
@when 6 = z | |
4 | |
@when (a, 4) = xy | |
4 | |
@otherwise | |
0 | |
end | |
# Too complex... | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#= | |
Test case | |
=# | |
x = (5, 2) | |
y = (6, 1) | |
# simple `@when` | |
syntax01 = :(# @when | |
let (a, 2) = x | |
a | |
end) | |
# syntax02 = :(@when (a, 2) = x begin a; end) | |
function m0(syntax) | |
@match syntax begin | |
Expr(:let, bd, ret) => | |
@match bd begin | |
:($a = $b) => | |
@format [a, b, ret] quote | |
@match b begin | |
a => ret | |
_ => nothing | |
end | |
end | |
a => :(let $a; $ret end) | |
end | |
_ => error("[m0] nothing matched") | |
end | |
end | |
res01 = :( | |
@match x begin | |
(a, 2) => a | |
_ => nothing | |
end) | |
# `@when` + `let` | |
syntax11 = :(# @when | |
let (a, 2) = x, | |
(b, 1) = y | |
a, b | |
end) | |
function m1(syntax) | |
@match syntax begin | |
Expr(:let, Expr(:block, bds...), ret) => | |
foldr(bds, init=ret) do each, last | |
@match each begin | |
:($a = $b) => | |
@format [a, b, last] quote | |
@match b begin | |
a => last | |
_ => nothing | |
end | |
end | |
a => :(let $a; $last end) | |
end | |
end | |
_ => error("[m1] nothing matched") | |
end | |
end | |
res11 = :( | |
@match x begin | |
(a, 2) => begin | |
@match y begin | |
(b, 1) => (a, b) | |
_ => nothing | |
end | |
end | |
_ => nothing | |
end) | |
# `@when` in `@when` | |
syntax21 = :(# @when | |
let (a, 2) = x | |
a, a, a | |
@when (b, 1) = x | |
b | |
end) | |
syntax22 = :(# @when | |
let (a, 1) = x | |
a | |
@when (b, 2) = x | |
b | |
@when (c, 3) = x | |
c | |
end) | |
function m2(syntax) | |
@match syntax begin | |
Expr(:let, | |
bd, | |
Expr(:block, | |
::LineNumberNode, | |
ret1 || Expr(:block, ret1), | |
::LineNumberNode, | |
Expr(:macrocall, | |
name, | |
::LineNumberNode, | |
Expr(:(=), case2, val2) | |
), ::LineNumberNode, | |
ret2 || Expr(:block, ret2) | |
) | |
) => | |
# @show bd ret1 ret2 " " | |
@match bd begin | |
:($a = $b) => begin | |
@format [a, b, ret1, ret2, case2, val2] quote | |
@match b begin | |
a => ret1 | |
case2 => val2 | |
_ => nothing | |
end | |
end | |
end | |
a => :(let $a; $last end) | |
end | |
_ => error("[m3] nothing matched") | |
end | |
end | |
res21 = :( | |
@match x begin | |
(a, 2) => a | |
(b, 2) => b | |
_ => nothing | |
end) | |
res22 = :( | |
@match x begin | |
(a, 2) => a | |
(b, 2) => b | |
(c, 3) => c | |
_ => nothing | |
end) | |
# `@otherwise` | |
syntax31 = :(# @when | |
let (a, 2) = x | |
a | |
@otherwise | |
x | |
end) | |
function m3(syntax) | |
@match syntax begin | |
Expr(:let, | |
bd, | |
Expr(:block, | |
::LineNumberNode, | |
ret1 || Expr(:block, ret1), | |
::LineNumberNode, | |
Expr(:macrocall, name, ::LineNumberNode), ::LineNumberNode, | |
ret2 || Expr(:block, ret2) | |
) | |
) => | |
# @show bd ret1 ret2 " " | |
@match bd begin | |
:($a = $b) => begin | |
@format [a, b, ret1, ret2] quote | |
@match b begin | |
a => ret1 | |
_ => ret2 | |
end | |
end | |
end | |
a => :(let $a; $last end) | |
end | |
_ => error("[m3] nothing matched") | |
end | |
end | |
res31 = :( | |
@match x begin | |
(a, 2) => a | |
_ => x | |
end) | |
# `@when` + `@otherwise` | |
syntax41 = :(# @when | |
let (a, 2) = x | |
a | |
@when (b, 2) = x | |
b | |
@otherwise | |
x | |
end) | |
# TODO | |
res41 = :( | |
@match x begin | |
(a, 2) => a | |
(b, 2) => b | |
_ => x | |
end) | |
#= | |
match macro with specific name??? | |
=# | |
syntax50 = :(@when x begin end) | |
@when Expr(:macrocall, name, body...) = syntax50 begin @show name; end | |
@when Expr(:macrocall, Symbol("@when"), body...) = syntax50 begin @show name; end # error | |
@when :(@when para body) = syntax50 begin @show para body; end # ret nothing |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment