@Kha It is too annoying to write `.val` all over the place. Moreover, we now have `match_syntax`.
160 lines
6.2 KiB
Text
160 lines
6.2 KiB
Text
/-
|
||
Copyright (c) 2020 Microsoft Corporation. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Leonardo de Moura, Sebastian Ullrich
|
||
-/
|
||
prelude
|
||
import Init.Lean.Util.CollectLevelParams
|
||
import Init.Lean.Elab.Definition
|
||
|
||
namespace Lean
|
||
namespace Elab
|
||
namespace Command
|
||
|
||
def expandOptDeclSig (stx : Syntax) : Syntax × Option Syntax :=
|
||
-- many Term.bracktedBinder >> Term.optType
|
||
let binders := stx.getArg 0;
|
||
let optType := stx.getArg 1; -- optional (parser! " : " >> termParser)
|
||
if optType.isNone then
|
||
(binders, none)
|
||
else
|
||
let typeSpec := optType.getArg 0;
|
||
(binders, some $ typeSpec.getArg 1)
|
||
|
||
def expandDeclSig (stx : Syntax) : Syntax × Syntax :=
|
||
-- many Term.bracktedBinder >> Term.typeSpec
|
||
let binders := stx.getArg 0;
|
||
let typeSpec := stx.getArg 1;
|
||
(binders, typeSpec.getArg 1)
|
||
|
||
def elabAbbrev (modifiers : Modifiers) (stx : Syntax) : CommandElabM Unit :=
|
||
-- parser! "abbrev " >> declId >> optDeclSig >> declVal
|
||
let (binders, type) := expandOptDeclSig (stx.getArg 2);
|
||
let modifiers := modifiers.addAttribute { name := `inline };
|
||
let modifiers := modifiers.addAttribute { name := `reducible };
|
||
elabDefLike {
|
||
ref := stx, kind := DefKind.def, modifiers := modifiers,
|
||
declId := stx.getArg 1, binders := binders, type? := type, val := stx.getArg 3
|
||
}
|
||
|
||
def elabDef (modifiers : Modifiers) (stx : Syntax) : CommandElabM Unit :=
|
||
-- parser! "def " >> declId >> optDeclSig >> declVal
|
||
let (binders, type) := expandOptDeclSig (stx.getArg 2);
|
||
elabDefLike {
|
||
ref := stx, kind := DefKind.def, modifiers := modifiers,
|
||
declId := stx.getArg 1, binders := binders, type? := type, val := stx.getArg 3
|
||
}
|
||
|
||
def elabTheorem (modifiers : Modifiers) (stx : Syntax) : CommandElabM Unit :=
|
||
-- parser! "theorem " >> declId >> declSig >> declVal
|
||
let (binders, type) := expandDeclSig (stx.getArg 2);
|
||
elabDefLike {
|
||
ref := stx, kind := DefKind.theorem, modifiers := modifiers,
|
||
declId := stx.getArg 1, binders := binders, type? := some type, val := stx.getArg 3
|
||
}
|
||
|
||
def elabConstant (modifiers : Modifiers) (stx : Syntax) : CommandElabM Unit := do
|
||
-- parser! "constant " >> declId >> declSig >> optional declValSimple
|
||
let (binders, type) := expandDeclSig (stx.getArg 2);
|
||
val ← match (stx.getArg 3).getOptional? with
|
||
| some val => pure val
|
||
| none => do {
|
||
val ← `(arbitrary _);
|
||
pure $ Syntax.node `Lean.Parser.Command.declValSimple #[ mkAtomFrom stx ":=", val ]
|
||
};
|
||
elabDefLike {
|
||
ref := stx, kind := DefKind.opaque, modifiers := modifiers,
|
||
declId := stx.getArg 1, binders := binders, type? := some type, val := val
|
||
}
|
||
|
||
def elabInstance (modifiers : Modifiers) (stx : Syntax) : CommandElabM Unit := do
|
||
-- parser! "instance " >> optional declId >> declSig >> declVal
|
||
let (binders, type) := expandDeclSig (stx.getArg 2);
|
||
let modifiers := modifiers.addAttribute { name := `instance };
|
||
declId ← match (stx.getArg 1).getOptional? with
|
||
| some declId => pure declId
|
||
| none => throwError stx "not implemented yet";
|
||
elabDefLike {
|
||
ref := stx, kind := DefKind.def, modifiers := modifiers,
|
||
declId := declId, binders := binders, type? := type, val := stx.getArg 3
|
||
}
|
||
|
||
def elabExample (modifiers : Modifiers) (stx : Syntax) : CommandElabM Unit :=
|
||
-- parser! "example " >> declSig >> declVal
|
||
let (binders, type) := expandDeclSig (stx.getArg 1);
|
||
let id := mkIdentFrom stx `_example;
|
||
let declId := Syntax.node `Lean.Parser.Command.declId #[id, mkNullNode];
|
||
elabDefLike {
|
||
ref := stx, kind := DefKind.example, modifiers := modifiers,
|
||
declId := declId, binders := binders, type? := some type, val := stx.getArg 2
|
||
}
|
||
|
||
def elabAxiom (modifiers : Modifiers) (stx : Syntax) : CommandElabM Unit :=
|
||
-- parser! "axiom " >> declId >> declSig
|
||
let declId := stx.getArg 1;
|
||
let (binders, typeStx) := expandDeclSig (stx.getArg 2);
|
||
withDeclId declId $ fun name => do
|
||
declName ← mkDeclName modifiers name;
|
||
applyAttributes stx declName modifiers.attrs AttributeApplicationTime.beforeElaboration;
|
||
explictLevelNames ← getLevelNames;
|
||
decl ← runTermElabM declName $ fun vars => Term.elabBinders binders.getArgs $ fun xs => do {
|
||
type ← Term.elabType typeStx;
|
||
Term.synthesizeSyntheticMVars false;
|
||
type ← Term.instantiateMVars typeStx type;
|
||
type ← Term.mkForall typeStx xs type;
|
||
(type, _) ← Term.mkForallUsedOnly typeStx vars type;
|
||
type ← Term.levelMVarToParam type;
|
||
let usedParams := (collectLevelParams {} type).params;
|
||
let levelParams := sortDeclLevelParams explictLevelNames usedParams;
|
||
pure $ Declaration.axiomDecl {
|
||
name := declName,
|
||
lparams := levelParams,
|
||
type := type,
|
||
isUnsafe := modifiers.isUnsafe
|
||
}
|
||
};
|
||
addDecl stx decl;
|
||
applyAttributes stx declName modifiers.attrs AttributeApplicationTime.afterTypeChecking;
|
||
applyAttributes stx declName modifiers.attrs AttributeApplicationTime.afterCompilation
|
||
|
||
def elabInductive (modifiers : Modifiers) (stx : Syntax) : CommandElabM Unit :=
|
||
pure () -- TODO
|
||
|
||
def elabClassInductive (modifiers : Modifiers) (stx : Syntax) : CommandElabM Unit :=
|
||
pure () -- TODO
|
||
|
||
def elabStructure (modifiers : Modifiers) (stx : Syntax) : CommandElabM Unit :=
|
||
pure () -- TODO
|
||
|
||
@[builtinCommandElab declaration]
|
||
def elabDeclaration : CommandElab :=
|
||
fun stx => do
|
||
modifiers ← elabModifiers (stx.getArg 0);
|
||
let decl := stx.getArg 1;
|
||
let declKind := decl.getKind;
|
||
if declKind == `Lean.Parser.Command.abbrev then
|
||
elabAbbrev modifiers decl
|
||
else if declKind == `Lean.Parser.Command.def then
|
||
elabDef modifiers decl
|
||
else if declKind == `Lean.Parser.Command.theorem then
|
||
elabTheorem modifiers decl
|
||
else if declKind == `Lean.Parser.Command.constant then
|
||
elabConstant modifiers decl
|
||
else if declKind == `Lean.Parser.Command.instance then
|
||
elabInstance modifiers decl
|
||
else if declKind == `Lean.Parser.Command.axiom then
|
||
elabAxiom modifiers decl
|
||
else if declKind == `Lean.Parser.Command.example then
|
||
elabExample modifiers decl
|
||
else if declKind == `Lean.Parser.Command.inductive then
|
||
elabInductive modifiers decl
|
||
else if declKind == `Lean.Parser.Command.classInductive then
|
||
elabClassInductive modifiers decl
|
||
else if declKind == `Lean.Parser.Command.structure then
|
||
elabStructure modifiers decl
|
||
else
|
||
throwError stx "unexpected declaration"
|
||
|
||
end Command
|
||
end Elab
|
||
end Lean
|