chore: define if-then-else again as a macro
We can do it using the new auxiliary notation `let_mvar%` and `wait_if_type_mvar%`.
This commit is contained in:
parent
42773941ed
commit
c24cd877c8
3 changed files with 10 additions and 31 deletions
|
|
@ -137,6 +137,16 @@ infixr:100 " <$> " => Functor.map
|
|||
macro_rules | `($x <|> $y) => `(binop_lazy% HOrElse.hOrElse $x $y)
|
||||
macro_rules | `($x >> $y) => `(binop_lazy% HAndThen.hAndThen $x $y)
|
||||
|
||||
syntax (name := termDepIfThenElse) (priority := high) ppGroup(ppDedent("if " ident " : " term " then" ppSpace term ppDedent(ppSpace "else") ppSpace term)) : term
|
||||
|
||||
macro_rules
|
||||
| `(if $h:ident : $c then $t:term else $e:term) => `(let_mvar% ?m := $c; wait_if_type_mvar% ?m; dite ?m (fun $h:ident => $t) (fun $h:ident => $e))
|
||||
|
||||
syntax (name := termIfThenElse) (priority := high) ppGroup(ppDedent("if " term " then" ppSpace term ppDedent(ppSpace "else") ppSpace term)) : term
|
||||
|
||||
macro_rules
|
||||
| `(if $c then $t:term else $e:term) => `(let_mvar% ?m := $c; wait_if_type_mvar% ?m; ite ?m $t $e)
|
||||
|
||||
macro "if " "let " pat:term " := " d:term " then " t:term " else " e:term : term =>
|
||||
`(match $d:term with | $pat:term => $t | _ => $e)
|
||||
|
||||
|
|
|
|||
|
|
@ -50,35 +50,6 @@ open Meta
|
|||
| none => throwError "invalid constructor ⟨...⟩, expected type must be known"
|
||||
| _ => throwUnsupportedSyntax
|
||||
|
||||
@[builtinTermElab Lean.Parser.Term.if] def elabIf : TermElab := fun stx expectedType? => do
|
||||
/- "if " >> optIdent >> termParser >> " then " >> termParser >> " else " >> termParser -/
|
||||
let c := stx[2]
|
||||
let t := stx[4]
|
||||
let e := stx[6]
|
||||
if !stx[1].isNone then
|
||||
-- TODO: add special support for dependent ite
|
||||
let h := stx[1][0]
|
||||
let stxNew ← `(dite $c (fun $h:ident => $t) (fun $h:ident => $e))
|
||||
withMacroExpansion stx stxNew <| elabTerm stxNew expectedType?
|
||||
else if let some c ← isLocalIdent? c then
|
||||
let cType ← inferType c
|
||||
-- Postpone if the type of the condition is not available
|
||||
tryPostponeIfMVar cType
|
||||
let localDecl ← getLocalDecl c.fvarId!
|
||||
-- If `c` is auxiliary let-decl created by this elaborator, then expand it (see "else" branch of this method)
|
||||
let c ←
|
||||
if localDecl.userName.eraseMacroScopes == `_if_cond then
|
||||
instantiateMVars localDecl.value
|
||||
else
|
||||
pure c
|
||||
elabAppArgs (← mkConst `ite) #[] #[Arg.expr c, Arg.stx t, Arg.stx e] expectedType? (explicit := false) (ellipsis := false)
|
||||
else
|
||||
-- If condition is not a free variable, then add an auxiliary let-decl.
|
||||
let cNew ← `(_if_cond)
|
||||
let iteNew := stx.setArg 2 cNew
|
||||
let stxNew ← `(let_tmp _if_cond := $c; $iteNew)
|
||||
withMacroExpansion stx stxNew <| elabTerm stxNew expectedType?
|
||||
|
||||
@[builtinTermElab borrowed] def elabBorrowed : TermElab := fun stx expectedType? =>
|
||||
match stx with
|
||||
| `(@& $e) => return markBorrowed (← elabTerm e expectedType?)
|
||||
|
|
|
|||
|
|
@ -269,8 +269,6 @@ def macroLastArg := macroDollarArg <|> macroArg
|
|||
|
||||
@[builtinTermParser] def dynamicQuot := leading_parser "`(" >> ident >> "|" >> incQuotDepth (parserOfStack 1) >> ")"
|
||||
|
||||
@[builtinTermParser] def «if» := leading_parser:leadPrec ppGroup $ ppDedent $ "if " >> optIdent >> termParser >> " then" >> ppSpace >> termParser >> ppDedent (ppSpace >> "else") >> ppSpace >> termParser
|
||||
|
||||
end Term
|
||||
|
||||
@[builtinTermParser default+1] def Tactic.quot : Parser := leading_parser "`(tactic|" >> incQuotDepth tacticParser >> ")"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue