-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
C API for module creation #59604
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
Merged
Merged
C API for module creation #59604
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Provide a way to create new modules without resorting to passing an `Expr(:module, ...)` to `eval()` by splitting up `jl_eval_module_expr()` into three pieces: Two stateful module creation functions which are exported: * `jl_begin_new_module()` - Creates the module - Situates it within the module hierarchy (creating a binding within the parent module, setting the module parent and inheriting uuid, registering root modules) - Deals with global rooting during initialization and state for detecting whether the module is open for eval. - Creates standard imports and bindings for module-local eval and include * `jl_end_new_module()` cleans up some of this state and calls `__init__()` for the module and its children when necessary. The `Expr`-related machinery is left in the internal function `jl_eval_module_expr()`.
988acb9
to
388b0ef
Compare
Test failures look unrelated. |
c42f
added a commit
to c42f/JuliaLowering.jl
that referenced
this pull request
Sep 20, 2025
Julia's incrementally evaluated top level semantics make it rather tricky to design a lowering interface for top level and module level expressions. Currently these expressions are effectively *interpreted* by eval rather than ever being processed by lowering. However, I'd like a cleaner separation between "low level evaluation" and lowering, such that Core can contain only the low level eval "driver function". I'd like to propose the split as follows: * "Low level" evaluation is about executing a sequence of thunks represented as `CodeInfo`, and potentially about creating modules for those to be executed inside. * Lowering is about expression processing. In principle, the runtime's view of `eval()` shouldn't know about `Expr` or `SyntaxTree` (or whatever AST we use) - that should be left to the compiler frontend. A useful way to think about the duties of the frontend is to consider the question "What if we wanted to host another language on top of the Julia runtime?". If we can eventually achieve that without ever generating Julia `Expr` then we will have succeeded in separating the frontend. To implement all this I've recast lowering as an incremental iterative API in this change. Thus it's the job of `eval()` to simply evaluate thunks and create new modules as driven by lowering. (Perhaps we'd move this definition of `eval()` over to the Julia runtime before 1.13.) Depends on JuliaLang/julia#59604
vtjnash
approved these changes
Sep 24, 2025
We might also want to consider making these Builtin functions, so that they can be interpreted fully without requiring a ccall shim, but also not important right now |
xal-0
pushed a commit
to xal-0/julia
that referenced
this pull request
Sep 30, 2025
Provide a way to create new modules without resorting to passing an `Expr(:module, ...)` to `eval()` by splitting up `jl_eval_module_expr()` into three pieces: Two module creation functions which are exported: * `jl_begin_new_module()` - Creates the module - Situates it within the module hierarchy (creating a binding within the parent module, setting the module parent and inheriting uuid, registering root modules) - Deals with global rooting during initialization and state for detecting whether the module is open for eval. - Creates standard imports and bindings for module-local eval and include * `jl_end_new_module()` cleans up some of this state and calls `__init__()` for the module and its children when necessary. The `Expr`-related machinery is left in the internal function `jl_eval_module_expr()`. Something along these lines is required to avoid calling `eval(Expr(:module, ...))` in the JuliaLowering implementation of module evaluation where we try never to construct `Expr`. There's clearly further cleanup which could be done here. It would be nice to use less global state (`jl_current_modules` and `jl_module_init_order`) and to not to have the `Base.__toplevel__` hack. However I wanted to keep this PR small so I've resisted the temptation to change anything more for now. Similar to JuliaLang#57965 in the sense that it splits more functionality out of `eval()`.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Provide a way to create new modules without resorting to passing an
Expr(:module, ...)
toeval()
by splitting upjl_eval_module_expr()
into three pieces:Two module creation functions which are exported:
jl_begin_new_module()
jl_end_new_module()
cleans up some of this state and calls__init__()
for the module and its children when necessary.The
Expr
-related machinery is left in the internal functionjl_eval_module_expr()
.Something along these lines is required to avoid calling
eval(Expr(:module, ...))
in the JuliaLowering implementation of module evaluation where we try never to constructExpr
.There's clearly further cleanup which could be done here. It would be nice to use less global state (
jl_current_modules
andjl_module_init_order
) and to not to have theBase.__toplevel__
hack. However I wanted to keep this PR small so I've resisted the temptation to change anything more for now.Similar to #57965 in the sense that it splits more functionality out of
eval()
.