Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow nested variable interpolation #381

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 5 additions & 11 deletions src/julia/pyjulia_helper.jl
Expand Up @@ -36,7 +36,7 @@ macro prepare_for_pyjulia_call(ex)

# f(x, quote_depth) should return a transformed expression x and whether to
# recurse into the new expression. quote_depth keeps track of how deep
# inside of nested quote objects we arepyeval
# inside of nested quote objects we are
function stoppable_walk(f, x, quote_depth=1)
(fx, recurse) = f(x, quote_depth)
if isexpr(fx,:quote)
Expand All @@ -48,18 +48,11 @@ macro prepare_for_pyjulia_call(ex)
walk(fx, (recurse ? (x -> stoppable_walk(f,x,quote_depth)) : identity), identity)
end

function make_pyeval(globals, locals, expr::Union{String,Symbol}, options...)
code = string(expr)
T = length(options) == 1 && 'o' in options[1] ? PyObject : PyAny
input_type = '\n' in code ? Py_file_input : Py_eval_input
:($convert($T, $pyeval_($code, $globals, $locals, $input_type)))
end

function insert_pyevals(globals, locals, ex)
stoppable_walk(ex) do x, quote_depth
if quote_depth==1 && isexpr(x, :$)
if x.args[1] isa Symbol
make_pyeval(globals, locals, x.args[1]), false
:(PyCall.@_py_str($globals, $locals, "", $(string(x.args[1])))), false
else
error("""syntax error in: \$($(string(x.args[1])))
Use py"..." instead of \$(...) for interpolating Python expressions.""")
Expand All @@ -68,7 +61,8 @@ macro prepare_for_pyjulia_call(ex)
if x.args[1]==Symbol("@py_str")
# in Julia 0.7+, x.args[2] is a LineNumberNode, so filter it out
# in a way that's compatible with Julia 0.6:
make_pyeval(globals, locals, filter(s->(s isa String), x.args[2:end])...), false
code_and_options = filter(s->(s isa String), x.args[2:end])
:(PyCall.@_py_str($globals, $locals, "", $(code_and_options...))), false
else
x, false
end
Expand All @@ -81,7 +75,7 @@ macro prepare_for_pyjulia_call(ex)
esc(quote
$pyfunction(
(globals, locals)->Base.eval(Main, $insert_pyevals(globals, locals, $(QuoteNode(ex)))),
$PyObject, $PyObject
$PyDict, $PyDict
)
end)
end
Expand Down