You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Refactor generated function implementation to provide bindings/method (JuliaLang#57230)
This PR refactors the generated function implementation in multiple
ways:
1. Rather than allocating a new LineNumber node to pass to the
generator, we just pass the original method from which this
LineNumberNode was constructed. This has been a bit of a longer-standing
annoyance of mine, since the generator needs to know properties of the
original method to properly interpret the return value from the
generator, but this information was only available on the C side.
2. Move the handling of `Expr` returns fully into Julia. Right not
things were a bit split with the julia code post-processing an `Expr`
return, but then handing it back to C for lowering. By moving it fully
into Julia, we can keep the C-side interface simpler by always getting a
`CodeInfo`.
With these refactorings done, amend the post-processing code to provide
binding edges for `Expr` returns. Ordinarily, bindings in lowered code
do not need edges, because we will scan the lowered code of the method
to find them. However, generated functions are different, because we do
not in general have the lowered code available. To still give them
binding edges, we simply scan through the post-lowered code and all of
the bindings we find into the edges array.
I will note that both of these will require minor adjustments to
`@generated` functions that use the CodeInfo interface (N.B.: this
interface is not considered stable and we've broken it in almost every
release so far). In particular, the following adjustments need to be
made:
1. Adjusting the `source` argument to the new `Method` ABI
2. If necessary, adding any edges that correspond to GlobalRefs used -
the code will treat the returned CodeInfo mostly opaquely and (unlike in
the `Expr` case) will not automatically compute these edges.
ci =ccall(:jl_expand, Any, (Any, Any), ex, defmod)
1661
+
if!isa(ci, CodeInfo)
1662
+
ifisa(ci, Expr) && ci.head ===:error
1663
+
error("syntax: $(ci.args[1])")
1664
+
end
1665
+
error("The function body AST defined by this @generated function is not pure. This likely means it contains a closure, a comprehension or a generator.")
1666
+
end
1667
+
ci.isva = isva
1668
+
code = ci.code
1669
+
bindings =IdSet{Core.Binding}()
1670
+
for i =1:length(code)
1671
+
stmt = code[i]
1672
+
ifisa(stmt, GlobalRef)
1673
+
push!(bindings, convert(Core.Binding, stmt))
1674
+
end
1675
+
end
1676
+
if!isempty(bindings)
1677
+
ci.edges = Core.svec(bindings...)
1678
+
end
1679
+
return ci
1680
+
end
1681
+
1682
+
# invoke and wrap the results of @generated expression
1683
+
function (g::Core.GeneratedFunctionStub)(world::UInt, source::Method, @nospecialize args...)
if (jl_is_expr(func) && ((jl_expr_t*)func)->head==jl_error_sym) {
716
-
ct->ptls->in_pure_callback=0;
717
-
jl_toplevel_eval(def->module, (jl_value_t*)func);
718
-
}
719
-
jl_error("The function body AST defined by this @generated function is not pure. This likely means it contains a closure, a comprehension or a generator.");
720
-
}
721
-
// TODO: This should ideally be in the lambda expression,
722
-
// but currently our isva determination is non-syntactic
723
-
func->isva=def->isva;
688
+
if (!jl_is_code_info(ex)) {
689
+
jl_error("As of Julia 1.12, generated functions must return `CodeInfo`. See `Base.generated_body_to_codeinfo`.");
0 commit comments