Skip to content
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

feat: traversal functions for Expr and SubExpr #1208

Merged
merged 16 commits into from
Jun 18, 2022

Conversation

EdAyers
Copy link
Contributor

@EdAyers EdAyers commented Jun 9, 2022

I'm working on a 'contextual suggestion' API for the Lean infoview which lets the user click on subexpressions in the infoview and see suggested tactics for these. In order to create this I ended up with quite a few functions for working with SubExpr.Pos and traversing and lensing on expressions with these.

I am happy to break these up in to multiple PRs if the reviewers find that appropriate.
I am also happy to instead merge any/all of these features in mathlib instead.

List of features in this PR:

  • Helper functions for SubExpr.Pos: push pop isRoot etc.
  • Lean/Meta/ExprTraverse.lean contains a set of traversal functions for expressions. These generalise the visit functions used in transform (it is possible to replace the implementation of transform with these traversal functions and all the tests still pass)
  • Lean/Meta/ExprLens.lean is a set of methods for working on subexpressions of e : Expr indexed by p : SubExpr.Pos. The main functions are
    • viewSubexpr (visit : (fvars : Array Expr) → (subexpr: Expr) → M α) (p : Pos) (root : Expr) : M α which runs visit at the subexpression of root addressed by p. (with bound variables properly instantiated)
    • replaceSubexpr (replace : (subexpr : Expr) → M Expr) (p : Pos) (root : Expr) : M Expr replaces the expression at the given position using the replace function. Again making sure that the Meta context is correct.
  • Some docstrings have been improved.

Todo list

  • add some unit tests for replaceSubExpr
  • more documentation
  • code style

@EdAyers EdAyers force-pushed the expr-lens branch 2 times, most recently from f9cba8d to 79d0943 Compare June 10, 2022 00:06
@Kha
Copy link
Member

Kha commented Jun 10, 2022

I am happy to break these up in to multiple PRs if the reviewers find that appropriate. I am also happy to instead merge any/all of these features in mathlib instead.

@leodemoura and I briefly talked about this PR, we are fine with merging all this into core

EdAyers added 11 commits June 15, 2022 17:00
Instead of an abbreviation. It is easier to understand
Pos operations in terms of 'push' and 'pop' rather than
through arithmetic.
Lean.Meta.transform is created with a series of recursive
visit functions. However these visit functions are useful
on their own outside of transform for traversing expressions.

This commit moves the visit functions outside the main function.
EdAyers added 2 commits June 15, 2022 17:29
This found a bug in lensCoord which I fixed.
variable {α : Type} [Inhabited α]

/-- Fold over the position starting at the root and heading to the leaf-/
def foldl (f : α → Nat → α) : α → Pos → α :=
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

foldup? folddown? When you imagine an expression tree is the root at the top or the bottom?


/-- Similar to `traverseLambda` but with an additional pos argument to track position. -/
def traverseLambdaWithPos
(f : Pos → Expr → M Expr) (p : Pos) (e : Expr) : M Expr := visit #[] p e
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternative formulation: make

structure ExprTraverseContext with
  (pos : Pos)
  (fvars : Array Expr)

and then

traverseXXXWithPos (f : Expr → ReaderT ExprTraverseContext Expr) : Expr → ReaderT ExprTraverseContext Expr

Or perhaps instead include the variable instances [MonadReader ExprTraverseContext M] and [MonadReaderWith ExprTraverseContext M]?

@EdAyers EdAyers marked this pull request as ready for review June 15, 2022 22:51
@EdAyers
Copy link
Contributor Author

EdAyers commented Jun 16, 2022

@EdAyers EdAyers mentioned this pull request Jun 16, 2022
3 tasks
This is needed because JSON will otherwise lossily
convert big nats to floats.
@Kha
Copy link
Member

Kha commented Jun 16, 2022

Why is Linux fsanitize crashing? https://github.com/leanprover/lean4/runs/6909389488?check_suite_focus=true#step:15:2360

@leodemoura It looks like we're leaking base here

lean4/src/Init/Fix.lean

Lines 31 to 32 in 7a3ee51

@[extern c inline "lean_fixpoint2(#5, #6, #7)"]
def fixCore2 {α₁ α₂ β : Type u} (base : α₁ → α₂ → β) (rec : (α₁ → α₂ → β) → α₁ → α₂ → β) : α₁ → α₂ → β :=

@leodemoura
Copy link
Member

Why is Linux fsanitize crashing? https://github.com/leanprover/lean4/runs/6909389488?check_suite_focus=true#step:15:2360

@leodemoura It looks like we're leaking base here

lean4/src/Init/Fix.lean

Lines 31 to 32 in 7a3ee51

@[extern c inline "lean_fixpoint2(#5, #6, #7)"]
def fixCore2 {α₁ α₂ β : Type u} (base : α₁ → α₂ → β) (rec : (α₁ → α₂ → β) → α₁ → α₂ → β) : α₁ → α₂ → β :=

Please do not use these functions. I meant to remove them a long time ago. They have runtime support, and were added to solve performance problems in the old parser engine we had. The problem that motivated these primitives does not even exist anymore, and I don't see a strong motivation for having them as primitives in our runtime.

@leodemoura
Copy link
Member

@EdAyers Could you please rewrite the code and avoid the fix* primitives?

Thanks,
Leo

leodemoura added a commit that referenced this pull request Jun 16, 2022
@leodemoura leodemoura merged commit ee6ba18 into leanprover:master Jun 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants