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:
Leonardo de Moura 2021-10-02 17:30:06 -07:00
parent 42773941ed
commit c24cd877c8
3 changed files with 10 additions and 31 deletions

View file

@ -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)

View file

@ -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?)

View file

@ -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 >> ")"