Lrpar codegen - #655
Conversation
This had to introduce a call to `parser_builder.from_ast.clone()` to work.
When building a parser from an ast rather than from a source string, we would clone the AST. Instead this patch takes it via a reference.
|
I forgot to mention that there is one aspect of I'm pretty sad to see this go, as it's saved me almost every time I've added a field which would affect the cache. |
| // change for reasons beyond lrpar's control. If it does change, that means that the lexer | ||
| // and lrpar would get out of sync, so we have to play it safe and regenerate in such | ||
| // cases. | ||
| let cache_str = code_gen.cache_string(&src_env, &build_env); |
There was a problem hiding this comment.
So there are a couple of places where we break the general abstraction, that
the code generator is just doing code generation, like here where we peek
at the cache string, to check if the existing code contains it.
| ) | ||
| .into()); | ||
| } | ||
| src_env.check_unused_header_keys()?; |
There was a problem hiding this comment.
Here is another place where we kind of break the abstraction by looking at the header for any unused keys, the other places src_env produces errors (when producing the build_env would be too early for this error, because of the inspect_rt callback above.
This is kind of undocumented API though, currently mostly used by the test_files key of the grmtools section. The callback needs to mark the test_files key as used.
|
One last thing, is that now that I have a blueprint for how this goes, perhaps I could figure out how to do an incremental transition, which could lead to a more reviewable patch (I do have some ideas how it would go). Edit: I feel like it's probably worth trying, and I'm kind of stuck inside until the smoke blows away, so I'll probably give this a shot. |
|
I have managed to get a good start at splitting this patch up, so I'm going to close this in favor of a future PR. |
Here is an attempt at pulling a codegen module out of
lrpar, it migrates theCTParserBuilderto use it, and passesthe testsuite. I haven't gone over this with a fine toothed comb, but there have been some obscure timing related problems I have introduced but noticed, but didn't cause any testsuite failures.
(Like calling
check_unused_header_keys()too early before the callback.I wasn't able to do this patch in a way that was even remotely incremental because of ownership issues. Nor really figure out a way to do it in a way that didn't require making slight changes to things as they moved over (mostly changing references to
self, removing callsunwrap()).There are 3 passes to this and a 4th structure
ParserBuildEnvArgs:ParserSrcEnvParserBuildEnvParserCodeGenThe general idea is:
ParserSrcEnv: source, source path, diagnostics generator,headercollection which contains the default values for the%grmtoolssection.ParserBuildEnvArgs, these are essentially the builder arguments including the essentialOption<>types. It's just a minimal builder.ParserBuildEnv: This structure contains fields derived from theBuildEnvArgsand also the inner types from options inBuildEnvArgs. By derived fields I mean things likeASTWithValidationInfoParserCodegen: This one contains aYaccGrammar,StateTable, andStateGraph. In order to generate code, though it still needs theSrcEnvand theBuildEnv.Currently the
BuildEnvtakes ownership of theBuildEnvArgs, it was easiest this way because therebuild_cachecode expectsOptionsit may be we should dropBuildEnvArgsfromBuildEnv.But generally the idea (in a pseudo functional syntax) is something to the effect of:
(SrcEnv?, BuildEnvArgs) -> BuildEnv? -> CodeGen::generate(&build_env, &src_env)?;There is a pretty high probability that this contains some code duplicated from
CTParserBuilder, whichdidn't go fully unused in
CTParserBuilder, given that the diff +/- is only a few hundred lines, I don't expect an enormous amount. But perhaps if it is really used in both places likefn indentappears to be we canuse ctbuilder::indentinstead.I'll try and read through it in this regard tomorrow.