chore: cleanup

This commit is contained in:
Leonardo de Moura 2020-08-28 08:27:30 -07:00
parent 479f001de4
commit 4bc1be17f4
13 changed files with 191 additions and 203 deletions

View file

@ -45,18 +45,11 @@ fun stx expectedType? => match_syntax stx with
expectedType ← instantiateMVars expectedType;
let expectedType := expectedType.consumeMData;
expectedType ← whnf expectedType;
match expectedType.getAppFn with
| Expr.const constName _ _ => do
env ← getEnv;
match env.find? constName with
| some (ConstantInfo.inductInfo val) =>
match val.ctors with
| [ctor] => do
newStx ← `($(mkCIdentFrom stx ctor) $(args.getSepElems)*);
withMacroExpansion stx newStx $ elabTerm newStx expectedType?
| _ => throwError ("invalid constructor ⟨...⟩, '" ++ constName ++ "' must have only one constructor")
| _ => throwError ("invalid constructor ⟨...⟩, '" ++ constName ++ "' is not an inductive type")
| _ => throwError ("invalid constructor ⟨...⟩, expected type is not an inductive type " ++ indentExpr expectedType)
matchConstStruct expectedType.getAppFn
(fun _ => throwError ("invalid constructor ⟨...⟩, expected type must be a structure " ++ indentExpr expectedType))
(fun val _ ctor => do
newStx ← `($(mkCIdentFrom stx ctor.name) $(args.getSepElems)*);
withMacroExpansion stx newStx $ elabTerm newStx expectedType?)
| none => throwError "invalid constructor ⟨...⟩, expected type must be known"
| _ => throwUnsupportedSyntax

View file

@ -194,7 +194,7 @@ modify fun s => { s with vars := s.vars.push (PatternVar.localVar id), found :=
-- It produces "unknown free variable: _kernel_fresh.<some idx>" at step `csimp.cpp`
def processIdAuxAux (stx : Syntax) (mustBeCtor : Bool) (env : Environment) (f : Expr) : M Nat :=
match f with
| Expr.const fName _ _ =>
| Expr.const fName _ _ => do
match env.find? fName with
| some $ ConstantInfo.ctorInfo val => liftM $ getNumExplicitCtorParams val
| some $ info =>
@ -498,26 +498,20 @@ partial def main : Expr → M Pattern
newE ← whnf e;
if newE != e then
main newE
else match e.getAppFn with
| Expr.const declName us _ => do
env ← getEnv;
match env.find? declName with
| ConstantInfo.ctorInfo v => do
let args := e.getAppArgs;
unless (args.size == v.nparams + v.nfields) $ throwInvalidPattern e;
let params := args.extract 0 v.nparams;
let fields := args.extract v.nparams args.size;
let binderInfos := getFieldsBinderInfo v;
fields ← fields.mapIdxM fun i field => do {
let binderInfo := binderInfos.get! i;
if binderInfo.isExplicit then
main field
else
mkInaccessible field
};
pure $ Pattern.ctor declName us params.toList fields.toList
| _ => throwInvalidPattern e
| _ => throwInvalidPattern e
else matchConstCtor e.getAppFn (fun _ => throwInvalidPattern e) fun v us => do
let args := e.getAppArgs;
unless (args.size == v.nparams + v.nfields) $ throwInvalidPattern e;
let params := args.extract 0 v.nparams;
let fields := args.extract v.nparams args.size;
let binderInfos := getFieldsBinderInfo v;
fields ← fields.mapIdxM fun i field => do {
let binderInfo := binderInfos.get! i;
if binderInfo.isExplicit then
main field
else
mkInaccessible field
};
pure $ Pattern.ctor v.name us params.toList fields.toList
end ToDepElimPattern

View file

@ -48,10 +48,9 @@ env ← getEnv;
m ← mkHeader "inductive" id lparams type isUnsafe;
let m := m ++ Format.line ++ "constructors:";
m ← ctors.foldlM
(fun (m : MessageData) ctor =>
match env.find? ctor with
| some v => pure $ m ++ Format.line ++ ctor ++ " : " ++ v.type
| none => pure m)
(fun (m : MessageData) ctor => do
cinfo ← getConstInfo ctor;
pure $ m ++ Format.line ++ ctor ++ " : " ++ cinfo.type)
m;
logInfo m

View file

@ -109,13 +109,9 @@ def getInductiveValFromMajor (major : Expr) : TacticM InductiveVal :=
liftMetaMAtMain $ fun mvarId => do
majorType ← inferType major;
majorType ← whnf majorType;
match majorType.getAppFn with
| Expr.const n _ _ => do
env ← getEnv;
match env.find? n with
| ConstantInfo.inductInfo val => pure val
| _ => Meta.throwTacticEx `induction mvarId ("major premise type is not an inductive type " ++ indentExpr majorType)
| _ => Meta.throwTacticEx `induction mvarId ("major premise type is not an inductive type " ++ indentExpr majorType)
matchConstInduct majorType.getAppFn
(fun _ => Meta.throwTacticEx `induction mvarId ("major premise type is not an inductive type " ++ indentExpr majorType))
(fun val _ => pure val)
private partial def getRecFromUsingLoop (baseRecName : Name) : Expr → TacticM (Option Meta.RecursorInfo)
| majorType => do

View file

@ -1105,16 +1105,13 @@ num.foldM (fun _ us => do u ← mkFreshLevelMVar; pure $ u::us) []
Remark: fresh universe metavariables are created if the constant has more universe
parameters than `explicitLevels`. -/
def mkConst (constName : Name) (explicitLevels : List Level := []) : TermElabM Expr := do
env ← getEnv;
match env.find? constName with
| none => throwError ("unknown constant '" ++ constName ++ "'")
| some cinfo =>
if explicitLevels.length > cinfo.lparams.length then
throwError ("too many explicit universe levels")
else do
let numMissingLevels := cinfo.lparams.length - explicitLevels.length;
us ← mkFreshLevelMVars numMissingLevels;
pure $ Lean.mkConst constName (explicitLevels ++ us)
cinfo ← getConstInfo constName;
if explicitLevels.length > cinfo.lparams.length then
throwError ("too many explicit universe levels")
else do
let numMissingLevels := cinfo.lparams.length - explicitLevels.length;
us ← mkFreshLevelMVars numMissingLevels;
pure $ Lean.mkConst constName (explicitLevels ++ us)
private def mkConsts (candidates : List (Name × List String)) (explicitLevels : List Level) : TermElabM (List (Expr × List String)) := do
env ← getEnv;

View file

@ -665,17 +665,6 @@ c?.isSome
end Environment
/- Helper functions for accessing environment -/
@[inline]
def matchConst {α : Type} (env : Environment) (e : Expr) (failK : Unit → α) (k : ConstantInfo → List Level → α) : α :=
match e with
| Expr.const n lvls _ =>
match env.find? n with
| some cinfo => k cinfo lvls
| _ => failK ()
| _ => failK ()
namespace Kernel
/- Kernel API -/

View file

@ -295,14 +295,10 @@ match type.eq? with
| none => throwAppBuilderException `noConfusion ("equality expected" ++ hasTypeMsg h type)
| some (α, a, b) => do
α ← whnf α;
env ← getEnv;
let f := α.getAppFn;
matchConst env f (fun _ => throwAppBuilderException `noConfusion ("inductive type expected" ++ indentExpr α)) $ fun cinfo us =>
match cinfo with
| ConstantInfo.inductInfo v => do
u ← getLevel target;
pure $ mkAppN (mkConst (mkNameStr v.name "noConfusion") (u :: us)) (α.getAppArgs ++ #[target, a, b, h])
| _ => throwAppBuilderException `noConfusion ("inductive type expected" ++ indentExpr α)
matchConstInduct α.getAppFn (fun _ => throwAppBuilderException `noConfusion ("inductive type expected" ++ indentExpr α)) fun v us => do
u ← getLevel target;
pure $ mkAppN (mkConst (mkNameStr v.name "noConfusion") (u :: us)) (α.getAppArgs ++ #[target, a, b, h])
def mkNoConfusion (target : Expr) (h : Expr) : m Expr := liftMetaM $ mkNoConfusionImp target h
def mkPure (monad : Expr) (e : Expr) : m Expr :=

View file

@ -58,11 +58,9 @@ forallTelescope e $ fun xs b => do
ensureType b;
check b
private def checkConstant (c : Name) (lvls : List Level) : MetaM Unit := do
env ← getEnv;
match env.find? c with
| none => throwUnknownConstant c
| some cinfo => unless (lvls.length == cinfo.lparams.length) $ throwIncorrectNumberOfLevels c lvls
private def checkConstant (constName : Name) (us : List Level) : MetaM Unit := do
cinfo ← getConstInfo constName;
unless (us.length == cinfo.lparams.length) $ throwIncorrectNumberOfLevels constName us
private def getFunctionDomain (f : Expr) : MetaM Expr := do
fType ← inferType f;

View file

@ -31,46 +31,37 @@ def throwIncorrectNumberOfLevels {α} (constName : Name) (us : List Level) : Met
throwError $ "incorrect number of universe levels " ++ mkConst constName us
private def inferConstType (c : Name) (us : List Level) : MetaM Expr := do
env ← getEnv;
match env.find? c with
| some cinfo =>
if cinfo.lparams.length == us.length then
pure $ cinfo.instantiateTypeLevelParams us
else
throwIncorrectNumberOfLevels c us
| none =>
throwUnknownConstant c
cinfo ← getConstInfo c;
if cinfo.lparams.length == us.length then
pure $ cinfo.instantiateTypeLevelParams us
else
throwIncorrectNumberOfLevels c us
private def inferProjType (structName : Name) (idx : Nat) (e : Expr) : MetaM Expr := do
let failed : Unit → MetaM Expr := fun _ => throwError $ "invalide projection" ++ indentExpr (mkProj structName idx e);
structType ← inferType e;
structType ← whnf structType;
env ← getEnv;
matchConst env structType.getAppFn failed $ fun structInfo structLvls => do
match structInfo with
| ConstantInfo.inductInfo { nparams := n, ctors := [ctor], .. } =>
let structParams := structType.getAppArgs;
if n != structParams.size then failed ()
else match env.find? ctor with
| none => failed ()
| some (ctorInfo) => do
ctorType ← inferAppType (mkConst ctor structLvls) structParams;
ctorType ← idx.foldM
(fun i ctorType => do
ctorType ← whnf ctorType;
match ctorType with
| Expr.forallE _ _ body _ =>
if body.hasLooseBVars then
pure $ body.instantiate1 $ mkProj structName i e
else
pure body
| _ => failed ())
ctorType;
matchConstStruct structType.getAppFn failed fun structVal structLvls ctorVal =>
let n := structVal.nparams;
let structParams := structType.getAppArgs;
if n != structParams.size then failed ()
else do
ctorType ← inferAppType (mkConst ctorVal.name structLvls) structParams;
ctorType ← idx.foldM
(fun i ctorType => do
ctorType ← whnf ctorType;
match ctorType with
| Expr.forallE _ d _ _ => pure d
| _ => failed ()
| _ => failed ()
| Expr.forallE _ _ body _ =>
if body.hasLooseBVars then
pure $ body.instantiate1 $ mkProj structName i e
else
pure body
| _ => failed ())
ctorType;
ctorType ← whnf ctorType;
match ctorType with
| Expr.forallE _ d _ _ => pure d
| _ => failed ()
def throwTypeExcepted {α} (type : Expr) : MetaM α :=
throwError $ "type expected " ++ indentExpr type

View file

@ -78,29 +78,27 @@ instance : HasToString RecursorInfo :=
end RecursorInfo
private def mkRecursorInfoForKernelRec (declName : Name) (val : RecursorVal) : MetaM RecursorInfo := do
indInfo ← getConstInfo val.getInduct;
match indInfo with
| ConstantInfo.inductInfo ival =>
let numLParams := ival.lparams.length;
let univLevelPos := (List.range numLParams).map RecursorUnivLevelPos.majorType;
let univLevelPos := if val.lparams.length == numLParams then univLevelPos else RecursorUnivLevelPos.motive :: univLevelPos;
let produceMotive := List.replicate val.nminors true;
let paramsPos := (List.range val.nparams).map some;
let indicesPos := (List.range val.nindices).map (fun pos => val.nparams + pos);
let numArgs := val.nindices + val.nparams + val.nminors + val.nmotives + 1;
pure {
recursorName := declName,
typeName := val.getInduct,
univLevelPos := univLevelPos,
majorPos := val.getMajorIdx,
depElim := true,
recursive := ival.isRec,
produceMotive := produceMotive,
paramsPos := paramsPos,
indicesPos := indicesPos,
numArgs := numArgs
}
| _ => throwError "ill-formed builtin recursor"
ival ← getConstInfoInduct val.getInduct;
let numLParams := ival.lparams.length;
let univLevelPos := (List.range numLParams).map RecursorUnivLevelPos.majorType;
let univLevelPos := if val.lparams.length == numLParams then univLevelPos else RecursorUnivLevelPos.motive :: univLevelPos;
let produceMotive := List.replicate val.nminors true;
let paramsPos := (List.range val.nparams).map some;
let indicesPos := (List.range val.nindices).map (fun pos => val.nparams + pos);
let numArgs := val.nindices + val.nparams + val.nminors + val.nmotives + 1;
pure {
recursorName := declName,
typeName := val.getInduct,
univLevelPos := univLevelPos,
majorPos := val.getMajorIdx,
depElim := true,
recursive := ival.isRec,
produceMotive := produceMotive,
paramsPos := paramsPos,
indicesPos := indicesPos,
numArgs := numArgs
}
private def getMajorPosIfAuxRecursor? (declName : Name) (majorPos? : Option Nat) : MetaM (Option Nat) :=
if majorPos?.isSome then pure majorPos?
@ -112,10 +110,8 @@ else do
if s != recOnSuffix && s != casesOnSuffix && s != brecOnSuffix then
pure none
else do
recInfo ← getConstInfo (mkRecFor p);
match recInfo with
| ConstantInfo.recInfo val => pure (some (val.nparams + val.nindices + (if s == casesOnSuffix then 1 else val.nmotives)))
| _ => throwError "unexpected recursor information"
val ← getConstInfoRec (mkRecFor p);
pure $ some (val.nparams + val.nindices + (if s == casesOnSuffix then 1 else val.nmotives))
| _ => pure none
private def checkMotive (declName : Name) (motive : Expr) (motiveArgs : Array Expr) : MetaM Unit :=

View file

@ -16,16 +16,12 @@ private def throwInductiveTypeExpected {α} (type : Expr) : MetaM α := do
throwError ("failed to compile pattern matching, inductive type expected" ++ indentExpr type)
def getInductiveUniverseAndParams (type : Expr) : MetaM (List Level × Array Expr) := do
env ← getEnv;
type ← whnfD type;
matchConst env type.getAppFn (fun _ => throwInductiveTypeExpected type) fun info us =>
match info with
| ConstantInfo.inductInfo val =>
let I := type.getAppFn;
let Iargs := type.getAppArgs;
let params := Iargs.extract 0 val.nparams;
pure (us, params)
| _ => throwInductiveTypeExpected type
matchConstInduct type.getAppFn (fun _ => throwInductiveTypeExpected type) fun val us =>
let I := type.getAppFn;
let Iargs := type.getAppArgs;
let params := Iargs.extract 0 val.nparams;
pure (us, params)
private def mkEqAndProof (lhs rhs : Expr) : MetaM (Expr × Expr) := do
lhsType ← inferType lhs;
@ -76,44 +72,40 @@ def generalizeIndices (mvarId : MVarId) (fvarId : FVarId) : MetaM GeneralizeIndi
withMVarContext mvarId $ do
lctx ← getLCtx;
localInsts ← getLocalInstances;
env ← getEnv;
checkNotAssigned mvarId `generalizeIndices;
fvarDecl ← getLocalDecl fvarId;
type ← whnf fvarDecl.type;
type.withApp $ fun f args => matchConst env f (fun _ => throwTacticEx `generalizeIndices mvarId "inductive type expected") $
fun cinfo _ => match cinfo with
| ConstantInfo.inductInfo val => do
unless (val.nindices > 0) $ throwTacticEx `generalizeIndices mvarId "indexed inductive type expected";
unless (args.size == val.nindices + val.nparams) $ throwTacticEx `generalizeIndices mvarId "ill-formed inductive datatype";
let indices := args.extract (args.size - val.nindices) args.size;
let IA := mkAppN f (args.extract 0 val.nparams); -- `I A`
IAType ← inferType IA;
forallTelescopeReducing IAType $ fun newIndices _ => do
let newType := mkAppN IA newIndices;
withLocalDeclD fvarDecl.userName newType $ fun h' =>
withNewIndexEqs indices newIndices $ fun newEqs newRefls => do
(newEqType, newRefl) ← mkEqAndProof fvarDecl.toExpr h';
let newRefls := newRefls.push newRefl;
withLocalDeclD `h newEqType $ fun newEq => do
let newEqs := newEqs.push newEq;
/- auxType `forall (j' : J) (h' : I A j'), j == j' -> h == h' -> target -/
target ← getMVarType mvarId;
tag ← getMVarTag mvarId;
auxType ← mkForallFVars newEqs target;
auxType ← mkForallFVars #[h'] auxType;
auxType ← mkForallFVars newIndices auxType;
newMVar ← mkFreshExprMVarAt lctx localInsts auxType MetavarKind.syntheticOpaque tag;
/- assign mvarId := newMVar indices h refls -/
assignExprMVar mvarId (mkAppN (mkApp (mkAppN newMVar indices) fvarDecl.toExpr) newRefls);
(indicesFVarIds, newMVarId) ← introN newMVar.mvarId! newIndices.size [] false;
(fvarId, newMVarId) ← intro1 newMVarId false;
pure {
mvarId := newMVarId,
indicesFVarIds := indicesFVarIds,
fvarId := fvarId,
numEqs := newEqs.size
}
| _ => throwTacticEx `generalizeIndices mvarId "inductive type expected"
type.withApp fun f args => matchConstInduct f (fun _ => throwTacticEx `generalizeIndices mvarId "inductive type expected") fun val _ => do
unless (val.nindices > 0) $ throwTacticEx `generalizeIndices mvarId "indexed inductive type expected";
unless (args.size == val.nindices + val.nparams) $ throwTacticEx `generalizeIndices mvarId "ill-formed inductive datatype";
let indices := args.extract (args.size - val.nindices) args.size;
let IA := mkAppN f (args.extract 0 val.nparams); -- `I A`
IAType ← inferType IA;
forallTelescopeReducing IAType $ fun newIndices _ => do
let newType := mkAppN IA newIndices;
withLocalDeclD fvarDecl.userName newType $ fun h' =>
withNewIndexEqs indices newIndices $ fun newEqs newRefls => do
(newEqType, newRefl) ← mkEqAndProof fvarDecl.toExpr h';
let newRefls := newRefls.push newRefl;
withLocalDeclD `h newEqType $ fun newEq => do
let newEqs := newEqs.push newEq;
/- auxType `forall (j' : J) (h' : I A j'), j == j' -> h == h' -> target -/
target ← getMVarType mvarId;
tag ← getMVarTag mvarId;
auxType ← mkForallFVars newEqs target;
auxType ← mkForallFVars #[h'] auxType;
auxType ← mkForallFVars newIndices auxType;
newMVar ← mkFreshExprMVarAt lctx localInsts auxType MetavarKind.syntheticOpaque tag;
/- assign mvarId := newMVar indices h refls -/
assignExprMVar mvarId (mkAppN (mkApp (mkAppN newMVar indices) fvarDecl.toExpr) newRefls);
(indicesFVarIds, newMVarId) ← introN newMVar.mvarId! newIndices.size [] false;
(fvarId, newMVarId) ← intro1 newMVarId false;
pure {
mvarId := newMVarId,
indicesFVarIds := indicesFVarIds,
fvarId := fvarId,
numEqs := newEqs.size
}
structure CasesSubgoal extends InductionSubgoal :=
(ctorName : Name)
@ -135,12 +127,11 @@ if !env.contains `Eq || !env.contains `HEq then pure none
else do
majorDecl ← getLocalDecl majorFVarId;
majorType ← whnf majorDecl.type;
majorType.withApp $ fun f args => matchConst env f (fun _ => pure none) $ fun cinfo _ => do
match cinfo with
| ConstantInfo.inductInfo ival =>
if args.size != ival.nindices + ival.nparams then pure none
else match env.find? (mkNameStr ival.name "casesOn") with
| ConstantInfo.defnInfo cval => pure $ some {
majorType.withApp fun f args => matchConstInduct f (fun _ => pure none) fun ival _ =>
if args.size != ival.nindices + ival.nparams then pure none
else match env.find? (mkNameStr ival.name "casesOn") with
| ConstantInfo.defnInfo cval =>
pure $ some {
inductiveVal := ival,
casesOnVal := cval,
majorDecl := majorDecl,
@ -148,7 +139,6 @@ else do
majorTypeArgs := args
}
| _ => pure none
| _ => pure none
/-
We say the major premise has independent indices IF

View file

@ -149,20 +149,14 @@ whnfRef.set whnfImpl
/- Given an expression `e`, compute its WHNF and if the result is a constructor, return field #i. -/
def reduceProj? (e : Expr) (i : Nat) : MetaM (Option Expr) := do
env ← getEnv;
e ← whnf e;
match e.getAppFn with
| Expr.const name _ _ =>
match env.find? name with
| some (ConstantInfo.ctorInfo ctorVal) =>
let numArgs := e.getAppNumArgs;
let idx := ctorVal.nparams + i;
if idx < numArgs then
pure (some (e.getArg! idx))
else
pure none
| _ => pure none
| _ => pure none
matchConstCtor e.getAppFn (fun _ => pure none) fun ctorVal _ =>
let numArgs := e.getAppNumArgs;
let idx := ctorVal.nparams + i;
if idx < numArgs then
pure (some (e.getArg! idx))
else
pure none
@[specialize] partial def whnfHeadPredAux (pred : Expr → MetaM Bool) : Expr → MetaM Expr
| e => Lean.WHNF.whnfEasyCases getLocalDecl getExprMVarAssignment? e $ fun e => do
@ -175,7 +169,6 @@ match e.getAppFn with
| none => pure e)
(pure e)
@[inline] def whnfHeadPred (e : Expr) (pred : Expr → MetaM Bool) : m Expr :=
liftMetaM $ whnfHeadPredAux pred e

View file

@ -26,6 +26,33 @@ variables {m : Type → Type} [MonadEnv m]
def setEnv (env : Environment) : m Unit :=
modifyEnv fun _ => env
@[inline] def matchConst [Monad m] {α : Type} (e : Expr) (failK : Unit → m α) (k : ConstantInfo → List Level → m α) : m α := do
match e with
| Expr.const constName us _ => do
env ← getEnv;
match env.find? constName with
| some cinfo => k cinfo us
| none => failK ()
| _ => failK ()
@[inline] def matchConstInduct [Monad m] {α : Type} (e : Expr) (failK : Unit → m α) (k : InductiveVal → List Level → m α) : m α :=
matchConst e failK fun cinfo us =>
match cinfo with
| ConstantInfo.inductInfo val => k val us
| _ => failK ()
@[inline] def matchConstCtor [Monad m] {α : Type} (e : Expr) (failK : Unit → m α) (k : ConstructorVal → List Level → m α) : m α :=
matchConst e failK fun cinfo us =>
match cinfo with
| ConstantInfo.ctorInfo val => k val us
| _ => failK ()
@[inline] def matchConstRec [Monad m] {α : Type} (e : Expr) (failK : Unit → m α) (k : RecursorVal → List Level → m α) : m α :=
matchConst e failK fun cinfo us =>
match cinfo with
| ConstantInfo.recInfo val => k val us
| _ => failK ()
section
variables [Monad m] [MonadError m]
@ -35,6 +62,35 @@ match env.find? constName with
| some info => pure info
| none => throwError ("unknown constant '" ++ constName ++ "'")
def getConstInfoInduct (constName : Name) : m InductiveVal := do
info ← getConstInfo constName;
match info with
| ConstantInfo.inductInfo v => pure v
| _ => throwError ("'" ++ constName ++ "' is not a inductive type")
def getConstInfoCtor (constName : Name) : m ConstructorVal := do
info ← getConstInfo constName;
match info with
| ConstantInfo.ctorInfo v => pure v
| _ => throwError ("'" ++ constName ++ "' is not a constructor")
def getConstInfoRec (constName : Name) : m RecursorVal := do
info ← getConstInfo constName;
match info with
| ConstantInfo.recInfo v => pure v
| _ => throwError ("'" ++ constName ++ "' is not a recursor")
@[inline] def matchConstStruct {α : Type} (e : Expr) (failK : Unit → m α) (k : InductiveVal → List Level → ConstructorVal → m α) : m α :=
matchConstInduct e failK fun ival us =>
if ival.isRec then failK ()
else match ival.ctors with
| [ctor] => do
ctorInfo ← getConstInfo ctor;
match ctorInfo with
| ConstantInfo.ctorInfo cval => k ival us cval
| _ => failK ()
| _ => failK ()
def addDecl [MonadOptions m] (decl : Declaration) : m Unit := do
env ← getEnv;
match env.addDecl decl with