Skip to content

Specifying which expressions Expr presenters apply to #2

@Vtec234

Description

@Vtec234

In Lean, a delaborator (see the metaprogramming book) is a metaprogram which can take low-level kernel Expressions to Syntax, pretty-printing them as human-readable, structured syntax trees. In ProofWidgets, an Expr presenter (defined here) is a sort of generalized delaborator which outputs interactive HTML trees instead of ASTs. For example, an Expr of type RBTree can be presented as a 2D red-black tree diagram:

infoview-rbtree

Similarly to delaborators, when registering a presenter we need some way to specify which Expressions it applies to (e.g. just the constructors of type RBTree). The current design (which I am about to remove) is that each ExprPresenter comes with an isApplicable : Expr → MetaM Bool field. This is super expressive but inefficient -- every time we want to present something, we have to run isApplicable on all the known presenters.

In contrast, delaborators are registered with reference to a constant name, and are executed on any expression whose head is that constant:

@[delab app.foo]
def delabfoo2 : Delab := do
  `(2)

#check foo -- 2 : Nat → Nat

A better mechanism for registering presenters would be analogous -- we use @[expr_presenter app.foo]. This is reasonably efficient as we can store them in a name-indexed environment extension and achieve amortized constant-time lookup (assuming a bounded amount of presenters for any given constant name). However, our design constraints are not exactly the same: the assumption with delaborators is that the first one that applies to a given Expr is the canonical choice. With widgets, we can give the user a choice of which presenter to use in the UI, for example to choose LaTeX in one case and a diagram in another. So there will have to be something to account for that.

If we wanted a higher degree of control than just the head constant name, a different possible design would have every presenter register itself with some global data structure. For example, registerSelf : DiscrTree ExprPresenter → DiscrTree ExprPresenter which stores the presenter at all patterns that it cares about (e.g. foo and foo *). My intuition is that this overcomplicates things and the simple delaborator-like design is better.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestmetaprogrammingDesign of metaprogramming APIs

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions