-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Replaceable single entry point for parser #35243
Conversation
49626e7
to
524b3e5
Compare
beba008
to
8fee17d
Compare
Ok, after some more cleanup and chasing down of a few broken tests I think this is ready for a closer look @Keno. @vtjnash as you can see this has a single entry point for the parser in BTW it's certain that this isn't the end game for the frontend, but I've tried to get to a reasonable intermediate state and document where it's at. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems reasonably straightforward now—just some small changes.
src/frontend.c
Outdated
const char* filename, size_t filename_len, | ||
size_t offset, jl_value_t* options) | ||
{ | ||
return (*jl_current_parser)(text, text_len, filename, filename_len, offset, options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't invalid to do, but I worry it'll reintroduce #27894, but much worse (as that's part of the definition of what cfunction
means). Since we already have many APIs that call back into Julia without requiring a C shim (e.g. Base.require
, Core.Compiler.typeinf_ext
, Base.loaded_modules_array()
, etc.) and none that use this design, I think it's just better that we stick with what we know (using jl_apply
here, like jl_type_infer
for example) and is slightly more powerful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok then, let's do it that way, it's simpler anyway. We can worry about bootstrap later (if indeed it makes any difference to this).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems reasonably straightforward now—just some small changes.
result = nothing | ||
line_and_ex = Expr(:toplevel, loc, nothing) | ||
for ex in ast.args | ||
if ex isa LineNumberNode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so this removes our hacky globals
jl_lineno = 0;
jl_filename = jl_string_data(filename);
I guess that's a good thing, it's just the end of an era, like discarding of a well-worn shoe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha! Yes it's going in that direction, though it doesn't quite remove them: the internal machinery will still set them, and their use in extreme circumstances (jl_critical_error
) will still work the same as it currently does (and be exactly as unthreadsafe as it currently is).
f30dc33
to
e8567db
Compare
This has been updated to move almost the whole parser replacement interface into Juila, with a few tiny shims in One thing I find particularly satisfying is that the ownership of the text buffer can now be safely communicated through the interface. So if the parser wants to return an error message which references the text buffer, and that buffer is a Regarding the ability to freeze the parser in a certain world, I added a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems good to me thus far. Slightly unfortunate to be causing Base now to require the existence of Core.Compiler
, so perhaps we should put the bare minimum of those symbols into boot.jl
, but not a show-stopper towards merging this.
How about I move the entire content of compiler/parsing.jl into boot.jl? It's only four new symbols. |
Ok, I've addressed all suggested cleanups, and moved the |
a43b3ad
to
73f857a
Compare
Rebased to fix the mess of commits and clean up a few things. Notable cleanup:
I think this is in a good state now so I plan to merge it later today unless there's anything further. |
Looking good! |
Add Core._parse binding as the internal entry point for parsing of Julia code. This is called by both C and Julia code which wishes to parse Julia. For now, it points at the flisp parser by default. Refactor include() implementation to be done in Julia code, and parsing rearrangement: * Implement include() and include_string() in Julia. This also reunifies the versions of include() in MainInclude and Base which had started diverging. * Add internal Core.Compiler.fl_parse and set this as the default value of the Core._parse binding. * Use Core._parse from Meta * Add `Meta.parseall()` for top-level parsing. For now as an internal function, but this will likely be made public shortly. Refactoring in C runtime code: * Remove flisp code from jl_parse_eval_all. This makes the top level parse-lower-eval loop independent of flisp internals. * Remove jl_parse_eval_all from use as the include implementation (still used during bootstrap). This also allowed the removal of mapexpr handling from the C code. * Keep jl_load and jl_load_file_string from julia.h unchanged for compatibility with the existing C API. (No julia code `ccall`s these anymore) * Unify flisp parsing to always parse from string rather than directly from file.
This simplifies stack traces for include() which were made much more complex by moving jl_parse_eval_all to the Julia layer.
This is a refactoring to allow the flisp parser to be replaced at runtime with some other parser as I've started to do in JuliaLang/FancyDiagnostics.jl#4.
I've largely separated this into logically distinct commits so it may be worth looking at those in isolation while reviewing. (The main place where the separation isn't quite clean is in some fluctuation of the parsing function API.) To summarize the implementation:
jl_parse
interface which lives in a new file frontend.c. The idea of this new file is to eventually contain all frontend-related C code, some of which should move from ast.c over time.jl_parse
currently has a C ABI and the implementation can be swapped out withjl_set_parser
. I'm somewhat unsure about whether this is best compared to maintaining a global parser object in julia, but it seems potentially easier for solving future bootstrap issues.jl_fl_parse
which is compatible withjl_parse
. This and other flisp entry points still live inast.c
.include
into Julia, which allowed themapexpr
handling injl_load_rewrite_file_string
andjl_load_rewrite
to be removed and implemented in Julia instead, and also allowsjl_parse_eval_all
to be only used within bootstrap and for implementing the olderjl_load
andjl_load_file_string
C API (actually these could be changed to callBase.include
in future).include
, I've introduced two small internal functionsMeta.parseall
andMeta.parseatom
to accompanyMeta.parse
. I've used this naming as I think this is what @JeffBezanson preferred; these can be further elaborated in AddMeta.parsefile
andMeta.parseall
functions as a wrapper aroundBase.parse_input_line
#34715 and made public there._simplify_include_frames
in order to not show users all theinclude
implementation details which were previously hidden in the C codejl_parse_eval_all
. This only applies whenprocess_backtrace
is called to simplify the backtrace for printing.Future TODOs
Clearly this isn't the end-game for the parser API, but I think it moves in a useful direction and I'd like to get something merged here to avoid the work going stale.
A big unresolved issue is how the parser can communicate fine-grained location information to macro expansion, lowering, etc, and how that will be preserved through those passes. Macro expansion is particularly interesting as any naive approach will break user code! Eventually we want to preserve location info in a CSTParser-like data structure, but for now
jl_parse
returns a normalExpr
.I felt like
jl_parse
should accept rich options in principle (for example, to support communicating parser state when reparsing an arbitrary piece of text, and other such things). This is partly why it accepts ajl_value_t
for the options rather than an integer I had in the earlier patches here. It remains to be seen exactly what options we might need, however.Also I should say that bootstrap and the full removal of the flisp frontend is completely unexplored so far.
Original description:
This is the start of a replacement for #35149, for discussion. The goals are
Meta.parse
; cf discussion at AddMeta.parsefile
andMeta.parseall
functions as a wrapper aroundBase.parse_input_line
#34715)parse_eval_all
into loading.jlI may leave this PR as a WIP (while I make a mess learning how everything slots together) and pull smaller logical pieces out as separate PRs for detailed review.