@@ -88,7 +88,8 @@ private def toBracketedBinderArrayLeafny (stx : Array (TSyntax `leafny_binder))
8888 let fb ← `(bracketedBinder| ($id : $tp:term))
8989 binders := binders.push fb
9090 | `(leafny_binder| (mut $id:ident : $tp:term)) => do
91- let fb ← `(bracketedBinder| ($id : $tp:term))
91+ let idOld := mkIdent <| id.getId.appendAfter "Old"
92+ let fb ← `(bracketedBinder| ($idOld : $tp:term))
9293 binders := binders.push fb
9394 | _ => throwError "unexpected syntax in leafny binder: {b}"
9495 return binders
@@ -118,7 +119,8 @@ def getIds (stx : Array (TSyntax `leafny_binder)) : MetaM (Array Ident) := do
118119 for b in stx do
119120 match b with
120121 | `(leafny_binder| (mut $id:ident : $_:term)) => do
121- ids := ids.push id
122+ let idOld := mkIdent <| id.getId.appendAfter "Old"
123+ ids := ids.push idOld
122124 | `(leafny_binder| ($id:ident : $_:term)) => do
123125 ids := ids.push id
124126 | _ => throwError "unexpected syntax in leafny binder: {b}"
@@ -139,15 +141,19 @@ partial def expandLeafnyDoSeqItem (modIds : Array Ident) (stx : doSeqItem) : Ter
139141 | `(Term.doSeqItem| $stx ;) => expandLeafnyDoSeqItem modIds $ <- `(Term.doSeqItem| $stx:doElem)
140142 | `(Term.doSeqItem| return ) => expandLeafnyDoSeqItem modIds $ <- `(Term.doSeqItem| return ())
141143 | `(Term.doSeqItem| return $t) =>
142- let mut ret <- `(term| ())
143- for modId in modIds do
144- ret <- `(term| ⟨$modId, $ret⟩)
145- return #[<-`(Term.doSeqItem| return ⟨$t, $ret⟩)]
144+ let ret <-
145+ if modIds.size = 0 then
146+ `(term| $t)
147+ else
148+ `(term| ($t, $[$modIds:term],*))
149+ return #[<-`(Term.doSeqItem| return $ret)]
146150 | `(Term.doSeqItem| pure $t) =>
147- let mut ret <- `(term| ())
148- for modId in modIds do
149- ret <- `(term| ⟨$modId, $ret⟩)
150- return #[<-`(Term.doSeqItem| pure ⟨$t, $ret⟩)]
151+ let ret <-
152+ if modIds.size = 0 then
153+ `(term| $t)
154+ else
155+ `(term| ($t, $[$modIds:term],*))
156+ return #[<-`(Term.doSeqItem| pure $ret)]
151157 | `(Term.doSeqItem| if $h:ident : $t:term then $thn:doSeq else $els:doSeq) =>
152158 let thn <- expandLeafnyDoSeq modIds thn
153159 let els <- expandLeafnyDoSeq modIds els
@@ -227,6 +233,13 @@ private def Array.andList (ts : Array (TSyntax `term)) : TermElabM (TSyntax `ter
227233 t <- `(term| $t' ∧ $t)
228234 return t
229235
236+ private def addPreludeToPreCond (pre : Term) (modIds : Array Ident) : CoreM (TSyntax `term) := do
237+ let mut pre := pre
238+ for modId in modIds do
239+ let modIdOld := mkIdent <| modId.getId.appendAfter "Old"
240+ pre ← `(term| let $modId:ident := $modIdOld:ident; $pre)
241+ pure pre
242+
230243elab_rules : command
231244 | `(command|
232245 method $name:ident $binders:leafny_binder* return ( $retId:ident : $type:term )
@@ -244,17 +257,22 @@ elab_rules : command
244257
245258 let mut mods := #[]
246259 for modId in modIds do
247- -- let modIdOld := mkIdent <| modId.getId.appendAfter "Old"
260+ let modIdOld := mkIdent <| modId.getId.appendAfter "Old"
248261 -- let modOld <- `(Term.doSeqItem| let $modIdOld:ident := $modId:ident)
249- let mod <- `(Term.doSeqItem| let mut $modId:ident := $modId :ident)
262+ let mod <- `(Term.doSeqItem| let mut $modId:ident := $modIdOld :ident)
250263 mods := mods.push mod
251264 let mutTypes ← getMutTypes binders
252- let mut retType <- `(Unit)
253- for mutType in mutTypes, modId in modIds do
254- retType <- `(($modId:ident : $mutType) × $retType)
265+ let mut retType : Term <- `($type)
266+ if mutTypes.size != 0 then
267+ let lastMutType := mutTypes[mutTypes.size - 1 ]!
268+ let mutTypes := mutTypes.pop.reverse
269+ let mut mutTypeProd := lastMutType
270+ for mutType in mutTypes do
271+ mutTypeProd <- `($mutType × $mutTypeProd)
272+ retType <- `($retType × $mutTypeProd)
255273 let defCmd <- `(command|
256274 set_option linter.unusedVariables false in
257- def $name $bindersIdents* : VelvetM (($retId:ident : $type) × $ retType) := do $mods* $doSeq*
275+ def $name $bindersIdents* : VelvetM $ retType:term := do $mods* $doSeq*
258276 $suf:suffix)
259277 -- let lemmaName := mkIdent <| name.getId.appendAfter "_correct"
260278
@@ -264,12 +282,13 @@ elab_rules : command
264282 let post <- ens.andListWithName ensName
265283
266284 let namelessPre <- req.andList
285+ let namelessPre <- addPreludeToPreCond namelessPre modIds
267286 let namelessPost <- ens.andList
268287
269- let mut ret <- `(term| ())
270- for modId in modIds do
271- let modId := mkIdent <| modId.getId.appendAfter "New"
272- ret <- `(term| ⟨$modId , $ret⟩ )
288+ let ret <- if modIds.size = 0 then
289+ `(term| $retId)
290+ else
291+ `(term| ($retId , $[$modIds:term],*) )
273292
274293 let ids ← getIds binders
275294 let obligation : VelvetObligation := {
@@ -279,17 +298,16 @@ elab_rules : command
279298 ret := ret
280299 pre := pre
281300 post := post
301+ modIds := modIds
282302 }
283- let newIds := modIds.map (fun x => Lean.mkIdent <| x.getId.appendAfter "New" )
284- let modBinders ← newIds.zip mutTypes |>.mapM fun (newId, mutType) =>
285- `(bracketedBinder| ($newId : $mutType))
286- return (defCmd, obligation, { obligation with pre := namelessPre , post := namelessPost , modBinders , newIds })
303+ let modBinders ← modIds.zip mutTypes |>.mapM fun (mId, mutType) =>
304+ `(bracketedBinder| ($mId : $mutType))
305+ return (defCmd, obligation, { obligation with pre := namelessPre , post := namelessPost , modBinders , retType := type })
287306 elabCommand defCmd
288307 velvetObligations.modify (·.insert name.getId obligation)
289308 velvetTestingContextMap.modify (·.insert name.getId testingCtx)
290309
291310notation "{" P "}" c "{" v "," Q "}" => triple P c (fun v => Q)
292-
293311/-
294312example:
295313open TotalCorrectness DemonicChoice
@@ -305,22 +323,24 @@ elab_rules : command
305323 let .some obligation := ctx[name.getId]? | throwError "no obligation found"
306324 let bindersIdents := obligation.binderIdents
307325 let ids := obligation.ids
308- let retId := obligation.retId
326+ -- let retId := obligation.retId
309327 let ret := obligation.ret
310- let pre := obligation.pre
328+ let pre ← liftCoreM <| addPreludeToPreCond obligation.pre obligation.modIds
311329 let post := obligation.post
312330 let lemmaName := mkIdent <| name.getId.appendAfter "_correct"
313331 -- let proof <- withRef tkp ``()
314332 let proofSeq ← withRef tkp `(tacticSeq|
315333 unfold $name
316334 ($proof))
335+
317336 let thmCmd <- withRef tkp `(command|
318337 @[loomSpec]
319338 lemma $lemmaName $bindersIdents* :
320339 triple
321340 $pre
322341 ($name $ids*)
323- (fun ⟨$retId, $ret⟩ => $post) := by $proofSeq $suf:suffix)
342+ (fun $ret => $post) := by $proofSeq $suf:suffix)
343+ trace[Loom] "{ thmCmd} "
324344 Command.elabCommand thmCmd
325345 velvetObligations.modify (·.erase name.getId)
326346
@@ -358,7 +378,7 @@ def elabDefiningDecidableInstancesForVelvetSpec (nameRaw : Ident)
358378 let (target, suffix, binders) :=
359379 if pre?
360380 then (ctx.pre, "PreDecidable" , bindersIdents)
361- else (ctx.post, "PostDecidable" , bindersIdents ++ ctx.modBinders)
381+ else (ctx.post, "PostDecidable" , bindersIdents ++ ctx.modBinders |>.push ⟨mkExplicitBinder ctx.retId ctx.retType⟩ )
362382 let decidableInstName := name.appendAfter suffix
363383 -- let proof := tac.getD (← `(term| (by infer_instance) ))
364384 let tac := tac.getD (← `(Lean.Parser.Tactic.tacticSeq| skip ))
@@ -394,7 +414,7 @@ elab_rules : command
394414 let bindersIdents := ctx.binderIdents
395415 let bundle (pre? : Bool) := if pre?
396416 then (ctx.pre, name.appendAfter "PreDecidable" , ids)
397- else (ctx.post, name.appendAfter "PostDecidable" , ids ++ ctx.newIds )
417+ else (ctx.post, name.appendAfter "PostDecidable" , ids ++ ctx.modIds |>.push retId )
398418 let decideTerm bundled : CommandElabM (TSyntax `term) := do
399419 let (target, instname, args) := bundled
400420 try
@@ -404,7 +424,7 @@ elab_rules : command
404424 `(term| ($(mkIdent ``decide) ($target)))
405425 let matcherTerm ← `(term|
406426 match ($(Syntax.mkApp (mkIdent execName) ids)) with
407- | $(mkIdent ``DivM.res) ⟨$retId, $ ret⟩ => $(← decideTerm <| bundle false )
427+ | $(mkIdent ``DivM.res) $ ret => $(← decideTerm <| bundle false )
408428 | _ => false )
409429 let ifTerm ← `(term| if $(← decideTerm <| bundle true ) then $matcherTerm else true )
410430 let testerName := name.appendAfter "Tester"
0 commit comments