diff --git a/README.md b/README.md index 5eb0583..872118d 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,12 @@ Matching ```julia using ExpressionPatterns.Matching -m1 = matcher(:(x+y)) +m1 = @matcher(x+y) m1(:(1+2)) == true m1(:(1-2)) == false -m2 = matcher(:(f(*{args}))) +m2 = @matcher(f(*{args})) m2(:(g(1,2))) == true m2(:(h())) == true @@ -137,4 +137,4 @@ See [Language.md](./docs/Language.md) for information on the pattern language. See [the examples](./examples/) or [the tests](./test/) for more uses. -Y'all should also check [MacroTools](https://github.com/MikeInnes/MacroTools.jl), which inspired me to remake and publicize this in the first place! +Y'all should also check [MacroTools](https://github.com/MikeInnes/MacroTools.jl), which inspired me to remake and publish this in the first place! diff --git a/src/Analyzer/Function.jl b/src/Analyzer/Function.jl index af4a781..3e29736 100644 --- a/src/Analyzer/Function.jl +++ b/src/Analyzer/Function.jl @@ -27,7 +27,7 @@ AnalysisState(state, mod::Module) = newstate(state.tree, state.literal, mo # analyze function: transform expressions into patterns #----------------------------------------------------------------------------------- -function analyze(ex, mod=current_module()) +function analyze(ex, mod) root = PatternRoot() consts = Set{Symbol}() analyze!(ex, newstate(root, false, mod, consts)) diff --git a/src/Destructuring/Applications.jl b/src/Destructuring/Applications.jl index ac7c4d0..7c05a0e 100644 --- a/src/Destructuring/Applications.jl +++ b/src/Destructuring/Applications.jl @@ -10,8 +10,8 @@ DA = Applications # Utilities #---------------------------------------------------------------------------- -function destructure_all(patterns, values, body) - destructure(:($(patterns...),), :(Expr(:tuple, $(values...))), body) +function destructure_all(patterns, mod, values, body) + destructure(:($(patterns...),), mod, :(Expr(:tuple, $(values...))), body) end #---------------------------------------------------------------------------- @@ -19,12 +19,12 @@ end #---------------------------------------------------------------------------- macro letds(lets...) - esc(letds(lets[1:end-1], lets[end])) + esc(letds(__module__, lets[1:end-1], lets[end])) end -function letds(lets, body) +function letds(mod, lets, body) patterns, values = unzip(map(x->x.args, lets)) - destructure_all(patterns, values, body) + destructure_all(patterns, mod, values, body) end #---------------------------------------------------------------------------- @@ -70,4 +70,4 @@ end #---------------------------------------------------------------------------- -end \ No newline at end of file +end diff --git a/src/Destructuring/Function.jl b/src/Destructuring/Function.jl index e9671ee..f5d1ee5 100644 --- a/src/Destructuring/Function.jl +++ b/src/Destructuring/Function.jl @@ -7,8 +7,8 @@ import ...Helper: clean_code import Base.Meta: quot export destructure -function destructure(pattern, ex, body) - ptree = analyze(pattern).child +function destructure(pattern, mod, ex, body) + ptree = analyze(pattern, mod).child @gensym vars quote $vars = $Variables() @@ -30,4 +30,4 @@ declare(vars, name) = :($name = $(vars)[$(quot(name))]) -end \ No newline at end of file +end diff --git a/src/Dispatch/Applications.jl b/src/Dispatch/Applications.jl index b0db3ea..ef06f9e 100644 --- a/src/Dispatch/Applications.jl +++ b/src/Dispatch/Applications.jl @@ -15,7 +15,7 @@ const DI = ExpressionPatterns.Dispatch.Applications const MACROMETHODS = TopMetaTable() @macrods macromet(name(*{patterns})[label], body) begin - esc(macromet(name, patterns, label, body, current_module())) + esc(macromet(name, patterns, label, body, __module__)) end function macromet(name, patterns, label, body, mod) @@ -25,14 +25,13 @@ function macromet(name, patterns, label, body, mod) code = quote - $newmethod!($macrotable, Expr(:tuple, $patterns...), $(quot(body)), $mod, $(quot(label))) + $newmethod!($macrotable, $patterns, $(quot(body)), $mod, $(quot(label))) end if undefined push!(code.args, :(macro $name(args...) - parameters = Expr(:tuple, args...) - $getmethod($macrotable, parameters)(parameters) + $callmethod($macrotable, args, __source__, __module__) end)) end return code @@ -43,21 +42,21 @@ end @macromet macromethod(name(*{patterns})[label], body)[with_label] begin - esc(macromet(name, patterns, label, body, current_module())) + esc(macromet(name, patterns, label, body, __module__)) end @macromet macromethod(name(*{patterns}), body)[no_label] begin - esc(macromet(name, patterns, unlabeled, body, current_module())) + esc(macromet(name, patterns, unlabeled, body, __module__)) end # assignment, to be used as @macromethod name(patterns...)[label] = expr @macromet macromethod(name(*{patterns})[label] = body)[eq_with_label] begin - esc(macromet(name, patterns, label, body, current_module())) + esc(macromet(name, patterns, label, body, __module__)) end @macromet macromethod(name(*{patterns}) = body)[eq_no_label] begin - esc(macromet(name, patterns, unlabeled, body, current_module())) + esc(macromet(name, patterns, unlabeled, body, __module__)) end # the [label] is optional in all definitions @@ -71,18 +70,18 @@ const METAFUNCTIONS = TopMetaTable() # normal @macromethod metafunction(name(*{patterns})[label], body)[with_label] = - esc(metafunction(name, patterns, label, body, current_module())) + esc(metafunction(name, patterns, label, body, __module__)) @macromethod metafunction(name(*{patterns}), body)[no_label] = - esc(metafunction(name, patterns, unlabeled, body, current_module())) + esc(metafunction(name, patterns, unlabeled, body, __module__)) # assignment @macromethod metafunction(name(*{patterns})[label] = body)[eq_with_label] = - esc(metafunction(name, patterns, label, body, current_module())) + esc(metafunction(name, patterns, label, body, __module__)) @macromethod metafunction(name(*{patterns}) = body)[eq_no_label] = - esc(metafunction(name, patterns, unlabeled, body, current_module())) + esc(metafunction(name, patterns, unlabeled, body, __module__)) function metafunction(name, patterns, label, body, mod) @@ -92,14 +91,13 @@ function metafunction(name, patterns, label, body, mod) code = quote - $newmethod!($metatable, Expr(:tuple, $patterns...), $(quot(body)), $mod, $(quot(label))) + $newmethod!($metatable, $patterns, $(quot(body)), $mod, $(quot(label))) end if undefined push!(code.args, - :(function $name(args...) - parameters = Expr(:tuple, args...) - $getmethod($metatable, parameters)(parameters) + :(function $name(args...; __module__=nothing, __source__=nothing) + $callmethod($metatable, args, __source__, __module__) end)) end return code diff --git a/src/Dispatch/MetaModule.jl b/src/Dispatch/MetaModule.jl index 2d97e66..c4732b8 100644 --- a/src/Dispatch/MetaModule.jl +++ b/src/Dispatch/MetaModule.jl @@ -12,9 +12,9 @@ const MF = Dispatch.Applications.METAFUNCTIONS # @metamodule #----------------------------------------------------------------------------------- -@macromethod metamodule(:R{:import, *{path}}) esc(importcode(path)) +@macromethod metamodule(:R{:import, *{path}}) esc(importcode(path, __module__)) @macromethod metamodule(:R{:importall, *{path}}) esc(importallcode(path)) -@macromethod metamodule(:R{:export, *{names}}) esc(exportcode(names)) +@macromethod metamodule(:R{:export, *{names}}) esc(exportcode(names, __module__)) @macromethod metamodule(:R{:toplevel}) nothing @macromethod metamodule(:R{:toplevel,x,*{xs}}) esc(quote @@ -26,22 +26,22 @@ end) # Code generation. #----------------------------------------------------------------------------------- -function importcode(path) +function importcode(path, mod) name = last(path) top = gettable(path[end]) quote import $(path...) import $(path[1:end-1]...).($(path[end-1])) - $(import_metatable!)($top, $(quot(name)), $(path[end-1])) + $(import_metatable!)($top, $(quot(name)), $(path[end-1]), $mod) end end -exportcode(names) = quote +exportcode(names, mod) = quote eval(:(export $($names...))) for name in $names top = $gettable(name) - $(export_metatable!)(top, name) + $(export_metatable!)(top, name, $mod) end end diff --git a/src/Dispatch/Reflection.jl b/src/Dispatch/Reflection.jl index e1c60d9..b1d03f4 100644 --- a/src/Dispatch/Reflection.jl +++ b/src/Dispatch/Reflection.jl @@ -23,28 +23,28 @@ gettable(typ, m) = preparg(x::Symbol) = quot(x) preparg(x::Vector) = :(Expr(:tuple, $x...)) -prefercode(m, arg1, arg2, typ, M=current_module()) = - :($(prefermethod!)($(gettable(typ, m))($M), $(preparg(arg1)), $(preparg(arg2)))) +prefercode(m, arg1, arg2, typ, M) = + :($(prefermethod!)($(gettable(typ, m))($M), $(preparg(arg1)), $(preparg(arg2)), $M)) -whichcode(m, patterns, typ, M=current_module()) = +whichcode(m, patterns, typ, M) = :($(whichmethod)($(gettable(typ, m))($M), Expr(:tuple, $(patterns)...))) -removecode(m, arg, typ, M=current_module()) = - :($(removemethod!)($(gettable(typ, m))($M), $(preparg(arg)))) +removecode(m, arg, typ, M) = + :($(removemethod!)($(gettable(typ, m))($M), $(preparg(arg)), $M)) -methodscode(m, typ, M=current_module()) = +methodscode(m, typ, M) = :($(gettable(typ, m))($M).methods) -conflictscode(m, typ, M=current_module()) = +conflictscode(m, typ, M) = :($(print_conflicts)(STDOUT, $(methodconflicts)($(gettable(typ, m))($M)))) #---------------------------------------------------------------------------- # which #---------------------------------------------------------------------------- -@macromethod whichmeta( m(*{patterns})) = whichcode(m, patterns, :fun) +@macromethod whichmeta( m(*{patterns})) = whichcode(m, patterns, :fun, __module__) @macromethod whichmeta( M.m(*{patterns})) = whichcode(m, patterns, :fun, M) -@macromethod whichmeta( @m(*{patterns})) = whichcode(m, patterns, :macro) +@macromethod whichmeta( @m(*{patterns})) = whichcode(m, patterns, :macro, __module__) @macromethod whichmeta(M.@m(*{patterns})) = whichcode(m, patterns, :macro, M) @@ -52,28 +52,28 @@ conflictscode(m, typ, M=current_module()) = # preference #---------------------------------------------------------------------------- -@macromethod prefer( m(*{p1}), :L{over}, m(*{p2})) = esc(prefercode(m, p1, p2, :fun)) +@macromethod prefer( m(*{p1}), :L{over}, m(*{p2})) = esc(prefercode(m, p1, p2, :fun, __module__)) @macromethod prefer( M.m(*{p1}), :L{over}, M.m(*{p2})) = esc(prefercode(m, p1, p2, :fun, M)) -@macromethod prefer( @m(*{p1}), :L{over}, @m(*{p2})) = esc(prefercode(m, p1, p2, :macro)) +@macromethod prefer( @m(*{p1}), :L{over}, @m(*{p2})) = esc(prefercode(m, p1, p2, :macro, __module__)) @macromethod prefer(M.@m(*{p1}), :L{over}, M.@m(*{p2})) = esc(prefercode(m, p1, p2, :macro, M)) -@macromethod prefer(label1, :L{over}, label2 in m) = esc(prefercode(m ,label1, label2, :fun)) +@macromethod prefer(label1, :L{over}, label2 in m) = esc(prefercode(m ,label1, label2, :fun, __module__)) @macromethod prefer(label1, :L{over}, label2 in M.m) = esc(prefercode(m ,label1, label2, :fun, M)) -@macromethod prefer(label1, :L{over}, label2 in @m) = esc(prefercode(m ,label1, label2, :macro)) +@macromethod prefer(label1, :L{over}, label2 in @m) = esc(prefercode(m ,label1, label2, :macro, __module__)) @macromethod prefer(label1, :L{over}, label2 in M.@m) = esc(prefercode(m ,label1, label2, :macro, M)) #---------------------------------------------------------------------------- # remove #---------------------------------------------------------------------------- -@macromethod remove( m(*{patterns})) = esc(removecode(m, patterns, :fun)) +@macromethod remove( m(*{patterns})) = esc(removecode(m, patterns, :fun, __module__)) @macromethod remove( M.m(*{patterns})) = esc(removecode(m, patterns, :fun, M)) -@macromethod remove( @m(*{patterns})) = esc(removecode(m, patterns, :macro)) +@macromethod remove( @m(*{patterns})) = esc(removecode(m, patterns, :macro, __module__)) @macromethod remove(M.@m(*{patterns})) = esc(removecode(m, patterns, :macro, M)) -@macromethod remove(label, :L{from}, m) = esc(removecode(m, label, :fun)) +@macromethod remove(label, :L{from}, m) = esc(removecode(m, label, :fun, __module__)) @macromethod remove(label, :L{from}, M.m) = esc(removecode(m, label, :fun, M)) -@macromethod remove(label, :L{from}, @m) = esc(removecode(m, label, :macro)) +@macromethod remove(label, :L{from}, @m) = esc(removecode(m, label, :macro, __module__)) @macromethod remove(label, :L{from}, M.@m) = esc(removecode(m, label, :macro, M)) @@ -81,9 +81,9 @@ conflictscode(m, typ, M=current_module()) = # metamethods #---------------------------------------------------------------------------- -@macromethod metamethods( m) = esc(methodscode(m, :fun)) +@macromethod metamethods( m) = esc(methodscode(m, :fun, __module__)) @macromethod metamethods( M.m) = esc(methodscode(m, :fun, M)) -@macromethod metamethods( @m) = esc(methodscode(m, :macro)) +@macromethod metamethods( @m) = esc(methodscode(m, :macro, __module__)) @macromethod metamethods(M.@m) = esc(methodscode(m, :macro, M)) @@ -91,9 +91,9 @@ conflictscode(m, typ, M=current_module()) = # metaconflicts #---------------------------------------------------------------------------- -@macromethod metaconflicts( m) = esc(conflictscode(m, :fun)) +@macromethod metaconflicts( m) = esc(conflictscode(m, :fun, __module__)) @macromethod metaconflicts( M.m) = esc(conflictscode(m, :fun, M)) -@macromethod metaconflicts( @m) = esc(conflictscode(m, :macro)) +@macromethod metaconflicts( @m) = esc(conflictscode(m, :macro, __module__)) @macromethod metaconflicts(M.@m) = esc(conflictscode(m, :macro, M)) diff --git a/src/Dispatch/TableManipulation.jl b/src/Dispatch/TableManipulation.jl index 4936583..dca5130 100644 --- a/src/Dispatch/TableManipulation.jl +++ b/src/Dispatch/TableManipulation.jl @@ -10,12 +10,30 @@ import ...Helper: clean_code import Base.Meta: quot export getmethod, newmethod!, removemethod!, prefermethod!, whichmethod, methodconflicts, - set_conflict_warnings + set_conflict_warnings, callmethod const Iterable = Union{Tuple, Vector, Set} WARN_CONFLICTS = :interactive +#---------------------------------------------------------------------------- +# Dispatch to and call method +#---------------------------------------------------------------------------- + +function callmethod(table, args, __source__, __module__) + m = getmethod(table, :($(args...),)) + m(__source__, __module__, args...) +end + +#---------------------------------------------------------------------------- +# Format patterns to be used as arguments +#---------------------------------------------------------------------------- + +function formatpatterns(patterns; for_matcher=false) + Expr(:tuple, (for_matcher ? [] : [:__source__, :__module__])..., patterns...) +end + + #---------------------------------------------------------------------------- # get methods from table #---------------------------------------------------------------------------- @@ -31,10 +49,13 @@ end # Insert methods in the table #---------------------------------------------------------------------------- -function newmethod!(table, pattern, body, mod, label=unlabeled) - match = matcher(pattern) - method = eval(mod, anonds(Expr(:tuple, pattern), body)) - tree = analyze(pattern) +function newmethod!(table, patterns, body, mod, label=unlabeled) + mpattern = formatpatterns(patterns, for_matcher=true) + fpattern = formatpatterns(patterns) + + match = matcher(mpattern, mod) + method = eval(mod, anonds(fpattern, body)) + tree = analyze(mpattern, mod) metamethod = MetaMethod(label, match, method, tree) addmethod!(table, metamethod) @@ -72,8 +93,8 @@ end # Remove methods from the table #---------------------------------------------------------------------------- -function removemethod!(table, pattern) - tree = analyze(pattern) +function removemethod!(table, pattern, mod) + tree = analyze(pattern, mod) methods = table.methods for i in eachindex(methods) @@ -86,7 +107,7 @@ function removemethod!(table, pattern) warn("Couldn't remove the method $(tree) from the $(table.name)") end -function removemethod!(table, label::Symbol) +function removemethod!(table, label::Symbol, mod) if haskey(table.labels, label) method = table.labels[label] methods = table.methods @@ -105,13 +126,13 @@ end # Manipulate preference of methods #---------------------------------------------------------------------------- -function prefermethod!(table, pattern1, pattern2) - tree1 = analyze(pattern1) - tree2 = analyze(pattern2) +function prefermethod!(table, pattern1, pattern2, mod) + tree1 = analyze(pattern1, mod) + tree2 = analyze(pattern2, mod) prefermethod_impl!(table, tree1, tree2) end -function prefermethod!(table, label1::Symbol, label2::Symbol) +function prefermethod!(table, label1::Symbol, label2::Symbol, mod) haskey(table.labels, label1) || notfounderror(table, "label $label1") haskey(table.labels, label2) || notfounderror(table, "label $label2") diff --git a/src/Dispatch/TopMetaTables.jl b/src/Dispatch/TopMetaTables.jl index bc311a7..853777a 100644 --- a/src/Dispatch/TopMetaTables.jl +++ b/src/Dispatch/TopMetaTables.jl @@ -48,7 +48,7 @@ function init_metatable!(toptable, mod, key, name) end end -function import_metatable!(toptable, tablekey, from, to=current_module()) +function import_metatable!(toptable, tablekey, from, to) init_module_table!(toptable, from) init_module_table!(toptable, to) !haskey(toptable[from], tablekey) && return warn("Unable to find metatable $(tablekey) in $(from).") @@ -57,7 +57,7 @@ function import_metatable!(toptable, tablekey, from, to=current_module()) toptable[to][tablekey] = toptable[from][tablekey] end -function export_metatable!(toptable, tablekey, from=current_module()) +function export_metatable!(toptable, tablekey, from) init_module_table!(toptable, from) push!(toptable[from].exports, tablekey) end diff --git a/src/Docs/Analyzer.jl b/src/Docs/Analyzer.jl index ced5a74..743c9f3 100644 --- a/src/Docs/Analyzer.jl +++ b/src/Docs/Analyzer.jl @@ -5,7 +5,7 @@ import ..Analyzer.Function: getstep, is_binding_name, is_special_expr, assertati AnalysisState, analyze, analyze!, analyze_args! """ -`analyze(ex[, module]) -> PatternRoot` +`analyze(ex, module) -> PatternRoot` Parses a julia code expression into a `PatternTree`, which can be used in matching, destructuring and dispatch. @@ -21,7 +21,6 @@ analyze(:(:T{MyType}), MyModule) ``` `MyType` will be looked for in `MyModule`. -If no module is specified, `current_module` is used. """ analyze; diff --git a/src/Docs/Dispatch.jl b/src/Docs/Dispatch.jl index 2bb0afe..20bf2c4 100644 --- a/src/Docs/Dispatch.jl +++ b/src/Docs/Dispatch.jl @@ -156,7 +156,7 @@ If no table is found, throw a `MetaTableNotFoundError`. get_metatable; """ -`import_metatable(toptable, key, from[, to=current_module()])` +`import_metatable(toptable, key, from, to)` Associates a metatable to a new module. @@ -260,4 +260,4 @@ Exports the metatable `name` from the current module M so that `@metamodule impo Import all exported metatables from `Module.Path`. """ -:@metamodule; \ No newline at end of file +:@metamodule; diff --git a/src/Docs/PatternStructure.jl b/src/Docs/PatternStructure.jl index 8b1bede..583fba7 100644 --- a/src/Docs/PatternStructure.jl +++ b/src/Docs/PatternStructure.jl @@ -57,7 +57,7 @@ test. example: ```julia - tree = analyze(:(x+y)).child + tree = analyze(:(x+y), @__MODULE__).child vars = Variables(constants(tree)) test = PredicateCheck(ex->all(iseven, ex.args[2:end])) gate = PatternGate(test) diff --git a/src/Matching/Function.jl b/src/Matching/Function.jl index 05152b8..ae8b91b 100644 --- a/src/Matching/Function.jl +++ b/src/Matching/Function.jl @@ -6,9 +6,20 @@ using ...PatternStructure.SlurpTypes using ...PatternStructure.Special using ...Matching.Environment using ...Helper -export matcher +export @matcher, matcher + +macro matcher(pattern) + matcher(pattern, __module__) +end + +module Dep end + +function matcher(pattern, mod=Dep) + if mod == Dep + warn("Single argument `matcher` is deprecated, use @matcher(pattern) or matcher(:(pattern), @__MODULE__) instead.") + mod = current_module() + end -function matcher(pattern, mod=current_module()) const pattern_tree = analyze(pattern, mod).child return match!(ex, variables=Variables()) = diff --git a/test/matching.jl b/test/matching.jl index 45cf40b..5434e7d 100644 --- a/test/matching.jl +++ b/test/matching.jl @@ -11,7 +11,7 @@ macro testmatch(pattern, block) arg_statements = (x->esc.(x.args[2:end])).(linesof(block)) res_statements = matchval.(arg_statements) - :(let match = $matcher($(esc(pattern))) + :(let match = $matcher($(esc(pattern)), @__MODULE__) $(res_statements...) end) end diff --git a/test/slurp-optimizations.jl b/test/slurp-optimizations.jl index b283849..030284a 100644 --- a/test/slurp-optimizations.jl +++ b/test/slurp-optimizations.jl @@ -4,44 +4,77 @@ using ExpressionPatterns.Analyzer using ExpressionPatterns.PatternStructure.SlurpTypes using Base.Test -# generic greedy - -@test isa(analyze(:(*{x+y,z},1+1,1,*{b})).child.children[1].head, GenericGreedySlurp) +macro test_slurp(body) + let pattern, index, typ, value, test + for (left, right) in (pair_vals(x) for x in body.args if is_pair_ex(x)) + left == :pattern ? (pattern = right) : + left == :index ? (index = right) : + left == :type ? (typ = right) : + left == :value ? (value = right) : + left == :test ? (test = right) : nothing + end + esc(quote + @test isa($analyze($(QuoteNode(pattern)), @__MODULE__).child.children[$index].head, $typ) + @letds $pattern = $value begin + @test $test + end + end) + end +end +is_pair_ex(x) = false +is_pair_ex(ex::Expr) = ex.head in [:(=>), :call] -@macrods t1(*{x+y,z},1+1,1,*{b}) (x,y,z) +pair_vals(ex) = (ex.args[ex.head == :(=>) ? 1 : 2].args[1], ex.args[end]) -@test @t1(10+2, a, 30+54, b, 53+1, c, 1+1, 1, 1+1, 1) == ([10,30,53,1], [2,54,1,1], [:a,:b,:c,1]) -# generic lazy +# generic greedy -@test isa(analyze(:(:?{x+y,z},1+1,1,*{b})).child.children[1].head, GenericLazySlurp) +@test_slurp begin + :pattern => (*{x+y,z},1+1,1,*{b}) + :index => 1 + :type => GenericGreedySlurp + :value => :(10+2, a, 30+54, b, 53+1, c, 1+1, 1, 1+1, 1) + :test => (x,y,z) == ([10, 30, 53, 1], [2, 54, 1, 1], [:a, :b, :c, 1]) +end -@macrods t2(:?{x+y,z},1+1,1,*{b}) (x,y,z) +# generic lazy -@test @t2(10+2, a, 30+54, b, 53+1, c, 1+1, 1, 1+1, 1) == ([10,30,53], [2,54,1], [:a,:b,:c]) +@test_slurp begin + :pattern => (:?{x+y,z},1+1,1,*{b}) + :index => 1 + :type => GenericLazySlurp + :value => :(10+2, a, 30+54, b, 53+1, c, 1+1, 1, 1+1, 1) + :test => (x,y,z) == ([10,30,53], [2,54,1], [:a,:b,:c]) +end # last, simple -@test isa(analyze(:(a,b,*{c},d,e)).child.children[3].head, SimpleLastSlurp) - -@macrods t3(a,b,*{c},d,e) c - -@test @t3(1,2,3,4,5,6,7) == [3,4,5] +@test_slurp begin + :pattern => (a,b,*{c},d,e) + :index => 3 + :type => SimpleLastSlurp + :value => :(1,2,3,4,5,6,7) + :test => c == [3,4,5] +end # simple, until, greedy -@test isa(analyze(:(*{a},3,*{b})).child.children[1].head, SimpleGreedySlurpUntil) - -@macrods t4(*{a},3,*{b}) a - -@test @t4(0,1,2,3,4,5,6) == [0,1,2] +@test_slurp begin + :pattern => (*{a},3,*{b}) + :index => 1 + :type => SimpleGreedySlurpUntil + :value => :(0,1,2,3,4,5,6) + :test => a == [0,1,2] +end # simple, until, lazy -@test isa(analyze(:(:?{a},3,*{b})).child.children[1].head, SimpleLazySlurpUntil) - -@macrods t5(:?{a},3,*{b}) a - -@test @t5(0,1,2,3,4,5,6) == [0,1,2] +@test_slurp begin + :pattern => (:?{a},3,*{b}) + :index => 1 + :type => SimpleLazySlurpUntil + :value => :(0,1,2,3,4,5,6) + :test => a == [0,1,2] +end end