From 9481073b473cb78eab0fe088312c96880bb8d645 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 28 Nov 2017 19:18:34 -0500 Subject: [PATCH] Improve enter macro Check whether it's a simple function call before performing lowering (fixes #14), and give a better error message when you try to enter something that's not a function call (fixes #11). --- src/ASTInterpreter2.jl | 57 +++++++++++++++++++++++++++++++++--------- test/misc.jl | 6 +++++ test/runtests.jl | 3 ++- 3 files changed, 53 insertions(+), 13 deletions(-) create mode 100644 test/misc.jl diff --git a/src/ASTInterpreter2.jl b/src/ASTInterpreter2.jl index a87c5606c34434..5341c421779274 100644 --- a/src/ASTInterpreter2.jl +++ b/src/ASTInterpreter2.jl @@ -437,19 +437,52 @@ end lower(mod, arg) = VERSION < v"0.7-" ? expand(arg) : Meta.lower(mod, arg) +# This is a version of gen_call_with_extracted_types, except that is passes back the call expression +# for further processing. +function extract_args(__module__, ex0) + if isa(ex0, Expr) + kws = collect(filter(x->isexpr(x,:kw),ex0.args)) + if !isempty(kws) + return Expr(:tuple,:(Core.kwfunc($(ex0.args[1]))), + Expr(:call,Base.vector_any,mapreduce( + x->[QuoteNode(x.args[1]),x.args[2]],vcat,kws)...), + map(x->isexpr(x, :parameters) ? QuoteNode(x) : x, + filter(x->!isexpr(x, :kw),ex0.args))...) + else + return Expr(:tuple, + map(x->isexpr(x,:parameters) ? QuoteNode(x) : x, ex0.args)...) + end + end + if isa(ex0, Expr) && ex0.head == :macrocall # Make @edit @time 1+2 edit the macro by using the types of the *expressions* + return error("Macros are not supported in @enter") + end + ex = lower(__module__, ex0) + exret = Expr(:none) + if !isa(ex, Expr) + return error("expression is not a function call or symbol") + elseif ex.head == :call + return Expr(:tuple, + map(x->isexpr(x,:parameters) ? QuoteNode(x) : x, ex.args)...) + elseif ex.head == :body + a1 = ex.args[1] + if isa(a1, Expr) && a1.head == :call + a11 = a1.args[1] + if a11 == :setindex! + return Expr(:tuple, + map(x->isexpr(x,:parameters) ? QuoteNode(x) : x, arg.args)...) + end + end + end + return error("expression is not a function call, " + * "or is too complex for @enter to analyze; " + * "break it down to simpler parts if possible") +end + function _make_stack(mod, arg) - arg = lower(mod, arg) - @assert isa(arg, Expr) && arg.head == :call - kws = collect(filter(x->isexpr(x,:kw),arg.args)) - if !isempty(kws) - args = Expr(:tuple,:(Core.kwfunc($(args[1]))), - Expr(:call,Base.vector_any,mapreduce( - x->[QuoteNode(x.args[1]),x.args[2]],vcat,kws)...), - map(x->isexpr(x, :parameters) ? QuoteNode(x) : x, - filter(x->!isexpr(x, :kw),arg.args))...) - else - args = Expr(:tuple, - map(x->isexpr(x,:parameters) ? QuoteNode(x) : x, arg.args)...) + args = try + extract_args(mod, arg) + catch e + return :(throw($e)) end quote theargs = $(esc(args)) diff --git a/test/misc.jl b/test/misc.jl new file mode 100644 index 00000000000000..031e616963a470 --- /dev/null +++ b/test/misc.jl @@ -0,0 +1,6 @@ +# Issue #14 +stack = @make_stack map(x->2x, 1:10) +state = dummy_state(stack) +execute_command(state, state.stack[1], Val{:finish}(), "finish") +@test isempty(state.stack) +@test state.overall_result == 2 .* [1:10...] diff --git a/test/runtests.jl b/test/runtests.jl index 9f030204f3e2c4..286fa072ffc4eb 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,4 +4,5 @@ using Base.Test include("evaling.jl") include("stepping.jl") include("interpret.jl") -include("ui.jl") \ No newline at end of file +include("ui.jl") +include("misc.jl") \ No newline at end of file