1- /- # Extra: Pretty Printing
1+ /-
2+ --#--
3+ # Extra: Pretty Printing
4+ --#--
5+ # 付録:プリティプリント
6+ --#--
27The pretty printer is what Lean uses to present terms that have been
38elaborated to the user. This is done by converting the `Expr`s back into
49`Syntax` and then even higher level pretty printing datastructures. This means
@@ -7,6 +12,10 @@ there has to be code that tells it how to do that.
712In the big picture, the pretty printer consists of three parts run in the
813order they are listed in:
914
15+ --#--
16+ プリティプリンタとは、Lean がエラボレートした項をユーザに提示するために使用されるものです。これは `Expr` を `Syntax` に変換し、さらに高レベルのプリティプリント用データ構造に戻すことで行われます。これは Lean が `Expr` を作成する際に使用した実際の `Syntax` を思い出すわけではないことを意味します:もしそうであればその方法を指示するコードがあるはずですから。全体像として、プリティプリンタは3つの部分から構成されています:
17+
18+ --#--
1019- the **[ delaborator ] (https://github.com/leanprover/lean4/tree/master/src/Lean/PrettyPrinter/Delaborator)**
1120 this will be our main interest since we can easily extend it with our own code.
1221 Its job is to turn `Expr` back into `Syntax`.
@@ -16,18 +25,35 @@ order they are listed in:
1625 responsible for turning the parenthesized `Syntax` tree into a `Format` object that contains
1726 more pretty printing information like explicit whitespaces
1827
28+ --#--
29+ - **[ デラボレータ ] (https://github.com/leanprover/lean4/tree/master/src/Lean/PrettyPrinter/Delaborator)** 、この部分は簡単に独自のコードで拡張ができることもあり最も興味深い部分です。このパートの仕事は `Expr` を `Syntax` に戻すことです。
30+ - **[ parenthesizer ] (https://github.com/leanprover/lean4/blob/master/src/Lean/PrettyPrinter/Parenthesizer.lean)** は `Syntax` 木に便利だと思われる位置に括弧を追加する役割を持ちます。
31+ - **[ フォーマッタ ] (https://github.com/leanprover/lean4/blob/master/src/Lean/PrettyPrinter/Formatter.lean)** は括弧が付けられた `Syntax` 木に明示的なスペースを入れるなどのよりプリティプリントな情報を含む `Format` オブジェクトに変換する役割を持ちます。
32+
33+ --#--
1934## Delaboration
35+ --#--
36+ ## デラボレーション
37+ --#--
2038As its name suggests, the delaborator is in a sense the opposite of the
2139elaborator. The job of the delaborator is to take an `Expr` produced by
2240the elaborator and turn it back into a `Syntax` which, if elaborated,
2341should produce an `Expr` that behaves equally to the input one.
2442
43+ --#--
44+ その名前が示すように、デラボレータはある意味においてエラボレータの反対です。デラボレータの仕事は、エラボレータが生成した `Expr` を受け取り、`Syntax` に戻すことです。ここで生成される `Syntax` はエラボレートされると、デラボレータに入力された `Expr` と同じものを出力しなければなりません。
45+
46+ --#--
2547Delaborators have the type `Lean.PrettyPrinter.Delaborator.Delab`. This
2648is an alias for `DelabM Syntax`, where `DelabM` is the delaboration monad.
2749All of this machinery is defined [ here ] (https://github.com/leanprover/lean4/blob/master/src/Lean/PrettyPrinter/Delaborator/Basic.lean).
2850`DelabM` provides us with quite a lot of options you can look up in the documentation
2951(TODO: Docs link). We will merely highlight the most relevant parts here.
3052
53+ --#--
54+ デラボレータは `Lean.PrettyPrinter.Delaborator.Delab` という型を持ちます。これは `DelabM Syntax` のエイリアスで、`DelabM` はデラボレーションのためのモナドです。この機構についてはすべて [ ここ ] (https://github.com/leanprover/lean4/blob/master/src/Lean/PrettyPrinter/Delaborator/Basic.lean) にて定義されています。`DelabM` は非常に多くのオプションを提供しており、これはドキュメントから探すことができます(TODO: Docs link)。ここでは単に最も関連性のある部分を強調します。
55+
56+ --#--
3157- It has a `MonadQuotation` instance which allows us to declare `Syntax` objects
3258 using the familiar quotation syntax.
3359- It can run `MetaM` code.
@@ -36,13 +62,26 @@ All of this machinery is defined [here](https://github.com/leanprover/lean4/blob
3662- You can obtain the current subexpression using `SubExpr.getExpr`. There is
3763 also an entire API defined around this concept in the `SubExpr` module.
3864
65+ --#--
66+ - `MonadQuotation` インスタンスを持っており、おなじみのquotation構文を使って `Syntax` オブジェクトを宣言することができます。
67+ - `MetaM` のコードを実行することができます。
68+ - 例外を投げるための `MonadExcept` インスタンスを持ちます。
69+ - `whenPPOption` のような関数を使うことで `pp` オプションを操作することができます。
70+ - 現在の部分式を取得するには `SubExpr.getExpr` を使用します。また、`SubExpr` モジュールには、この概念を扱う API 全体が定義されています。
71+
72+ --#--
3973### Making our own
74+ --#--
75+ ### 独自のデラボレータを作る
76+ --#--
4077Like so many things in metaprogramming the elaborator is based on an attribute,
4178in this case the `delab` one. `delab` expects a `Name` as an argument,
4279this name has to start with the name of an `Expr` constructor, most commonly
4380`const` or `app`. This constructor name is then followed by the name of the
4481constant we want to delaborate. For example, if we want to delaborate a function
4582`foo` in a special way we would use `app.foo`. Let's see this in action:
83+ --#--
84+ メタプログラミングの多くのものと同様に、エラボレータは属性に基づいており、今回の場合では `delab` です。`delab` は引数として `Name` を受け取り、この名前は `Expr` コンストラクタの名前で始まる必要があり、最も一般的あなのは `const` か `app` です。このコンストラクタ名の後にデラボレートしたい定数の名前が続きます。例えば、関数 `foo` を特別な方法でデラボレートしたい場合は `app.foo` を使います。これを実際にやってみましょう:
4685-/
4786
4887import Lean
@@ -59,9 +98,12 @@ def delabFoo : Delab := do
5998#check foo 13 -- 1 : Nat, full applications are also pretty printed this way
6099
61100/-!
101+ --#--
62102This is obviously not a good delaborator since reelaborating this `Syntax`
63103will not yield the same `Expr`. Like with many other metaprogramming
64104attributes we can also overload delaborators:
105+ --#--
106+ この `Syntax` を再度エラボレートしても同じ `Expr` は得られないため、明らかに良いデラボレータではありません。他の多くのメタプログラミングの属性と同様に、デラボレータをオーバーロードすることもできます:
65107-/
66108
67109@[delab app.foo]
@@ -71,10 +113,13 @@ def delabfoo2 : Delab := do
71113#check foo -- 2 : Nat → Nat
72114
73115/-!
116+ --#--
74117The mechanism for figuring out which one to use is the same as well. The
75118delaborators are tried in order, in reverse order of registering, until one
76119does not throw an error, indicating that it "feels unresponsible for the `Expr`".
77120In the case of delaborators, this is done using `failure`:
121+ --#--
122+ それを使うかを判断するメカニズムも同じです。デラボレータは登録された順番の逆順に、「`Expr` に対して責任が無いと感じる」ことを示すエラーを投げないものまで試行されます。デラボレータの場合、これは `failure` を使って行われます:
78123-/
79124
80125@[delab app.foo]
@@ -85,8 +130,11 @@ def delabfoo3 : Delab := do
85130#check foo -- 2 : Nat → Nat, still 2 since 3 failed
86131
87132/-!
133+ --#--
88134In order to write a proper delaborator for `foo`, we will have to use some
89135slightly more advanced machinery though:
136+ --#--
137+ `foo` のための適切なデラボレータを書くためにはもう少し高度な機構を使う必要があります:
90138-/
91139
92140@[delab app.foo]
@@ -101,9 +149,14 @@ def delabfooFinal : Delab := do
101149#check foo -- 2 : Nat → Nat, still 2 since 3 failed
102150
103151/-!
152+ --#--
104153Can you extend `delabFooFinal` to also account for non full applications?
105154
155+ --#--
156+ 読者は `delabFooFinal` を拡張して、完全でない適用も考慮することができるでしょうか?
157+
106158## Unexpanders
159+ --#--
107160While delaborators are obviously quite powerful it is quite often not necessary
108161to use them. If you look in the Lean compiler for `@[delab` or rather `@[builtin_delab`
109162(a special version of the `delab` attribute for compiler use, we don't care about it),
@@ -115,21 +168,35 @@ they are of type `Lean.PrettyPrinter.Unexpander` which in turn is an alias for
115168are supposed to be the inverse of macros. The `UnexpandM` monad is quite a lot
116169weaker than `DelabM` but it still has:
117170
171+ --#--
172+ デラボレータは明らかに強力ですが、使う必要がないことも良くあります。Lean コンパイラにて `@[delab` か `@[builtin_delab`(コンパイラ用の特別バージョンの `delab` 属性)を探してみるとほとんど出てこないことがわかるでしょう。というのも、プリティプリントの大部分はいわゆる unexpander によって行われるからです。デラボレータとは異なり、これらは `Lean.PrettyPrinter.Unexpander` 型で、これは `Syntax → Lean.PrettyPrinter.UnexpandM Syntax` のエイリアスです。見ての通り、これらは `Syntax` から `Syntax` への変換で、マクロの逆であることを除けばマクロによく似ています。`UnexpandM` モナドは `DelabM` よりもかなり弱いですが、それでも下記の機能を持ちます:
173+
174+ --#--
118175- `MonadQuotation` for syntax quotations
119176- The ability to throw errors, although not very informative ones: `throw ()`
120177 is the only valid one
121178
179+ --#--
180+ - syntax quotation のための `MonadQuotation`
181+ - 例外の送出機能、ただこれはあまり有益なものではありません:唯一有効なのは `throw ()` だけです。
182+
183+ --#--
122184Unexpanders are always specific to applications of one constant. They are registered
123185using the `app_unexpander` attribute, followed by the name of said constant. The unexpander
124186is passed the entire application of the constant after the `Expr` has been delaborated,
125187without implicit arguments. Let's see this in action:
188+ --#--
189+ unexpander は常にある1つの定数の適用に対して固有です。これらは `app_unexpander` 属性と、それに続く対象の定数名を使って登録されます。unexpander には暗黙の引数無しで `Expr` がデラボレートされた後に、定数の適用全体が渡されます。これを実際に見てみましょう:
126190-/
127191
128192def myid {α : Type } (x : α) := x
129193
130194@[app_unexpander myid]
131195def unexpMyId : Unexpander
196+ --#--
132197 -- hygiene disabled so we can actually return `id` without macro scopes etc.
198+ --#--
199+ -- 健全性を無効にすることで、マクロスコープなどを使わずに `id` を実際に返すことができる。
133200 | `(myid $arg) => set_option hygiene false in `(id $arg)
134201 | `(myid) => pure $ mkIdent `id
135202 | _ => throw ()
@@ -138,15 +205,25 @@ def unexpMyId : Unexpander
138205#check myid -- id : ?m.3870 → ?m.3870
139206
140207/-!
208+ --#--
141209For a few nice examples of unexpanders you can take a look at
142210[ NotationExtra ] (https://github.com/leanprover/lean4/blob/master/src/Init/NotationExtra.lean)
143211
212+ --#--
213+ unexpander についていくつかの良例は [ NotationExtra ] (https://github.com/leanprover/lean4/blob/master/src/Init/NotationExtra.lean) を参照してください。
214+
215+ --#--
144216### Mini project
217+ --#--
218+ ### ミニプロジェクト
219+ --#--
145220As per usual, we will tackle a little mini project at the end of the chapter.
146221This time we build our own unexpander for a mini programming language.
147222Note that many ways to define syntax already have generation of the required
148223pretty printer code built-in, e.g. `infix`, and `notation` (however not `macro_rules`).
149224So, for easy syntax, you will never have to do this yourself.
225+ --#--
226+ いつものように、章の最後にてちょっとしたミニプロジェクトに取り組んでみます。今回はミニプログラミング言語のための独自の unexpander を作ります。`infix` や `notation` のような構文を定義するための多くの方法には必要なプリティプリンタコードを生成する機能がすでに組み込まれていることに注意してください(ただし、`macro_rules` には含まれていません)。そのため、簡単な構文であれば、自分でこれを行う必要はないでしょう。
150227-/
151228
152229declare_syntax_cat lang
@@ -180,8 +257,11 @@ instance : Coe Ident (TSyntax `lang) where
180257]
181258
182259/-!
260+ --#--
183261As you can see, the pretty printing output right now is rather ugly to look at.
184262We can do better with an unexpander:
263+ --#--
264+ 見ての通り、現時点の表示される出力はかなり醜いものになっています。unexpander を使えばもっとよくなります:
185265-/
186266
187267@[app_unexpander LangExpr.numConst]
@@ -218,7 +298,10 @@ def unexpandLet : Unexpander
218298]
219299
220300/-!
301+ --#--
221302That's much better! As always, we encourage you to extend the language yourself
222303with things like parenthesized expressions, more data values, quotations for
223304`term` or whatever else comes to your mind.
305+ --#--
306+ この方がずっと良いです!いつものように読者は、括弧でくくられた式や、より多くのデータ値、`term` の引用など思いついたものを使って自分で言語を拡張することをお勧めします。
224307-/
0 commit comments