diff --git a/src/Init/Notation.lean b/src/Init/Notation.lean index 5611f4dee7..cdab0d0d43 100644 --- a/src/Init/Notation.lean +++ b/src/Init/Notation.lean @@ -267,6 +267,8 @@ syntax (name := rawNatLit) "nat_lit " num : term @[inherit_doc] infixr:90 " ∘ " => Function.comp @[inherit_doc] infixr:35 " × " => Prod +@[inherit_doc] infixr:35 " ×ₚ " => PProd +@[inherit_doc] infixr:35 " ×ₘ " => MProd @[inherit_doc] infix:50 " ∣ " => Dvd.dvd @[inherit_doc] infixl:55 " ||| " => HOr.hOr diff --git a/src/Init/NotationExtra.lean b/src/Init/NotationExtra.lean index fe3de0b2ba..fea8cf5163 100644 --- a/src/Init/NotationExtra.lean +++ b/src/Init/NotationExtra.lean @@ -163,6 +163,18 @@ end Lean | `($(_) $x $y) => `(($x, $y)) | _ => throw () +/- +@[app_unexpander PProd.mk] def unexpandPProdMk : Lean.PrettyPrinter.Unexpander + | `($(_) $x ($y, $ys,*)ₚ) => `(($x, $y, $ys,*)ₚ) + | `($(_) $x $y) => `(($x, $y)ₚ) + | _ => throw () + +@[app_unexpander MProd.mk] def unexpandMProdMk : Lean.PrettyPrinter.Unexpander + | `($(_) $x ($y, $ys,*)ₘ) => `(($x, $y, $ys,*)ₘ) + | `($(_) $x $y) => `(($x, $y)ₘ) + | _ => throw () +-/ + @[app_unexpander ite] def unexpandIte : Lean.PrettyPrinter.Unexpander | `($(_) $c $t $e) => `(if $c then $t else $e) | _ => throw () diff --git a/src/Lean/Elab/BuiltinNotation.lean b/src/Lean/Elab/BuiltinNotation.lean index 1f41718124..f94542c88b 100644 --- a/src/Lean/Elab/BuiltinNotation.lean +++ b/src/Lean/Elab/BuiltinNotation.lean @@ -220,6 +220,31 @@ partial def mkPairs (elems : Array Term) : MacroM Term := pure acc loop (elems.size - 1) elems.back +/-- Return syntax `PProd.mk elems[0] (PProd.mk elems[1] ... (PProd.mk elems[elems.size - 2] elems[elems.size - 1])))` -/ +partial def mkPPairs (elems : Array Term) : MacroM Term := + let rec loop (i : Nat) (acc : Term) := do + if i > 0 then + let i := i - 1 + let elem := elems[i]! + let acc ← `(PProd.mk $elem $acc) + loop i acc + else + pure acc + loop (elems.size - 1) elems.back + +/-- Return syntax `MProd.mk elems[0] (MProd.mk elems[1] ... (MProd.mk elems[elems.size - 2] elems[elems.size - 1])))` -/ +partial def mkMPairs (elems : Array Term) : MacroM Term := + let rec loop (i : Nat) (acc : Term) := do + if i > 0 then + let i := i - 1 + let elem := elems[i]! + let acc ← `(MProd.mk $elem $acc) + loop i acc + else + pure acc + loop (elems.size - 1) elems.back + + open Parser in partial def hasCDot : Syntax → Bool | Syntax.node _ k args => @@ -305,6 +330,17 @@ where return (← expandCDot? pairs).getD pairs | _ => Macro.throwUnsupported +/- +@[builtin_macro Lean.Parser.Term.ptuple] def expandPTuple : Macro + | `(()ₚ) => ``(PUnit.unit) + | `(($e, $es,*)ₚ) => mkPPairs (#[e] ++ es) + | _ => Macro.throwUnsupported + +@[builtin_macro Lean.Parser.Term.mtuple] def expandMTuple : Macro + | `(($e, $es,*)ₘ) => mkMPairs (#[e] ++ es) + | _ => Macro.throwUnsupported +-/ + @[builtin_macro Lean.Parser.Term.typeAscription] def expandTypeAscription : Macro | `(($e : $(type)?)) => do match (← expandCDot? e) with diff --git a/src/Lean/Parser/Term.lean b/src/Lean/Parser/Term.lean index 6cd855f3fd..77d7965ae8 100644 --- a/src/Lean/Parser/Term.lean +++ b/src/Lean/Parser/Term.lean @@ -174,9 +174,19 @@ do not yield the right result. -/ @[builtin_term_parser] def typeAscription := leading_parser "(" >> (withoutPosition (withoutForbidden (termParser >> " :" >> optional (ppSpace >> termParser)))) >> ")" + /-- Tuple notation; `()` is short for `Unit.unit`, `(a, b, c)` for `Prod.mk a (Prod.mk b c)`, etc. -/ @[builtin_term_parser] def tuple := leading_parser "(" >> optional (withoutPosition (withoutForbidden (termParser >> ", " >> sepBy1 termParser ", " (allowTrailingSep := true)))) >> ")" + +/-- Universe polymorphic tuple notation; `()ₚ` is short for `PUnit.unit`, `(a, b, c)ₚ` for `PProd.mk a (PProd.mk b c)`, etc. -/ +@[builtin_term_parser] def ptuple := leading_parser + "(" >> optional (withoutPosition (withoutForbidden (termParser >> ", " >> sepBy1 termParser ", " (allowTrailingSep := true)))) >> ")ₚ" + +/-- Universe monomorphic tuple notation; `(a, b, c)ₘ` for `MProd.mk a (MProd.mk b c)`, etc. -/ +@[builtin_term_parser] def mtuple := leading_parser + "(" >> withoutPosition (withoutForbidden (termParser >> ", " >> sepBy1 termParser ", " (allowTrailingSep := true))) >> ")ₘ" + /-- Parentheses, used for grouping expressions (e.g., `a * (b + c)`). Can also be used for creating simple functions when combined with `·`. Here are some examples: diff --git a/stage0/src/stdlib_flags.h b/stage0/src/stdlib_flags.h index 0699845ba4..658ab0874e 100644 --- a/stage0/src/stdlib_flags.h +++ b/stage0/src/stdlib_flags.h @@ -8,7 +8,7 @@ options get_default_options() { // switch to `true` for ABI-breaking changes affecting meta code opts = opts.update({"interpreter", "prefer_native"}, false); // switch to `true` for changing built-in parsers used in quotations - opts = opts.update({"internal", "parseQuotWithCurrentStage"}, false); + opts = opts.update({"internal", "parseQuotWithCurrentStage"}, true); // toggling `parseQuotWithCurrentStage` may also require toggling the following option if macros/syntax // with custom precheck hooks were affected opts = opts.update({"quotPrecheck"}, true); diff --git a/tests/lean/348.lean.expected.out b/tests/lean/348.lean.expected.out index cc7ea95c77..70c81daaeb 100644 --- a/tests/lean/348.lean.expected.out +++ b/tests/lean/348.lean.expected.out @@ -1 +1 @@ -348.lean:3:24-3:25: error: unexpected token '⟩'; expected ')' +348.lean:3:24-3:25: error: unexpected token '⟩'; expected ')', ')ₘ' or ')ₚ' diff --git a/tests/lean/interactive/incrementalTactic.lean.expected.out b/tests/lean/interactive/incrementalTactic.lean.expected.out index 706ae32c68..497c5c1de5 100644 --- a/tests/lean/interactive/incrementalTactic.lean.expected.out +++ b/tests/lean/interactive/incrementalTactic.lean.expected.out @@ -32,7 +32,8 @@ t 2 "severity": 1, "range": {"start": {"line": 1, "character": 38}, "end": {"line": 4, "character": 3}}, - "message": "unexpected token '/-!'; expected ')', '_', identifier or term", + "message": + "unexpected token '/-!'; expected ')', ')ₚ', '_', identifier or term", "fullRange": {"start": {"line": 1, "character": 38}, "end": {"line": 4, "character": 3}}}]} diff --git a/tests/lean/trailingComma.lean.expected.out b/tests/lean/trailingComma.lean.expected.out index 99655e8904..213955c2a2 100644 --- a/tests/lean/trailingComma.lean.expected.out +++ b/tests/lean/trailingComma.lean.expected.out @@ -1,4 +1,4 @@ [1, 2, 3] (2, 3) trailingComma.lean:6:13-6:14: error: unexpected token ','; expected ']' -trailingComma.lean:7:11-7:12: error: unexpected token ','; expected ')' +trailingComma.lean:7:11-7:12: error: unexpected token ','; expected ')', ')ₘ' or ')ₚ'