Repository navigation
Description
Summary
I want to add a Lean 4 analyzer. The only usable Lean grammar is in tree-sitter-language-pack 1.x, but pyproject.toml caps the pack below 0.9. #130 added the cap because "the Dart grammar/API in 0.9 is not yet verified". Do you accept a move to 1.x for this? I can send the bump, with the Dart verification below, and the analyzer as two stacked PRs.
Grammar options
I compared the candidates on 300 real Lean 4 files (programs and proofs, not Mathlib), sampled from a private corpus of about 1,000 files:
| Grammar | Files with no errors | Lines in ERROR |
Declarations found | Python packaging |
|---|---|---|---|---|
Julian/tree-sitter-lean (the lean grammar in pack 1.23.1) |
46% | 24.8% | 91.0% | Only in pack 1.x. Not on PyPI, and the git install does not build its C extension. |
wvhulle/tree-sitter-lean (crate tree-sitter-lean4 0.3.0) |
28% | 33.4% | 78.3% | None (Rust crate only) |
antlr/grammars-v4 lean |
not measured | ANTLR, not tree-sitter. It skips whitespace and comments and needs a matched end. |
get_parser("lean") fails on pack 0.8.0, 0.9.1 and 0.13.0, and works on 1.23.1.
What the 1.x bump changes
I made the change on a branch and ran the suite:
- With only the pin changed, 2 Dart tests fail:
test_call_resolution_rulesandtest_riverpod_and_router_edges. The 1.x Dart grammar parsesFoo<T>(x)as a call whoseargument_partholdstype_arguments, not as arelational_expression. So theGarage.open -> ItemandcarProvider -> Cartype-argument edges are lost. - An 11-line change in
_process_chainreads those type arguments from the call. After it, all 654 tests pass, andruff checkandruff format --checkare clean. - 1.x downloads each grammar on first use and caches it under
cache_dir(). The pack grammars that CodeWiki uses aredart,go,javascript,typescript,vueandzig. So the first run needs network access. I can add at.download([...])step todocker/Dockerfile, so that the image runs offline.
This is the Dart verification that #130 asked for. I found no other issue or PR about updating the pack.
Proposed analyzer design
The grammar alone is not enough. It fails on #eval, #guard, #[...], ¬, ←, using, with and user notation. Also, end is a flat top-level node, so the tree does not give namespace nesting. I propose two layers:
- Structure, from a header scanner. The scanner reads Lean commands from the source, with comments and strings masked. It gives declaration names (
def,theorem/lemma,abbrev,instance,structure,class,inductive,axiom,opaque), thenamespace/section/endstack,open(includingopen X in),import, spans and/-- -/docstrings. It does not depend onERRORregions. - References, from tree-sitter. For a declaration whose node has no error (76.7% in the sample), take the
identifiernodes and drop binder,let, field and pattern names. For the other declarations, use tokens from the masked text.
Each reference resolves only to an exact fully qualified name. The analyzer tries the namespace chain, the open namespaces and the declarations of the imported files (transitively, cached by mtime, like zig.py does). It drops a reference that has no match, and it never guesses by a bare name. A lean branch in _resolve_callee keeps this authoritative, like the Go and Dart branches.
Other parts:
- Component types:
structure→struct,class→interface,inductive→class, and the rest →function.node_typekeeps the Lean keyword. .lake/andlake-packages/go in the ignore patterns.lakefile.leanandlakefile.tomlbecome build artifacts, andlake-manifest.jsonandlean-toolchainbecome manifests.- Tests use synthetic Lean only.
Known limits:
- Generalized field notation (
v.normforVec.norm) needs type information, so it does not resolve. - References from user
notation/macroare lost. - The scanner assumes that each command starts a line, which is the usual Lean style.
Tools that use Lean itself (doc-gen4, jixia) give exact data, but they need a built project, and jixia must match the project's Lean version. I propose to keep them out of scope.
Related
- Added flutter/dart support #130 added the
<0.9.0cap for Dart. - fix(analyzers): a class's constructor is a component like any method #149 found that the
requirements.txtpins (tree-sitter 0.23.2) could not load the C# grammar (ABI 15). 1b4af43 fixed this with tree-sitter 0.26.0. Pack 1.23.1 declarestree-sitter>=0.23, so the current pin already works with it. - analyzers: add tree-sitter based Go analyzer #140 and Add Zig and Vue SFC analyzers, Autotools build artifacts #142 (Go, Zig, Vue) take their grammars from the pack, so the 1.x move affects them too. Their tests pass on 1.23.1.
Questions
- Do you accept the move to
tree-sitter-language-pack>=1.23.1,<2.0.0, with the Dart fix, as a separate PR? - Do you accept that grammars download on first use, if the Docker image fetches them at build time?
- Is the two-layer design acceptable, or do you want a tree-sitter-only analyzer, with fewer declarations and no namespace nesting?
Activity