@@ -18,18 +18,18 @@ import Lean
18
18
-- XOR, denoted \oplus
19
19
infixl :60 " ⊕ " => fun l r => (!l && r) || (l && !r)
20
20
21
- #eval true ⊕ true -- false
22
- #eval true ⊕ false -- true
23
- #eval false ⊕ true -- true
24
- #eval false ⊕ false -- false
21
+ #guard !( true ⊕ true )
22
+ #guard true ⊕ false
23
+ #guard false ⊕ true
24
+ #guard !( false ⊕ false )
25
25
26
26
-- with `notation`, "left XOR"
27
27
notation :10 l:10 " LXOR " r:11 => (!l && r)
28
28
29
- #eval true LXOR true -- false
30
- #eval true LXOR false -- false
31
- #eval false LXOR true -- true
32
- #eval false LXOR false -- false
29
+ #guard !( true LXOR true )
30
+ #guard !( true LXOR false )
31
+ #guard false LXOR true
32
+ #guard !( false LXOR false )
33
33
34
34
/- As we can see the `infixl` command allows us to declare a notation for
35
35
a binary operation that is infix, meaning that the operator is in between
@@ -52,9 +52,9 @@ The two unintuitive parts about these two are:
52
52
precedence, meaning how strong they bind to their arguments, let's see this in action:
53
53
-/
54
54
55
- #eval true ⊕ false LXOR false -- false
56
- #eval ( true ⊕ false ) LXOR false -- false
57
- #eval true ⊕ (false LXOR false ) -- true
55
+ #guard !( true ⊕ false LXOR false )
56
+ #guard !(( true ⊕ false ) LXOR false )
57
+ #guard true ⊕ (false LXOR false )
58
58
59
59
/-!
60
60
As we can see, the Lean interpreter analyzed the first term without parentheses
@@ -154,9 +154,12 @@ We can now write `MyTerm` in place of things like `1 + 1` and it will be
154
154
it just means that the Lean parser can understand it:
155
155
-/
156
156
157
+ /-⋆-/ /--
158
+ info: elaboration function for 'termMyTerm' has not been implemented
159
+ MyTerm
160
+ -/
161
+ #guard_msgs in --#
157
162
#check_failure MyTerm
158
- -- elaboration function for 'termMyTerm' has not been implemented
159
- -- MyTerm
160
163
161
164
/-! Note: `#check_failure` command allows incorrectly typed terms to be indicated without error. -/
162
165
@@ -276,13 +279,20 @@ syntax binNumber := binDigit,+
276
279
/-!
277
280
Since we can just use named parsers in place of syntax categories, we can now easily
278
281
add this to the `term` category:
282
+ -/
283
+
284
+ open Lean Parser in
285
+ /-- function to check if parsing passes -/
286
+ def parse (cat : Name) (s : String) : MetaM Syntax := do
287
+ ofExcept <| runParserCategory (← getEnv) cat s
279
288
280
- ```lean
281
289
syntax "bin(" binNumber ")" : term
282
- #check bin(Z, O, Z, Z, O) -- elaboration function hasn't been implemented but parsing passes
283
- #check bin() -- fails to parse because `binNumber` is "one or many": expected 'O' or 'Z'
284
- ```
285
- -/
290
+ #check_failure bin(Z, O, Z, Z, O) -- elaboration function hasn't been implemented but parsing passes
291
+
292
+ -- fails to parse `bin()` because `binNumber` is "one or many": expected 'O' or 'Z'
293
+ /-⋆-/ /-- error: <input>:1:4: expected 'O' or 'Z' -/
294
+ #guard_msgs in --#
295
+ #eval parse `term "bin()"
286
296
287
297
syntax binNumber' := binDigit,* -- note the *
288
298
syntax "emptyBin(" binNumber' ")" : term
@@ -390,8 +400,8 @@ def isAdd11 : Syntax → Bool
390
400
| `(Nat.add 1 1 ) => true
391
401
| _ => false
392
402
393
- #eval isAdd11 (Syntax.mkApp (mkIdent `Nat.add) #[Syntax.mkNumLit "1" , Syntax.mkNumLit "1" ]) -- true
394
- #eval isAdd11 (Syntax.mkApp (mkIdent `Nat.add) #[mkIdent `foo, Syntax.mkNumLit "1" ]) -- false
403
+ #guard isAdd11 (Syntax.mkApp (mkIdent `Nat.add) #[Syntax.mkNumLit "1" , Syntax.mkNumLit "1" ]) -- true
404
+ #guard ! isAdd11 (Syntax.mkApp (mkIdent `Nat.add) #[mkIdent `foo, Syntax.mkNumLit "1" ]) -- false
395
405
396
406
/-!
397
407
The next level with matches is to capture variables from the input instead
@@ -426,8 +436,8 @@ def isLitAdd : TSyntax `term → Option Nat
426
436
| `(Nat.add $x:num $y:num) => some (x.getNat + y.getNat)
427
437
| _ => none
428
438
429
- #eval isLitAdd (Syntax.mkApp (mkIdent `Nat.add) #[Syntax.mkNumLit "1" , Syntax.mkNumLit "1" ]) -- some 2
430
- #eval isLitAdd (Syntax.mkApp (mkIdent `Nat.add) #[mkIdent `foo, Syntax.mkNumLit "1" ]) -- none
439
+ #guard isLitAdd (Syntax.mkApp (mkIdent `Nat.add) #[Syntax.mkNumLit "1" , Syntax.mkNumLit "1" ]) = some 2
440
+ #guard isLitAdd (Syntax.mkApp (mkIdent `Nat.add) #[mkIdent `foo, Syntax.mkNumLit "1" ]) = none
431
441
432
442
/-!
433
443
If you want to access the `Syntax` behind a `TSyntax` you can do this using
@@ -448,6 +458,7 @@ chapters.
448
458
declare_syntax_cat arith
449
459
450
460
syntax num : arith
461
+
451
462
syntax arith "-" arith : arith
452
463
syntax arith "+" arith : arith
453
464
syntax "(" arith ")" : arith
@@ -466,7 +477,9 @@ def test : Elab.TermElabM Nat := do
466
477
let stx ← `(arith| (12 + 3 ) - 4 )
467
478
pure (denoteArith stx)
468
479
469
- #eval test -- 11
480
+ /-⋆-/ /-- info: 11 -/
481
+ #guard_msgs in --#
482
+ #eval test
470
483
471
484
/-!
472
485
Feel free to play around with this example and extend it in whatever way
@@ -547,7 +560,9 @@ basic version of our notation:
547
560
-/
548
561
notation "{ " x " | " p " }" => setOf (fun x => p)
549
562
550
- #check { (x : Nat) | x ≤ 1 } -- { x | x ≤ 1 } : Set Nat
563
+ /-⋆-/ /-- info: { x | x ≤ 1 } : Set Nat -/
564
+ #guard_msgs in --#
565
+ #check { (x : Nat) | x ≤ 1 }
551
566
552
567
example : 1 ∈ { (y : Nat) | y ≤ 1 } := by simp[Membership.mem, Set.mem, setOf]
553
568
example : 2 ∈ { (y : Nat) | y ≤ 3 ∧ 1 ≤ y } := by simp[Membership.mem, Set.mem, setOf]
0 commit comments