Skip to content

Commit 61192b4

Browse files
committed
allow specifying interpreter with @interpret
1 parent 7b6ca0d commit 61192b4

File tree

2 files changed

+58
-25
lines changed

2 files changed

+58
-25
lines changed

src/construct.jl

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,9 @@ end
691691
# call expression for further processing.
692692
function extract_args(__module__, ex0)
693693
if isa(ex0, Expr)
694-
if any(a->(isexpr(a, :kw) || isexpr(a, :parameters)), ex0.args)
694+
if isexpr(ex0, :macrocall) # Make @edit @time 1+2 edit the macro by using the types of the *expressions*
695+
return error("Macros are not supported in @interpret")
696+
elseif any(@nospecialize(a)->(isexpr(a, :kw) || isexpr(a, :parameters)), ex0.args)
695697
arg1, args, kwargs = gensym("arg1"), gensym("args"), gensym("kwargs")
696698
return quote
697699
$arg1 = $(ex0.args[1])
@@ -707,9 +709,6 @@ function extract_args(__module__, ex0)
707709
mapany(x->isexpr(x,:parameters) ? QuoteNode(x) : x, ex0.args)...)
708710
end
709711
end
710-
if isexpr(ex0, :macrocall) # Make @edit @time 1+2 edit the macro by using the types of the *expressions*
711-
return error("Macros are not supported in @enter")
712-
end
713712
ex = Meta.lower(__module__, ex0)
714713
if !isa(ex, Expr)
715714
return error("expression is not a function call or symbol")
@@ -727,30 +726,13 @@ function extract_args(__module__, ex0)
727726
end
728727
end
729728
return error("expression is not a function call, "
730-
* "or is too complex for @enter to analyze; "
729+
* "or is too complex for @interpret to analyze; "
731730
* "break it down to simpler parts if possible")
732731
end
733732

734-
"""
735-
@interpret f(args; kwargs...)
736-
737-
Evaluate `f` on the specified arguments using the interpreter.
738-
739-
# Example
740-
741-
```jldoctest
742-
julia> a = [1, 7];
743-
744-
julia> sum(a)
745-
8
746-
747-
julia> @interpret sum(a)
748-
8
749-
```
750-
"""
751-
macro interpret(arg)
733+
function interpret(mod::Module, @nospecialize(ex0); interp=RecursiveInterpreter())
752734
args = try
753-
extract_args(__module__, arg)
735+
extract_args(mod, ex0)
754736
catch e
755737
return :(throw($e))
756738
end
@@ -762,11 +744,50 @@ macro interpret(arg)
762744
elseif shouldbreak(frame, 1)
763745
frame, BreakpointRef(frame.framecode, 1)
764746
else
765-
local ret = finish_and_return!(frame)
747+
local ret = finish_and_return!($interp, frame)
766748
# We deliberately return the top frame here; future debugging commands
767749
# via debug_command may alter the leaves, we want the top frame so we can
768750
# ultimately do `get_return`.
769751
isa(ret, BreakpointRef) ? (frame, ret) : ret
770752
end
771753
end
772754
end
755+
756+
function interpret(mod::Module, opt, xs...)
757+
if isexpr(opt, :(=))
758+
optname, optval = opt.args
759+
optname isa Symbol || error("Invalid @interpret call: $optname is not a symbol")
760+
if optname === :interp
761+
return interpret(mod, xs...; interp=esc(optval))
762+
else
763+
error("Invalid @interpret call: $optname is not a recognized option")
764+
end
765+
else
766+
error("Invalid @interpret call: $opt is not a keyword")
767+
end
768+
end
769+
770+
"""
771+
@interpret [interp] f(args; kwargs...)
772+
773+
Evaluate `f` on the specified arguments using the interpreter.
774+
775+
# Example
776+
777+
```jldoctest
778+
julia> a = [1, 7];
779+
780+
julia> sum(a)
781+
8
782+
783+
julia> @interpret sum(a)
784+
8
785+
```
786+
"""
787+
macro interpret(ex0)
788+
return interpret(__module__, ex0)
789+
end
790+
791+
macro interpret(xs...)
792+
return interpret(__module__, xs...)
793+
end

test/interpret.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,3 +961,15 @@ func_arrayref(a, i) = Core.arrayref(true, a, i)
961961
@static if isdefinedglobal(Base, :ScopedValues)
962962
@testset "interpret_scopedvalues.jl" include("interpret_scopedvalues.jl")
963963
end
964+
965+
@testset "changing interpreter for @interpret" begin
966+
@test sin(42) == @interpret sin(42)
967+
@test sin(42) == @interpret interp=RecursiveInterpreter() sin(42)
968+
@test sin(42) == @interpret interp=Compiled() sin(42)
969+
@test ((@allocated @interpret interp=RecursiveInterpreter() sin(42)) (@allocated @interpret interp=Compiled() sin(42)))
970+
let interp1 = RecursiveInterpreter(),
971+
interp2 = Compiled()
972+
@test sin(42) == @interpret interp=interp1 sin(42)
973+
@test sin(42) == @interpret interp=interp2 sin(42)
974+
end
975+
end

0 commit comments

Comments
 (0)