-
Notifications
You must be signed in to change notification settings - Fork 98
feat: typed syntax as the target of doc elaboration #692
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
base: docthunk
Are you sure you want to change the base?
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
|
Benchmark results for 052dcb4 against 41cc5c3 are in! @robsimmons No significant changes detected. |
| /-- | ||
| The result of elaborating an inline component of a document | ||
| -/ | ||
| public abbrev Inline := Term |
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.
Why are these Term, rather than a parallel structure to Target.Block? Has it just not yet been done, or is there an underlying reason?
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.
Just hasn't been done — was demonstrating a block-only incremental adoption.
| The result of elaborating a document block. Concretely denotes a {lean}`Doc.Block genre` for some | ||
| unspecified {name}`genre`. | ||
| -/ | ||
| public inductive Block where |
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 looks like it could be implemented without the repetition as:
inductive InlineExt where
| other (container : Term)
| stx (stx : Term)
inductive BlockExt where
| other (container : Term)
| stx (stx : Term)
abbrev Inline := Lean.Doc.Inline InlineExt
abbrev Block := Lean.Doc.Block InlineExt BlockExt
That would give the same expressive power, from what I can see, while allowing a lot more shared code.
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.
Or, alternately,
inductive InlineExt where
| other (container : Term)
| stx (stx : Term)
inductive BlockExt where
| other (container : Term)
| stx (stx : Term)
def Target : Genre where
Inline := InlineExt
Block := BlockExt
PartMetadata := Empty
TraverseContext := Empty
TraverseState := Empty
but I think that's a bit less straightforward.
|
|
||
| end | ||
|
|
||
| mutual |
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 whole mutual block strikes me as code that should be Quote instances. That wouldn't let the code use quotations, but this kind of thing isn't so hard to build directly. Is it because there were issues propagating the genre via unification?
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.
Oh wait, these are converting from Target.Block. The fact that I stumbled here is evidence that at least a comment would be useful!
| let exp ← blockExpandersFor kind | ||
| for e in exp do | ||
| try | ||
| let termStx ← withFreshMacroScope <| e stx | ||
| return termStx | ||
| return .stx termStx | ||
| catch | ||
| | ex@(.internal id) => | ||
| if id == unsupportedSyntaxExceptionId then continue | ||
| else throw ex | ||
| | ex => throw ex | ||
| let exp ← blockElabsFor kind |
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.
Having this in two stages says that all expanders take precedence over all elaborators. I think the current code follows the usual Lean practice, where more-recently-defined expanders take precedence. I say "I think" because this feature is used in only a few places so it's not fresh in my mind.
I think this is OK, but it should be a deliberate and documented decision rather than an artifact of the implementation. To make them use the same precedence rules, the expander/elab extension could be one extension that contains a sum type instead of two separate ones.
|
I think this is a nice direction to go in with a lot of potential to make it much easier to implement Verso extensions. Given that the Verso AST is "closed" (the concrete syntax is fixed), I think this same approach could be put earlier in the pipeline. Instead of passing |
This PR allows block elaboration to target a typed concrete representation of blocks instead of producing
Termobjects. It is directly modeled off of #453, which retargeted block elaboration fromTermtoExpr. Unlike in that PR, here the goal is not to reduce build times, it is to make document elaboration less metaprogramming-ful, and to move towards being able to serialize much of the structure of an elaborated document as JSON or something similar.The first critical change is in
Verso.Doc.Elab.Basic: theFinishedParttype, which is already a concrete representation of the result of elaborating a document, is renamed toElab.Part, and correspondingElab.BlockandElab.Inlinetypes are added to represent the concrete representations of the result of elaborating a block and of elaborating inline syntax. (Elab.Inlineis just an alias forTerm, since we're not retargeting term elaboration in this PR.)The second critical change is in
Verso.Doc.Elab.Monad, where a newblock_elabdecorator is added to parallel theblock_expanderdecorator, and inVerso.Doc.Elab.Block, where the new family of decorators are queried. This is a relatively isolated change: the interesting changes happen when elaborators are introduced that parallel thecode_block_expanderanddirective_expanderdecorators.