Skip to content

Conversation

@ammkrn
Copy link
Contributor

@ammkrn ammkrn commented Jan 1, 2026

When ready, will close #3 (also see that issue for relevant discussion).

The format is described in format_ndjson and the README has been updated accordingly, along with the recommended command for invocation; the old README recommended invoking lake exe, which will not correctly set up the lake env in the most common use case, something like exporting mathlib.

format_ndjson.md Outdated
Expr.lit (Literal.strVal)
```
{
"lit": {
Copy link
Contributor

Choose a reason for hiding this comment

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

This does not seem to be what your program currently actually prints?

| .lit (.natVal i) => return .mkObj [("natVal", s!"{i}")]
| .lit (.strVal s) => return .mkObj [("strVal", s)]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, I've pushed a correction for the format specification.

format_ndjson.md Outdated
"levelParams": Array<integer>,
"type": integer,
"value": integer,
"hints": Array<"opaque" | "abbrev" | integer>
Copy link
Contributor

Choose a reason for hiding this comment

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

This is also incorrectly documented afaict?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ditto.

Corrects two errors in the format specification for string literals and
reducibility hints.
Correct a typo of `deBruijnIndex`
@ammkrn
Copy link
Contributor Author

ammkrn commented Jan 9, 2026

The open comments should be resolved, and I believe I addressed the remaining points in #10

+ Namespaces backreferences from a generic "i" to "in", "il", and "ie" for name, level, and expr.

+ Abbreviates some json attribute names
@nomeata
Copy link

nomeata commented Jan 9, 2026

Thanks!

(Seeing how slow lean4export is I’m inclined to rewrite the exporter to use simple string interpolation into hardcoded JSON lines, at least for everything that only contains numbers, but that can wait until other dust has settled.)

Modifies the export procedure and format to export the components of an
inductive declaration (the inductive specification(s), constructors,
and recursors) together.

Consumers are generally going to want to find these related declarations
anyway, and with the introduction of the auxiliary `.rec_<N>` recursors
motivated by nested inductive support, (in my opinion) this is a more
comprehensible format.
@ammkrn
Copy link
Contributor Author

ammkrn commented Jan 13, 2026

I've added one commit 50db814 to implement the change mentioned elsewhere, packaging related elements of an inductive declaration.

@nomeata
Copy link

nomeata commented Jan 13, 2026

Great! Are declarations now following the Lean.Declaration type consistently, so that a lean-using importer can parse to that type directly?

Hmm, it seems we now have a somewhat odd mix of Lean.Declaration and Lean.ConstantInfo. But if its a “best of both worlds” mix it’s maybe fine?

@ammkrn
Copy link
Contributor Author

ammkrn commented Jan 13, 2026

Great! Are declarations now following the Lean.Declaration type consistently, so that a lean-using importer can parse to that type directly?

Hmm, it seems we now have a somewhat odd mix of Lean.Declaration and Lean.ConstantInfo. But if its a “best of both worlds” mix it’s maybe fine?

I'm not sure how one would be able to parse anything directly regardless of format since (a) we're using integer pointers and (b) it was already suggested that we make simplifying cuts that would prevent direct parsing, like removing "deBruijnIndex" and changing "binderName".

Lean.Declaration only includes what's strictly necessary for a "full" kernel implementation to do the work of type checking; for example it expects the consumer to both construct and check recursors. The very first exporter implementation followed that pattern.

In the previous round of format changes, it was decided that the exporter should include additional information (like "targets" for the recursors and rec rules, Eq/Quot declarations, etc.). With this additional info it's much easier to bootstrap new checkers, implement certain memory optimizations, and have things like parallel checkers.

Looking at Lean.Declaration, maybe it's worth it to similarly group mutual definitions as well.

@nomeata
Copy link

nomeata commented Jan 13, 2026

I didn’t mean “parse generically”, but I meant “parse export to List Lean.Declaration” (so field name changes or indirections are not a blocker).

But thanks for the historical perspective, agreed on that count.

@nomeata nomeata mentioned this pull request Jan 15, 2026
@nomeata
Copy link

nomeata commented Jan 15, 2026

Looking at Lean.Declaration, maybe it's worth it to similarly group mutual definitions as well.

These are always ever unsafe, so not of high importance here? But in principle you are right.

Exports elements of mutual theorem and def/opaque blocks together.
@ammkrn
Copy link
Contributor Author

ammkrn commented Jan 15, 2026

Looking at Lean.Declaration, maybe it's worth it to similarly group mutual definitions as well.

These are always ever unsafe, so not of high importance here? But in principle you are right.

Should be done in 7188ec9 modulo style issues.

@nomeata
Copy link

nomeata commented Jan 15, 2026

Am I reading this right that it doesn't distinguish between a normal definition and a singly-recursive definition? It seems that of that's the case, import information is lost. I assume that's why Lean.Declaration is explicit in where the mutual groups are. But maybe lean forgets that information so it's hard to reproduce the declaration here?

@nomeata
Copy link

nomeata commented Jan 15, 2026

Hmm, the Kernel certainly doesn’t seem to remember whether a declaration came from a .mutualDefnDecl or not, so by the time we have a ConstantInfo this information is lost.

Ah! But the kernel treats any unsafe declaration as recursive, even if not in a mutual block. Odd. But not partial declarations.

I find it confusing.

In any case, I think I’m leaning towards an export format that more closely matches Lean.Declaration here, and with a dedicated .mutual tag that is only used when Lean.Declaration.mutualDefnDecl would be used (namely when its unsafe or partial and all is not a singleton). This way parsers for checkers who do not support this can just skip the whole line. But I don't feel strongly about it.

@ammkrn
Copy link
Contributor Author

ammkrn commented Jan 15, 2026

In any case, I think I’m leaning towards an export format that more closely matches Lean.Declaration here, and with a dedicated .mutual tag that is only used when Lean.Declaration.mutualDefnDecl would be used (namely when its unsafe or partial and all is not a singleton). This way parsers for checkers who do not support this can just skip the whole line. But I don't feel strongly about it.

I have no issue with that. To the earlier question, I think examination of all (specifically whether there's more than one name in there) would be the context clue.

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.

[RFC] Switch to JSON

3 participants