Conversation
Collaborator
Author
|
Reviewed by OpenAI Codex over six rounds; every reproducible finding is fixed and tested. The ones worth recording here, because they changed the design rather than the code:
Measurements, since the corpus exercises none of this: a differential against the pre-#547 implementation over all 2015 What is left needs a |
Walk the whole source tracking comments, string, raw-string and character literals, French-quoted identifiers and bracket depth, instead of inspecting one physical line at a time. Closes #544. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwavhp4R8ptW6rP8hXERHE
Read a brace as an interpolation hole only in a string Lean parses as interpolated, splice surviving attributes out of the source instead of reprinting them, treat a syntax quotation as opaque, and recognise trivia inside an attribute instance and after an import. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwavhp4R8ptW6rP8hXERHE
Strip `@[eval_problem]` only where Lean would apply it, in front of a
declaration. That bounds every way this file's lexer can be wrong — an
interpolation it did not expect, a syntax extension it cannot know about — to a
marker left in place, which the generated workspace reports as `unknown
attribute [eval_problem]`, rather than an unannounced edit to somebody's source.
Read a string plainly unless the token in front of it says otherwise, so an
ordinary `"{"` no longer runs the scan on to the next `}`; recognise the marker
spelled `«eval_problem»`; read a quoted identifier inside an interpolation hole;
read an import broken across lines or carrying a comment; and coalesce the spans
removing two markers from one attribute list.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwavhp4R8ptW6rP8hXERHE
…port An attribute is only an attribute at the head of a command: at the start of its line, after the `in` of a prefix command, or after another attribute block. Together with the declaration that must follow, that is what marker-shaped text in a misread string has to reproduce to be stripped by mistake — spelling out `@[eval_problem] theorem` inside a string no longer suffices. Stop treating a doc comment after an import as the import's own: Lean gives it to the declaration that follows, so the import goes and the comment stays. Let a declaration carry any number of attribute blocks, and add the declaration keywords `coinductive`, `register_option` and `irreducible_def`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwavhp4R8ptW6rP8hXERHE
Where the brace-blind and interpolated readings of a string literal disagree about its extent, the scanner does not know whether what follows is code or the contents of somebody's string, and now declines to strip there rather than resolve it by guessing. That is the precondition of every construction that got marker-shaped text edited out of a literal: reaching it takes a hole read as plain text. The corroborating tests on command position and on the declaration that follows are tests on text, so a string can spell out whatever they look for — a line break, an `in`, a sibling attribute, `theorem`. This one is a test on how the scanner came to be looking at the marker instead. An attribute block now leaves command position open only where it was itself at the head of a command. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwavhp4R8ptW6rP8hXERHE
A string opened inside a hole carries holes of its own only if it is itself
interpolated. In `s!"{f "a{b"}"` the inner literal's brace stands for itself, and
reading it as a hole leaves the outer string looking unterminated, so the scan
resumes partway through it — which is how marker-shaped text there was still
being edited out.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwavhp4R8ptW6rP8hXERHE
A reading that never closes disagrees about where the literal ends by more than any other, so it says the literal runs to the end of the input and the span is disputed accordingly. Taking it for agreement was the one place the test was not symmetric in the two readings, and it was reachable with built-in syntax: a `dbg_trace` the lookback cannot classify, holding a raw string, left the interpolated reading unbalanced and the message exposed as code. It costs nothing to say so. Appending a marker to each of Mathlib's 8312 files strips all 8312, before and after. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwavhp4R8ptW6rP8hXERHE
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR replaces the line-oriented marker stripper in
EvalTools/Generate.leanwith a scanner that walks the whole source, tracking line and block comments, string, raw-string and character literals, French-quoted identifiers, syntax quotations and bracket depth. The marker is now recognised in every position Lean accepts it: sharing a line with its declaration or with a prefix command such asinclude x inorset_option … in, spanning several lines, carrying trivia as in@[/- why -/ eval_problem], spelled«eval_problem», or carrying siblings whose arguments contain a]or a,. Surviving siblings are spliced out of the source rather than reprinted, so a comment among them keeps the line break that terminates it. Imports are parsed the same way, so one broken across lines or carrying a comment is recognised, while a doc comment trailing an import stays with the declaration it documents.Lexing Lean without its parser cannot be exact: whether a
{in a string opens an interpolation hole is settled by the grammar, and the grammar is extensible. Three things keep that inexactness from editing somebody's string. A marker is stripped only in command position and only in front of a declaration; and no span the two readings of a string literal disagree about is stripped from at all. The first two are tests on text, which a string can reproduce; the third is not a test on the marker but on how the scanner came to be looking at it, and reaching marker-shaped text inside a literal takes exactly the disagreement it declines to resolve. What is left over is a marker left in place, which the generated workspace reports asunknown attribute [eval_problem]when it is built.Source.opaqueLexemeEnd?is the one place that knows how to step over a comment or a literal;Source.findTheoremBodyMarkernow uses it in place of its own copy.Nothing in the catalog exercises any of this today, so a differential check against the old implementation over every
.leanfile inLeanEval/,EvalTools/,tests/,generated/andtemplates/— in both shapes the generator passes in, with and without local-import stripping — reports no change in output.Closes #544.
🤖 Prepared with Claude Code