Commit graph

539 commits

Author SHA1 Message Date
Kim Morrison
1ce7047bf5
feat: cleanup of get and back functions on List/Array (#7059)
This PR moves away from using `List.get` / `List.get?` / `List.get!` and
`Array.get!`, in favour of using the `GetElem` mediated getters. In
particular it deprecates `List.get?`, `List.get!` and `Array.get?`. Also
adds `Array.back`, taking a proof, matching `List.getLast`.
2025-02-17 01:43:45 +00:00
Kyle Miller
1babe9fc67
feat: make binders in #check be hoverable (#7074)
This PR modifies the signature pretty printer to add hover information
for parameters in binders. This makes the binders be consistent with the
hovers in pi types.

Suggested by @david-christiansen
2025-02-14 17:28:54 +00:00
Kyle Miller
1f6abcaf6c
feat: make all app unexpanders respond to pp.tagAppFns (#6730)
This PR changes how app unexpanders are invoked. Before the ref was
`.missing`, but now the ref is the head constant's delaborated syntax.
This way, when `pp.tagAppFns` is true, then tokens in app unexpanders
are annotated with the head constant. The consequence is that in docgen,
tokens will be linkified. This new behavior is consistent with how
`notation` defines app unexpanders.

In a followup PR we can slightly simplify the `notation` unexpander
macro to not set the ref.
2025-02-02 23:29:12 +00:00
Kyle Miller
89d897a34d
feat: make coeFun delaborator respect pp.tagAppFns (#6729)
This PR makes the pretty printer for `.coeFun`-tagged functions respect
`pp.tagAppFns`. The effect is that in docgen, when an expression pretty
prints as `f x y z` with `f` a coerced function, then if `f` is a
constant it will be linkified.
2025-02-02 22:54:23 +00:00
Kyle Miller
3fb264b569
feat: modify delaborator to tag generalized field notation (#6703)
This PR modifies the delaborator so that in `pp.tagAppFns` mode,
generalized field notation is tagged with the head constant. The effect
is that docgen documentation will linkify dot notation. Internal change:
now formatted `rawIdent` can be tagged.
2025-02-02 21:34:49 +00:00
Kim Morrison
5b1c6b558a
feat: align take/drop/extract across List/Array/Vector (#6860)
This PR makes `take`/`drop`/`extract` available for each of
`List`/`Array`/`Vector`. The simp normal forms differ, however: in
`List`, we simplify `extract` to `take+drop`, while in `Array` and
`Vector` we simplify `take` and `drop` to `extract`. We also provide
`Array/Vector.shrink`, which simplifies to `take`, but is implemented by
repeatedly popping. Verification lemmas for `Array/Vector.extract` to
follow in a subsequent PR.
2025-01-30 01:24:25 +00:00
Martin Dvořák
eb30249b11
doc: make description of pp.analyze more precise (#6726)
As @nomeata told me, it should be "try to (...)" because even with
`pp.analyze` roundtripping often fails.
2025-01-21 15:03:48 +00:00
Kim Morrison
9080df3110
chore: import cleanup in Init (#6522)
This PR avoids unnecessarily importing "kitchen sink" files.
2025-01-04 04:13:13 +00:00
Eric Wieser
11eea84fd5
doc: explain app_delab (#6450)
This PR adds a docstring to the `@[app_delab]` attribute.

---------

Co-authored-by: Kyle Miller <kmill31415@gmail.com>
2024-12-29 15:06:55 +00:00
Kyle Miller
58f8e21502
feat: labeled and unique sorries (#5757)
This PR makes it harder to create "fake" theorems about definitions that
are stubbed-out with `sorry` by ensuring that each `sorry` is not
definitionally equal to any other. For example, this now fails:
```lean
example : (sorry : Nat) = sorry := rfl -- fails
```
However, this still succeeds, since the `sorry` is a single
indeterminate `Nat`:
```lean
def f (n : Nat) : Nat := sorry
example : f 0 = f 1 := rfl -- succeeds
```
One can be more careful by putting parameters to the right of the colon:
```lean
def f : (n : Nat) → Nat := sorry
example : f 0 = f 1 := rfl -- fails
```
Most sources of synthetic sorries (recall: a sorry that originates from
the elaborator) are now unique, except for elaboration errors, since
making these unique tends to cause a confusing cascade of errors. In
general, however, such sorries are labeled. This enables "go to
definition" on `sorry` in the Infoview, which brings you to its origin.
The option `set_option pp.sorrySource true` causes the pretty printer to
show source position information on sorries.

**Details:**

* Adds `Lean.Meta.mkLabeledSorry`, which creates a sorry that is labeled
with its source position. For example, `(sorry : Nat)` might elaborate
to
  ```
sorryAx (Lean.Name → Nat) false
`lean.foo.12.8.12.13.8.13._sorry._@.lean.foo._hyg.153
  ```
It can either be made unique (like the above) or merely labeled. Labeled
sorries use an encoding that does not impact defeq:
  ```
sorryAx (Unit → Nat) false (Function.const Lean.Name ()
`lean.foo.14.7.13.7.13.69._sorry._@.lean.foo._hyg.174)
  ```

* Makes the `sorry` term, the `sorry` tactic, and every elaboration
failure create labeled sorries. Most are unique sorries, but some
elaboration errors are labeled sorries.

* Renames `OmissionInfo` to `DelabTermInfo` and adds configuration
options to control LSP interactions. One field is a source position to
use for "go to definition". This is used to implement "go to definition"
on labeled sorries.

* Makes hovering over a labeled `sorry` show something friendlier than
that full `sorryAx` expression. Instead, the first hover shows the
simplified ``sorry `«lean.foo:48:11»``. Hovering over that hover shows
the full `sorryAx`. Setting `set_option pp.sorrySource true` makes
`sorry` always start with printing with this source position
information.

* Removes `Lean.Meta.mkSyntheticSorry` in favor of `Lean.Meta.mkSorry`
and `Lean.Meta.mkLabeledSorry`.

* Changes `sorryAx` so that the `synthetic` argument is no longer
optional.

* Gives `addPPExplicitToExposeDiff` awareness of labeled sorries. It can
set `pp.sorrySource` when source positions differ.

* Modifies the delaborator framework so that delaborators can set Info
themselves without it being overwritten.

Incidentally closes #4972.

Inspired by [this Zulip
thread](https://leanprover.zulipchat.com/#narrow/channel/287929-mathlib4/topic/Is.20a.20.60definition_wanted.60.20keyword.20possible.3F/near/477260277).
2024-12-11 23:53:02 +00:00
Kyle Miller
7b8504cf06
chore: post-stage0 cleanup for #6165 (#6268)
This PR puts code in terms of syntax quotations now that there has been
a stage0 update. Fixes a lingering bug in StructInst where some
intermediate syntax was malformed, but this had no observable effects
outside of some debug messages.
2024-12-01 00:20:59 +00:00
Kyle Miller
a1c3a36433
feat: parity between structure instance notation and where notation (#6165)
This PR modifies structure instance notation and `where` notation to use
the same notation for fields. Structure instance notation now admits
binders, type ascriptions, and equations, and `where` notation admits
full structure lvals. Examples of these for structure instance notation:
```lean
structure PosFun where
  f : Nat → Nat
  pos : ∀ n, 0 < f n

def p : PosFun :=
  { f n := n + 1
    pos := by simp }

def p' : PosFun :=
  { f | 0 => 1
      | n + 1 => n + 1
    pos := by rintro (_|_) <;> simp }
```
Just like for the structure `where` notation, a field `f x y z : ty :=
val` expands to `f := fun x y z => (val : ty)`. The type ascription is
optional.

The PR also is setting things up for future expansion. Pending some
discussion, in the future structure/`where` notation could have have
embedded `where` clauses; rather than `{ a := { x := 1, y := z } }` one
could write `{ a where x := 1; y := z }`.
2024-11-30 20:27:25 +00:00
Kim Morrison
ea221f3283
feat: Nat.(fold|foldRev|any|all)M? take a function which sees the upper bound (#6139)
This PR modifies the signature of the functions `Nat.fold`,
`Nat.foldRev`, `Nat.any`, `Nat.all`, so that the function is passed the
upper bound. This allows us to change runtime array bounds checks to
compile time checks in many places.
2024-11-22 03:05:51 +00:00
Tony Beta Lambda
99031695bd
feat: display coercions with a type ascription (#6119)
This PR adds a new delab option `pp.coercions.types` which, when
enabled, will display all coercions with an explicit type ascription.

[Link to Zulip
discussion](https://leanprover.zulipchat.com/#narrow/channel/239415-metaprogramming-.2F-tactics/topic/Roundtripping.20delaboration.20involving.20coercions)

Towards #4315
2024-11-21 23:02:47 +00:00
Kim Morrison
72e952eadc
chore: avoid runtime array bounds checks (#6134)
This PR avoids runtime array bounds checks in places where it can
trivially be done at compile time.

None of these changes are of particular consequence: I mostly wanted to
learn how much we do this, and what the obstacles are to doing it less.
2024-11-21 05:04:52 +00:00
Kim Morrison
f85c66789d
feat: Array.insertIdx/eraseIdx take a tactic-provided proof (#6133)
This PR replaces `Array.feraseIdx` and `Array.insertAt` with
`Array.eraseIdx` and `Array.insertIdx`, both of which take a `Nat`
argument and a tactic-provided proof that it is in bounds. We also have
`eraseIdxIfInBounds` and `insertIdxIfInBounds` which are noops if the
index is out of bounds. We also provide a `Fin` valued version of
`Array.findIdx?`. Together, these quite ergonomically improve the array
indexing safety at a number of places in the compiler/elaborator.
2024-11-20 09:52:38 +00:00
Kyle Miller
5eef3d27fb
feat: have #print show precise fields of structures (#6096)
This PR improves the `#print` command for structures to show all fields
and which parents the fields were inherited from, hiding internal
details such as which parents are represented as subobjects. This
information is still present in the constructor if needed. The pretty
printer for private constants is also improved, and it now handles
private names from the current module like any other name; private names
from other modules are made hygienic.

Example output for `#print Monad`:
```
class Monad.{u, v} (m : Type u → Type v) : Type (max (u + 1) v)
number of parameters: 1
parents:
  Monad.toApplicative : Applicative m
  Monad.toBind : Bind m
fields:
  Functor.map : {α β : Type u} → (α → β) → m α → m β
  Functor.mapConst : {α β : Type u} → α → m β → m α
  Pure.pure : {α : Type u} → α → m α
  Seq.seq : {α β : Type u} → m (α → β) → (Unit → m α) → m β
  SeqLeft.seqLeft : {α β : Type u} → m α → (Unit → m β) → m α
  SeqRight.seqRight : {α β : Type u} → m α → (Unit → m β) → m β
  Bind.bind : {α β : Type u} → m α → (α → m β) → m β
constructor:
  Monad.mk.{u, v} {m : Type u → Type v} [toApplicative : Applicative m] [toBind : Bind m] : Monad m
resolution order:
  Monad, Applicative, Bind, Functor, Pure, Seq, SeqLeft, SeqRight
```

Suggested by Floris van Doorn [on
Zulip](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/.23print.20command.20for.20structures/near/482503637).
2024-11-19 21:54:45 +00:00
Kyle Miller
691acde696
feat: pp.parens option to pretty print with all parentheses (#2934)
This PR adds the option `pp.parens` (default: false) that causes the
pretty printer to eagerly insert parentheses, which can be useful for
teaching and for understanding the structure of expressions. For
example, it causes `p → q → r` to pretty print as `p → (q → r)`.

Any notations with precedence greater than or equal to `maxPrec` do not
receive such discretionary parentheses, since this precedence level is
considered to be infinity.

This option was a feature in the Lean 3 community edition.
2024-11-15 19:11:54 +00:00
Kyle Miller
498d41633b
fix: pretty print .coeFun with terminfo of coercee (#6085)
This PR improves the term info for coercions marked with
`CoeFnType.coeFun` (such as `DFunLike.coe` in Mathlib), making "go to
definition" on the function name work. Hovering over such a coerced
function will show the coercee rather than the coercion expression. The
coercion expression can still be seen by hovering over the whitespace in
the function application.
2024-11-15 01:45:38 +00:00
Leonardo de Moura
b1e52f1475
chore: mark Meta.Context.config as private (#6051)
Motivation: we want to modify the internal representation and improve
`isDefEq` caching.
This PR is preparing the stage for future modifications.
2024-11-13 13:30:06 +11:00
Kyle Miller
d1a99d8d45
fix: avoid delaborating with field notation if object is a metavariable (#6014)
This PR prevents `Nat.succ ?_` from pretty printing as `?_.succ`, which
should make `apply?` be more usable.

Closes #5993
2024-11-08 20:57:37 +00:00
Kyle Miller
c7f5fd9a83
feat: make "type mismatch" error add numeric type ascriptions (#5919)
Example:
```lean
example : 0 = (0 : Nat) := by
  exact Eq.refl (0 : Int)
/-
error: type mismatch
  Eq.refl 0
has type
  (0 : Int) = 0 : Prop
but is expected to have type
  (0 : Nat) = 0 : Prop
-/
```
2024-11-01 16:44:52 +00:00
Kim Morrison
218601009b
chore: rename Array.back to back! (#5897) 2024-10-31 09:18:18 +00:00
Kyle Miller
cdbe29b46d
feat: accurate binder names in signatures (like in output of #check) (#5827)
An important part of the interface of a function is the parameter names,
for making used of named arguments. This PR makes the parameter names
print in a reliable way. The parameters of the type now appear as
hygienic names if they cannot be used as named arguments.

Modifies the heuristic for how parameters are chosen to appear before or
after the colon. The rule is now that parameters start appearing after
the colon at the first non-dependent non-instance-implicit parameter
that has a name unusable as a named argument. This is a refinement of
#2846.

Fixes the issue where consecutive hygienic names pretty print without a
space separating them, so we now have `(x✝ y✝ : Nat)` rather than `(x✝y✝
: Nat)`.

Breaking change: `Lean.PrettyPrinter.Formatter.pushToken` now takes an
additional boolean `ident` argument, which should be `true` for
identifiers. Used to insert discretionary space between consecutive
identifiers.

Closes #5810
2024-10-29 16:43:11 +00:00
Kyle Miller
c50f04ace0
feat: add delaborators for <|>, <*>, >>, <*, and *> (#5854)
Closes #5668
2024-10-26 23:49:16 +00:00
Kyle Miller
e07272a53a
chore: review delaborators, make sure they respond to pp.explicit (#5830)
Rule: if an expression contains an implicit argument that the
delaborator would omit, only use the delaborator if `pp.explicit` is
false.
2024-10-24 22:56:47 +00:00
Kim Morrison
71122696a1
feat: rename Array.shrink to take, and relate to List.take (#5796) 2024-10-21 23:35:32 +00:00
Kyle Miller
fd15d8f9ed
feat: Lean.Expr.name? (#5760)
Adds a recognizer for `Name` literal expressions. Handles `Name`
constructors as well as the `Lean.Name.mkStr*` functions.
2024-10-18 02:40:26 +00:00
Kyle Miller
36c2511b27
feat: options pp.mvars.anonymous and pp.mvars.levels (#5711)
Gives more control over pretty printing metavariables.

- When `pp.mvars.levels` is false, then universe level metavariables
pretty print as `_` rather than `?u.22`
- When `pp.mvars.anonymous` is false, then anonymous metavariables
pretty print as `?_` rather than `?m.22`. Named metavariables still
pretty print with their names. When this is false, it also sets
`pp.mvars.levels` to false, since every level metavariable is anonymous.
- When `pp.mvars` is false, then all metavariables pretty print as `?_`
or `_`.

Modifies TryThis to use `pp.mvars.anonymous` rather than doing a
post-delaboration modification. This incidentally improves TryThis since
it now prints universe level metavariables as `_` rather than `?u.22`.
2024-10-14 21:44:15 +00:00
Kyle Miller
bd46319aee
feat: add option pp.mvars.delayed (#5643)
Where before we had
```lean
#check fun x : Nat => ?a
-- fun x ↦ ?m.7 x : (x : Nat) → ?m.6 x
```
Now by default we have
```lean
#check fun x : Nat => ?a
-- fun x => ?a : (x : Nat) → ?m.6 x
```
In particular, delayed assignment metavariables such as `?m.7` pretty
print using the name of the metavariable they are delayed assigned to,
suppressing the bound variables used in the delayed assignment (hence
`?a` rather than `?a x`). Hovering over `?a` shows `?m.7 x`.

The benefit is that users can see the user-provided name in local
contexts. A justification for this pretty printing choice is that `?m.7
x` is supposed to stand for `?a`, and furthermore it is just as opaque
to assignment in defeq as `?a` is (however, when synthetic opaque
metavariables are made assignable, delayed assignments can be a little
less assignable than true synthetic opaque metavariables).

The original pretty printing behavior can be recovered using `set_option
pp.mvars.delayed true`.

This PR also extends the documentation for holes and synthetic holes,
with some technical details about what delayed assignments are. This
likely should be moved to the reference manual, but for now it is
included in this docstring.

(This PR is a simplified version of #3494, which has a round-trippable
notation for delayed assignments. The pretty printing in this PR is
unlikely to round trip, but it is better than the current situation,
which is that delayed assignment metavariables never round trip, and
plus it does not require introducing a new notation.)
2024-10-08 17:48:52 +00:00
Kyle Miller
6cdede33fb
fix: make sure name literals use escaping when pretty printing (#5639)
The app unexpanders for `Name.mkStr1` through `Name.mkStr8` weren't
respecting the escaping rules for names. For example, ``#check `«a.b»``
would show `` `a.b``.

This PR folds the unexpanders into the name literal delaborator, where
escaping is already handled.
2024-10-08 17:36:49 +00:00
Joachim Breitner
60096e7d15
refactor: more idiomatic syntax for if h: (#5567)
https://github.com/leanprover/lean4/pull/5552 introduced a fair number
of `if h:`, but the slightly preferred style is `if h :`, with a space,
so here goes a quick `sed`.
2024-10-01 15:23:54 +00:00
TomasPuverle
ddec5336e5
chore: switch obvious cases of array "bang"[]! indexing to rely on hypothesis (#5552)
Update certain uses of `arr[i]!` to use the "provably correct" version
`arr[i]`, in order to use "best practices".

Some motivation and discussion on
[Zulip](https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Lean.20compiler.2Felaborator.20development.20question/near/472934715)
2024-10-01 11:12:22 +00:00
Kyle Miller
40d6a6def0
fix: use breakable instead of unbreakable whitespace when formatting tokens (#5513)
The formatter was using `tk ++ " "` to separate tokens from tokens they
would merge with, but `" "` is not whitespace that could merge. This
affected large binder lists, which wouldn't pretty print with any line
breaks. Now they can be flowed across multiple lines.

Closes #5424
2024-09-29 06:33:39 +00:00
Kyle Miller
1129160d80
fix: make formatter use current token table (#5389)
Previously the formatter was using the builtin token table rather that
the one in the current environment. This could lead to round-tripping
failures for user-defined notations.

For an illustrative example, given the following notation
```lean
infixl:65 "+'" => Int.add
notation:65 a:65 "+'-" b:66 => Int.add a (id b)
```
then `5 +' -1` would parse as `Int.add 5 (-1)` and incorrectly pretty
print as `5+'-1`, which in turn would parse as `Int.add 5 (id 1)`. Now
it pretty prints as `5+' -1`.
2024-09-24 05:33:12 +00:00
euprunin
50339e38d9
chore: fix spelling mistakes in src/Lean/ (#5426)
Co-authored-by: euprunin <euprunin@users.noreply.github.com>
2024-09-23 14:56:59 +00:00
Kim Morrison
8c6ac845b1 chore: cleanup after export Bool.and/or/not/xor 2024-09-16 12:45:51 +10:00
Kim Morrison
4e0f6b8b45 feat: export Bool.and/or/not/xor 2024-09-16 12:45:51 +10:00
Kyle Miller
8fcec4049b
fix: make pretty printer escape identifiers that are tokens (#4979)
For example, if `forall` is a variable, it now pretty prints as
`«forall»`.

Closes #4686
2024-09-07 21:28:44 +00:00
Kyle Miller
7cd406f335
fix: check is valid structure projection when pretty printing (#4982)
For structure projections, the pretty printer assumed that the
expression was type correct. Now it checks that the object being
projected is of the correct type. Such terms appear in type mismatch
errors.

Also, fixes and improves `#print` for structures. The types of
projections now use MessageData (so are now hoverable), and the type of
`self` is now the correct type.

Closes #4670
2024-08-12 15:52:17 +00:00
Kyle Miller
5f31e938c1
feat: @[app_delab] (#4976)
Adds `@[app_delab ident]` as a macro for `@[delab app.ident]`. Resolves
the identifier when expanding the macro, saving needing to use the fully
qualified identifiers that `@[delab]` requires. Also, unlike `@[delab]`,
throws an error if the identifier cannot be resolved.

Closes #4899
2024-08-10 16:54:39 +00:00
Markus Himmel
4bac74c4ac chore: switch to Std.HashMap and Std.HashSet almost everywhere 2024-08-07 18:24:42 +02:00
Kyle Miller
7f128b39e7
feat: more than one optional argument can be omitted while pretty printing (#4854)
Before, the delaborator was conservative about omitting optional
arguments, only omitting the very last one. Now it can omit arbitrarily
long sequences of optional arguments from the end.

For simplicity of implementation, every optional argument is delaborated
and then potentially discarded. It could save state and lazily
delaborate, but we're running under the hypothesis that most optional
arguments are for very simple values (like `true`, `false`, or a numeric
literal), so it is unlikely that efficiency gains, if any, are worth it.
In particular, in the future structure constructors will have optional
arguments, but `unexpandStructureInstance` assumes none of the optional
fields are omitted.

Closes #4812
2024-07-29 19:02:39 +00:00
Marc Huisinga
84f8871c3f
fix: filter duplicate subexpressions (#4786)
For every parenthesized expression `(foo)`, the InfoView produces an
interactive component both for `(foo)` itself and its subexpression
`foo` because the corresponding `TaggedText` in the language server is
duplicated as well. Both of these subexpressions have the same
subexpression position and so they are identical w.r.t. interactive
features.

Removing this duplication would help reduce the size of the DOM of the
InfoView and ensure that the UI for InfoView features is consistent for
`(foo)` and `foo` (e.g. hovers would always highlight `(foo)`, not
either `(foo)` or `foo` depending on whether the mouse cursor is on the
bracket or not). It would also help resolve a bug where selecting a
subexpression will yield selection highlighting both for `(foo)` and
`foo`, as we use the subexpression position to identify which terms to
highlight.

This PR adjusts the parenthesizer to move the corresponding info instead
of duplicating it.
2024-07-25 08:58:49 +00:00
Joachim Breitner
1a12f63f74
refactor: move Synax.hasIdent, shake dependencies (#4766)
I noticed that a change to `Lean.PrettyPrinter.Delaborator.Builtins`
rebuilt more modules than I expected, so I moved a definition and
reduced some dependcies.

More reduction would be possible to move const-delaboration out of the
big `Lean.PrettyPrinter`, and import from `Lean.PrettyPrinter`
selectively.
2024-07-16 21:19:26 +00:00
Joachim Breitner
95b8095fa6
feat: PProd syntax (part 3) (#4756)
reworks #4730 based on feedback from @kmill:

 * Uses `×'` for PProd
 * No syntax for MProd for now
 * Angle brackets (without nesting) for the values
2024-07-16 21:06:04 +00:00
Kyle Miller
94cc8eb863
chore: add comment for why anonymous constructor notation isn't flattened during pretty printing (#4764) 2024-07-16 19:04:51 +00:00
Kyle Miller
5f70c1ca64
fix: make matcher pretty printer sensitive to pp.explicit (#4724)
Matchers usually have implicit arguments, and even if they don't the
notation hides the name of the matcher function.

Now when hovering over `match` expressions you can see the actual
underlying matcher expression.
2024-07-11 01:49:49 +00:00
Kyle Miller
7de0c58dc1
fix: don't set pp.tagAppFns when pretty printing signatures (#4665)
In #3911, a refactor to share `MessageData` code between `ppConst` and
the signature pretty printer unintentionally caused the signature pretty
printer to use the `pp.tagAppFns` option. This causes, for example, `+`
in `a + b` to independently have its own hover information due to the
fact that `notation` app unexpanders use the head function's syntax as
the `ref` when constructing the notation syntax. This behavior of
`pp.tagAppFns` is intentional, and it is used by docgen, but it should
not be activated for signatures.

This affects `#check` and was reported by Kevin Buzzard [on
Zulip](https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/degraded.20hover.20experience.20on.20.23check/near/449380674).

This PR also makes sure the initial `ref` when applying app unexpanders
is `.missing`, rather than whatever random value might be present in the
`CoreM` context.
2024-07-05 23:02:39 +00:00
Kyle Miller
c2edae92c8
fix: make sure syntax nodes always run their formatters (#4631)
Now syntax nodes have their formatters run even if the parsers they wrap
are all arity zero. This fixes an issue where if `ppSpace` appears in a
`macro`/`elab` then it does not format with a space due to the fact that
macro argument processing wraps this as `group(ppSpace)`, and `ppSpace`
has arity zero.

Implementation note: the fix is to make the `visitArgs` formatter
combinator always visit the last child, even if it does not exist (in
which case the visited node will be `Syntax.missing`). To compensate,
parser combinators like many and optional need to be sure to keep track
of whether there any children. Only optional's needed to be modified.

Closes #4561
2024-07-03 07:45:34 +00:00