11/-
2+ --#--
23# Embedding DSLs By Elaboration
34
5+ --#--
6+ # エラボレーションによる DSL の埋め込み
7+
8+ --#--
49In this chapter we will learn how to use elaboration to build a DSL. We will not
510explore the full power of `MetaM`, and simply gesture at how to get access to
611this low-level machinery.
712
13+ --#--
14+ この章では DSL を構築するためにどのようにエラボレーションを使うかについて学びます。ここでは `MetaM` の全機能を探求することはせずに、単にこの低レベルの機構にアクセスする方法を紹介します。
15+
16+ --#--
817More precisely, we shall enable Lean to understand the syntax of
918[ IMP ] (http://concrete-semantics.org/concrete-semantics.pdf),
1019which is a simple imperative language, often used for teaching operational and
11- denotational semantics.
20+ denotational semantics.
21+
22+ --#--
23+ 具体的には、[ IMP ] (http://concrete-semantics.org/concrete-semantics.pdf) の構文を Lean が理解できるようにします。これは単純な命令型言語で、操作的意味論・表示的意味論の教育によく用いられます。
1224
25+ --#--
1326We are not going to define everything with the same encoding that the book does.
1427For instance, the book defines arithmetic expressions and boolean expressions.
1528We, will take a different path and just define generic expressions that take
1629unary or binary operators.
1730
31+ --#--
32+ この本と同じエンコーディングですべてを定義するつもりはありません。例えば、この本では算術式や真偽値の式を定義しています。本章では別の方針を取り、単項演算子や二項演算子を取る一般的な式を定義します。
33+
34+ --#--
1835This means that we will allow weirdnesses like `1 + true`! But it will simplify
1936the encoding, the grammar and consequently the metaprogramming didactic.
2037
38+ --#--
39+ つまり、`1 + true` のような奇妙さを許容します!しかし、これはエンコーディングや文法、ひいてはメタプログラミングの教材として単純化することになります。
40+
41+ --#--
2142## Defining our AST
2243
44+ --#--
45+ ## AST の定義
46+
47+ --#--
2348We begin by defining our atomic literal value.
49+ --#--
50+ まず、アトミックなリテラルの値を定義します。
2451-/
2552
2653import Lean
@@ -31,16 +58,31 @@ inductive IMPLit
3158 | nat : Nat → IMPLit
3259 | bool : Bool → IMPLit
3360
61+ --#--
3462/- This is our only unary operator -/
63+ --#--
64+ /-
65+ 次は唯一の単項演算子です。
66+ -/
3567inductive IMPUnOp
3668 | not
3769
70+ --#--
3871/- These are our binary operations. -/
72+ --#--
73+ /-
74+ これらは二項演算子です。
75+ -/
3976
4077inductive IMPBinOp
4178 | and | add | less
4279
80+ --#--
4381/- Now we define the expressions that we want to handle. -/
82+ --#--
83+ /-
84+ ここで、今回扱いたい式を定義します。
85+ -/
4486
4587inductive IMPExpr
4688 | lit : IMPLit → IMPExpr
@@ -49,8 +91,11 @@ inductive IMPExpr
4991 | bin : IMPBinOp → IMPExpr → IMPExpr → IMPExpr
5092
5193/-
94+ --#--
5295And finally the commands of our language. Let's follow the book and say that
5396"each piece of a program is also a program":
97+ --#--
98+ そして最後に、言語のコマンドです。この本に従って、「プログラムの各部分もプログラムである」としましょう:
5499-/
55100
56101inductive IMPProgram
@@ -61,11 +106,18 @@ inductive IMPProgram
61106 | While : IMPExpr → IMPProgram → IMPProgram
62107
63108/-
109+ --#--
64110## Elaborating literals
65111
112+ --#--
113+ ### リテラルのエラボレート
114+
115+ --#--
66116Now that we have our data types, let's elaborate terms of `Syntax` into
67117terms of `Expr`. We begin by defining the syntax and an elaboration function for
68118literals.
119+ --#--
120+ さて、データ型ができたので、`Syntax` の項を `Expr` の項にエラボレートしましょう。まずはリテラルの構文とそのエラボレーション関数を定義します。
69121-/
70122
71123declare_syntax_cat imp_lit
@@ -74,8 +126,12 @@ syntax "true" : imp_lit
74126syntax "false" : imp_lit
75127
76128def elabIMPLit : Syntax → MetaM Expr
129+ --#--
77130 -- `mkAppM` creates an `Expr.app`, given the function `Name` and the args
78131 -- `mkNatLit` creates an `Expr` from a `Nat`
132+ --#--
133+ -- `mkAppM` は対象の関数の `Name` とその引数から `Expr.app` を作成する
134+ -- `mkNatLit` は `Nat` から `Expr` を作成する
79135 | `(imp_lit| $n:num) => mkAppM ``IMPLit.nat #[mkNatLit n.getNat]
80136 | `(imp_lit| true ) => mkAppM ``IMPLit.bool #[.const ``Bool.true []]
81137 | `(imp_lit| false ) => mkAppM ``IMPLit.bool #[.const ``Bool.false []]
@@ -88,14 +144,26 @@ elab "test_elabIMPLit " l:imp_lit : term => elabIMPLit l
88144#reduce test_elabIMPLit false -- IMPLit.bool true
89145
90146/-
147+ --#--
91148## Elaborating expressions
92149
150+ --#--
151+ ## 式のエラボレート
152+
153+ --#--
93154In order to elaborate expressions, we also need a way to elaborate our unary and
94155binary operators.
95156
157+ --#--
158+ 式をエラボレートするために、単項演算子と二項演算子をエラボレートする方法も必要です。
159+
160+ --#--
96161Notice that these could very much be pure functions (`Syntax → Expr`), but we're
97162staying in `MetaM` because it allows us to easily throw an error for match
98- completion.-/
163+ completion.
164+ --#--
165+ これらは純粋関数(`Syntax → Expr`)にすることもできますが、マッチの網羅時に例外を簡単に投げられるように `MetaM` に留まることとします。
166+ -/
99167
100168declare_syntax_cat imp_unop
101169syntax "not" : imp_unop
@@ -115,7 +183,12 @@ def elabIMPBinOp : Syntax → MetaM Expr
115183 | `(imp_binop| <) => return .const ``IMPBinOp.less []
116184 | _ => throwUnsupportedSyntax
117185
186+ --#--
118187/-Now we define the syntax for expressions: -/
188+ --#--
189+ /-
190+ ここで式の構文を定義します:
191+ -/
119192
120193declare_syntax_cat imp_expr
121194syntax imp_lit : imp_expr
@@ -124,24 +197,33 @@ syntax imp_unop imp_expr : imp_expr
124197syntax imp_expr imp_binop imp_expr : imp_expr
125198
126199/-
200+ --#--
127201Let's also allow parentheses so the IMP programmer can denote their parsing
128202precedence.
203+ --#--
204+ IMP プログラマがパースの優先順位を示せるように括弧も許可しましょう。
129205-/
130206
131207syntax "(" imp_expr ")" : imp_expr
132208
133209/-
210+ --#--
134211Now we can elaborate our expressions. Note that expressions can be recursive.
135212This means that our `elabIMPExpr` function will need to be recursive! We'll need
136213to use `partial` because Lean can't prove the termination of `Syntax`
137214consumption alone.
215+ --#--
216+ これで式をエラボレートできます。式は再帰的であることに注意してください。これは `elabIMPExpr` 関数が再帰的である必要があることを意味します!Lean は `Syntax` の消費だけでは終了を証明できないため `partial` を使う必要があります。
138217-/
139218
140219partial def elabIMPExpr : Syntax → MetaM Expr
141220 | `(imp_expr| $l:imp_lit) => do
142221 let l ← elabIMPLit l
143222 mkAppM ``IMPExpr.lit #[l]
223+ --#--
144224 -- `mkStrLit` creates an `Expr` from a `String`
225+ --#--
226+ -- `mkStrLit` は `String` から `Expr` を作成する
145227 | `(imp_expr| $i:ident) => mkAppM ``IMPExpr.var #[mkStrLit i.getId.toString]
146228 | `(imp_expr| $b:imp_unop $e:imp_expr) => do
147229 let b ← elabIMPUnOp b
@@ -167,9 +249,16 @@ elab "test_elabIMPExpr " e:imp_expr : term => elabIMPExpr e
167249-- IMPExpr.bin IMPBinOp.add (IMPExpr.lit (IMPLit.nat 1)) (IMPExpr.lit (IMPLit.bool true))
168250
169251/-
252+ --#--
170253## Elaborating programs
171254
255+ --#--
256+ ## プログラムのエラボレート
257+
258+ --#--
172259And now we have everything we need to elaborate our IMP programs!
260+ --#--
261+ そしてこれで IMP プログラムをエラボレートするために必要なものがすべて手に入りました!
173262-/
174263
175264declare_syntax_cat imp_program
@@ -203,8 +292,11 @@ partial def elabIMPProgram : Syntax → MetaM Expr
203292 | _ => throwUnsupportedSyntax
204293
205294/-
295+ --#--
206296And we can finally test our full elaboration pipeline. Let's use the following
207297syntax:
298+ --#--
299+ そしてついにエラボレーションのパイプラインを完全にテストすることができます。以下の構文を使ってみましょう:
208300-/
209301
210302elab ">>" p:imp_program "<<" : term => elabIMPProgram p
0 commit comments