Zulip Chat Archive

Stream: lean4

Topic: Current state of dependency management


Patrick Massot (Dec 13 2023 at 16:44):

I haven't followed the discussions about the very complicated issue of having a Lean library requiring more than Mathlib (and its dependency). What is the state of the art? Concretely, does anyone knows how to start a library depending on Mathlib and Partax? Right now Partax has lean toolchain 4.3.0 and Mathlib has lean toolchain 4.4.0-rc1. I would like to tell lake: use Lean 4.3.0 in my project with the latest Mathlib compatible with 4.3.0 and the latest Partax. I tried various things but without any luck. Note that using any version of Mathlib compatible with 4.3.0 would already be a good start. @Mac Malone

Patrick Massot (Dec 13 2023 at 16:45):

Note this should be a trivial case since Mathlib and Partax have no common dependency.

Mac Malone (Dec 13 2023 at 16:46):

Also, fortunately, Mathlib has release tags that mirror the Lean 4 version, so you should just be able to require mathlb from <url> @ "v4.3.0".

Patrick Massot (Dec 13 2023 at 16:47):

This is the very first thing I tried.

Patrick Massot (Dec 13 2023 at 16:48):

I tried editing the project lean-toolchain and lakefile to put 4.3.0 everywhere.

Mac Malone (Dec 13 2023 at 16:48):

Oh! What happened?

Patrick Massot (Dec 13 2023 at 16:48):

But somehow std still gets messed up.

Mac Malone (Dec 13 2023 at 16:49):

That's weird.

Patrick Massot (Dec 13 2023 at 16:49):

I'll try again from the beginning.

Patrick Massot (Dec 13 2023 at 16:50):

There are so many steps and each step can mess up the work of the previous step so the order is crucial.

Patrick Massot (Dec 13 2023 at 16:51):

Weirdly enough, it looks like it worked this time.

Mac Malone (Dec 13 2023 at 16:56):

As an aside, if you plan to use Partax for compiling large parser categories (e.g., ones including term), I want to warn you that it will take some time (a few minutes), as I have not had time to work on optimizing the parser compiler.

Patrick Massot (Dec 13 2023 at 16:57):

I understand this needs to be avoided. I'd like to define my own syntax category and compile that.

Mac Malone (Dec 13 2023 at 16:58):

Great! In that case, it should hopefully work well!

Patrick Massot (Dec 13 2023 at 16:58):

Is there any documentation besides the README?

Patrick Massot (Dec 13 2023 at 17:00):

import Partax

declare_syntax_cat test

syntax "foo" : test

syntax "bar" : test

open scoped Partax

compile_parser Lean.Parser.Category.test => testParser

fails :sad:

Patrick Massot (Dec 13 2023 at 17:09):

Mac Malone said:

As an aside, if you plan to use Partax for compiling large parser categories (e.g., ones including term), I want to warn you that it will take some time (a few minutes), as I have not had time to work on optimizing the parser compiler.

Actually maybe I misunderstood that comment. The syntax I want to be able to parse obviously contain terms. Does that mean I can't use Partax? And those few minutes, are they only when building the parser or also whenever using the parser?

Mac Malone (Dec 13 2023 at 17:09):

Patrick Massot said:

Is there any documentation besides the README?

@Patrick Massot Sadly, not much. However, this case is covered by the README. To compile parser categories, one uses compile_parser_category instead of compile_parser.

Patrick Massot (Dec 13 2023 at 17:11):

I tried

import Partax

declare_syntax_cat test

syntax "foo" : test

syntax "bar" : test

open scoped Partax

compile_parser_category Lean.Parser.Category.test

but it also fails

Patrick Massot (Dec 13 2023 at 17:11):

It says: parser 'Lean.Parser.Category.test' is missing a 'keywords : NameSet' definition

Mac Malone (Dec 13 2023 at 17:11):

Patrick Massot said:

The syntax I want to be able to parse obviously contain terms. Does that mean I can't use Partax? And those few minutes, are they only when building the parser or also whenever using the parser?

You can use Partax, it just means compiling the term category will take a few minutes. The compiled parser will be fast, just the building is slow. You can cache the result by sticking the compilation of term in a separate module. (Partax does this with Partax.Test.LCompile.)

Mac Malone (Dec 13 2023 at 17:13):

Patrick Massot said:

I tried
[...]
but it also fails

Sorry, I should have been more specific. To compile a category, use compile_parser_category <category-name>. For instance, compile_parser_category test in your example.

Mac Malone (Dec 13 2023 at 17:15):

@Patrick Massot Also, I did verify that Partax builds on v4.4.0-rc1, so you should also be able to use it with the latest Mathlib.

Patrick Massot (Dec 13 2023 at 17:15):

Ok, compile_parser_category test works (I mean it does not bring any error message), thanks.

Patrick Massot (Dec 13 2023 at 17:16):

Is the next step to put import Partax.Test.LCompile to get terms?

Mac Malone (Dec 13 2023 at 17:16):

Here is a complete version of your example:

import Partax

declare_syntax_cat test

syntax "foo" : test

syntax "bar" : test

open scoped Partax

compile_parser_category test

#eval test.run' "foo" -- Except String (TSyntax `test)

Mac Malone (Dec 13 2023 at 17:17):

Patrick Massot said:

Is the next step to put import Partax.Test.LCompile to get terms?

That will only get you the core terms/commands. If you wan tthe Mathlib ones, you will need to do the same as LCompile but after an import Mathlib (and an open scoped of any relevant namespace defining more scoped terms/commands).

Patrick Massot (Dec 13 2023 at 17:26):

Did you actually ever tried that? How long did it take?

Mac Malone (Dec 13 2023 at 17:28):

@Patrick Massot No, I have not tried compiling Mathlib parsers. I do not imagine it will take orders of magnitude longer (e.g., it will likely take several minutes rather than a few). The definitions Partax creates are not mutual, so the time should scale approximately linearly (especially as the primary time sink is elaboration time).

Mac Malone (Dec 13 2023 at 17:33):

I can go give it a shot an report back if you want.

Patrick Massot (Dec 13 2023 at 17:33):

I can already tell you 15 minutes are not enough on my computer.

Mac Malone (Dec 13 2023 at 17:34):

wow

Patrick Massot (Dec 13 2023 at 17:34):

I'll have lunch now and see whether a lunch time is enough.

Mac Malone (Dec 13 2023 at 17:34):

I wonder how many parsers mathlib defines...

Mario Carneiro (Dec 13 2023 at 17:36):

not that many

Mac Malone (Dec 13 2023 at 17:36):

@Mario Carneiro Note this includes syntax/notation declarations.

Mario Carneiro (Dec 13 2023 at 17:36):

at least not term parsers, but I suppose the term grammar is mutual with tactic and mathlib defines a lot of those

Mac Malone (Dec 13 2023 at 17:37):

Ah, yes, term includes tactic.

Mario Carneiro (Dec 13 2023 at 17:37):

is it possible to not go through the elaborator here?

Mac Malone (Dec 13 2023 at 17:38):

@Mario Carneiro Yes, that would be the optimization I should spend time on.

Mac Malone (Dec 13 2023 at 17:38):

I just haven't had the time (no pun intended).

Mario Carneiro (Dec 13 2023 at 17:38):

I'm sure you have better things to do with your time :wink:

Patrick Massot (Dec 13 2023 at 17:51):

35 minutes is not enough, so I'll declare this approach unsuitable for anything involving Mathlib.

Mario Carneiro (Dec 13 2023 at 17:52):

what is your motivation for using Partax in the first place?

Mac Malone (Dec 13 2023 at 17:52):

:sad: That's probably fair.

Patrick Massot (Dec 13 2023 at 17:56):

Mario, the context is Lean verbose, my controlled natural language for teaching library. I ported the help tactic which suggest tactics. Currently this help tactic outputs strings but there is nothing checking that those strings are valid tactics. If I modify the syntax of a tactic and forget to update the help tactic then users get misleading advice. So I tried to build syntax in the help tactic. But this is super painful. So my next idea was to keep producing strings but try to parse them before suggesting them. This is where Partax sounded useful. But I guess I should simply try runParserCategory.

Mario Carneiro (Dec 13 2023 at 17:56):

yes you should

Mario Carneiro (Dec 13 2023 at 17:57):

although, it's also strange that your syntax wouldn't parse

Mac Malone (Dec 13 2023 at 17:57):

Yes, in the context of a tactic, runParserCategory is probably much better anyway (as there is already a proper Lean environment).

Mario Carneiro (Dec 13 2023 at 17:57):

in what way is it painful to build syntax?

Patrick Massot (Dec 13 2023 at 17:59):

Mario Carneiro said:

although, it's also strange that your syntax wouldn't parse

I don't understand what you mean.

Mario Carneiro (Dec 13 2023 at 18:00):

if you pretty print syntax it always parses (outside a few rare edge cases)

Mario Carneiro (Dec 13 2023 at 18:00):

so it is definitely recommended to construct syntax and pretty print it instead of building a string

Mario Carneiro (Dec 13 2023 at 18:01):

this is how tryThis works

Patrick Massot (Dec 13 2023 at 18:01):

The problem is not to pretty-print syntax, it is to build syntax. Mostly because the quotation syntax is so brittle and needs random type ascriptions all over the place.

Mario Carneiro (Dec 13 2023 at 18:02):

hm, my recommendation is still to use syntax quotations but maybe there is a specific issue that comes up?

Patrick Massot (Dec 13 2023 at 18:03):

It always end up working, sometimes after getting help, but it's a huge work compared to building a string.

Patrick Massot (Dec 13 2023 at 18:03):

So building a string and parsing it seems a lot easier.

Mario Carneiro (Dec 13 2023 at 18:04):

well you are talking about brittle solutions, producing a string is very brittle

Patrick Massot (Dec 13 2023 at 18:05):

I know that string production alone is super brittle, this is why I'm trying various ways to produce syntax.

Mario Carneiro (Dec 13 2023 at 18:06):

well reparsing won't help, it will just change the way that the tactic breaks

Patrick Massot (Dec 13 2023 at 18:06):

The goal is to catch breaking before users see it.

Mario Carneiro (Dec 13 2023 at 18:07):

it really sounds to me like syntax quotations are the right way to go, even if they are fiddly

Patrick Massot (Dec 13 2023 at 18:07):

The library has tests, but currently they don't try the suggestions.

Mario Carneiro (Dec 13 2023 at 18:07):

because only you have to deal with that, not users

Patrick Massot (Dec 13 2023 at 18:09):

Ok, I'll try again quotations. Let's pick an example. Given n : Name, a string such as " ≥ " and e : Expr, how would you produce syntax for n ≥ e?

Mario Carneiro (Dec 13 2023 at 18:10):

there is no "such as" for syntax in that position, you would have to pattern match it and handle them separately

Patrick Massot (Dec 13 2023 at 18:10):

I mean without first producing a string and then parsing it...

Patrick Massot (Dec 13 2023 at 18:11):

Ok, let's say the relation is fixed.

Mario Carneiro (Dec 13 2023 at 18:11):

let n := mkIdent n
match s with
| "≥" => `($n:ident  $e)
| ...

Patrick Massot (Dec 13 2023 at 18:11):

Does that really work without delaborating e first?

Mario Carneiro (Dec 13 2023 at 18:11):

oh I missed that e is not syntax

Mario Carneiro (Dec 13 2023 at 18:12):

no you need to call delab on it first

Patrick Massot (Dec 13 2023 at 18:13):

Ok, so this is indeed a lot of work. Doable but a lot of work.

Siddhartha Gadgil (Dec 14 2023 at 03:52):

A related question: is there a convenient method similar to runParserCategory but which parses a maximal initial piece matching the syntax? Currently I solve this by copy-pasting and modifying from runParserCategory.

Mario Carneiro (Dec 14 2023 at 03:52):

no


Last updated: Dec 20 2023 at 11:08 UTC