|
| 1 | +import LogicFormalization.Chapter2.Section3.Defs |
| 2 | + |
| 3 | +namespace Language.Automation |
| 4 | + |
| 5 | +open Lean Elab Elab.Command |
| 6 | + |
| 7 | +syntax inv := "⁻¹" |
| 8 | +syntax mul := "⬝" |
| 9 | +syntax neg := "-" |
| 10 | +syntax add := "+" |
| 11 | +/-- The syntax for function symbols. Currently |
| 12 | +`0`, `1`, `⁻¹`, `⬝`, `-`, and `+`.-/ |
| 13 | +syntax funs := num <|> inv <|> mul <|> neg <|> add |
| 14 | + |
| 15 | +syntax lt := "<" |
| 16 | +/-- The syntax for relation symbols. Currently just `<`. -/ |
| 17 | +syntax rels := lt |
| 18 | + |
| 19 | +def symbolNameAndArity (s: Syntax): CommandElabM (Name × ℕ) := |
| 20 | + let arg := s.getArg 0 |
| 21 | + match arg.getKind with |
| 22 | + | ``inv => pure (`inv, 1) |
| 23 | + | ``mul => pure (`mul, 2) |
| 24 | + | ``neg => pure (`neg, 1) |
| 25 | + | ``add => pure (`add, 2) |
| 26 | + | ``lt => pure (`lt, 2) |
| 27 | + | `num => |
| 28 | + match arg.toNat with |
| 29 | + | 0 => pure (`zero, 0) |
| 30 | + | 1 => pure (`one, 0) |
| 31 | + | n => throw (.error s |
| 32 | + s!"Only numeric literals `0` and `1` \ |
| 33 | + are supported, but `{n}` was passed in") |
| 34 | + | _ => throw (.error s s!"Received an invalid symbol") |
| 35 | + |
| 36 | +def mkInductiveEnum (typeName: Name) (elemNames: Array Name): Declaration := |
| 37 | + dbg_trace elemNames |
| 38 | + let ctors := elemNames.toList.map fun name => |
| 39 | + { name := typeName ++ name, type := .const typeName [] } |
| 40 | + let it := |
| 41 | + { name := typeName, type := .sort 1, ctors } |
| 42 | + .inductDecl [] 0 [it] false |
| 43 | + |
| 44 | +set_option hygiene false in |
| 45 | +elab "#declare_language" lang:ident "{" symbols:(funs<|>rels),* "}" : command => do |
| 46 | + |
| 47 | + let (fs, rs) := symbols.getElems.partition (·.raw.isOfKind ``funs) |
| 48 | + let fNamesAndArities ← Array.unzip <$> fs.mapM symbolNameAndArity |
| 49 | + let rNamesAndArities ← Array.unzip <$> rs.mapM symbolNameAndArity |
| 50 | + |
| 51 | + dbg_trace fNamesAndArities |
| 52 | + -- declare the inductive types |
| 53 | + let ϝ := lang.getId ++ `ϝ |
| 54 | + let ρ := lang.getId ++ `ρ |
| 55 | + let fDecl := mkInductiveEnum ϝ fNamesAndArities.fst |
| 56 | + |
| 57 | + let rDecl := mkInductiveEnum ρ rNamesAndArities.fst |
| 58 | + liftCoreM (addAndCompile fDecl *> addAndCompile rDecl) |
| 59 | + -- from `mkAuxConstructions` (private) in `MutualInductive.lean` |
| 60 | + for fn in [mkRecOn, mkCasesOn, mkNoConfusion, mkBelow, mkIBelow, mkBRecOn, mkBInductionOn] do |
| 61 | + liftTermElabM (fn ϝ *> fn ρ) |
| 62 | + |
| 63 | + -- derive instances |
| 64 | + elabCommand <| ←`( |
| 65 | + namespace $lang |
| 66 | + deriving instance Repr, DecidableEq for $(mkIdent ϝ), $(mkIdent ρ) |
| 67 | + |
| 68 | + |
| 69 | + end $lang |
| 70 | + ) |
| 71 | + |
| 72 | +-- namespace OAb |
| 73 | +-- #print OAb.ϝ |
| 74 | +-- instance: Arity OAb.ϝ where |
| 75 | +-- arity x := match x with | .one => 0 |
| 76 | +-- end OAb |
| 77 | + |
| 78 | + |
| 79 | +-- #check ϝ |
| 80 | +-- #print Nat |
| 81 | +-- #print OAb.ϝ.rec |
| 82 | + |
| 83 | +-- open Lean Elab Command in |
| 84 | +-- elab "#my_cmd" : command => do |
| 85 | +-- let name := `abcde |
| 86 | +-- let ctors := [{ name, type := .sort 1, ctors := [⟨name ++ `zero, .const name []⟩] }] |
| 87 | +-- let fDecl := .inductDecl [] 0 ctors false |
| 88 | +-- liftCoreM (addAndCompile fDecl) |
| 89 | + |
| 90 | + |
| 91 | +open Lean.Parser.Command in |
| 92 | +def mkEnum {m: Type → Type} [Monad m] [MonadQuotation m] (typeName: Name) (elemNames: Array Name): m (TSyntax `Lean.Parser.Command.declaration) := do |
| 93 | + let emptyDeclModifiers ← `(declModifiers|) |
| 94 | + let emptyOptDeclSig ← `(optDeclSig|) |
| 95 | + let ctors: Array (TSyntax `Lean.Parser.Command.ctor) ← elemNames.mapM fun name => do |
| 96 | + have {α}: Coe Syntax (TSyntax α) := ⟨TSyntax.mk⟩ |
| 97 | + let ctor := mkNode `Lean.Parser.Command.ctor #[mkNullNode, mkAtom "|", emptyDeclModifiers, ←`($(mkIdent name)), emptyOptDeclSig] |
| 98 | + return ⟨ctor⟩ |
| 99 | + return ⟨ |
| 100 | + .node .none `Lean.Parser.Command.declaration #[ |
| 101 | + emptyDeclModifiers, |
| 102 | + .node .none `Lean.Parser.Command.inductive #[ |
| 103 | + mkAtom "inductive", |
| 104 | + ←`(declId| $(mkIdent typeName)), |
| 105 | + emptyOptDeclSig, |
| 106 | + mkNullNode, |
| 107 | + mkListNode ctors, |
| 108 | + mkNullNode, |
| 109 | + ←`(optDeriving|) |
| 110 | + ], |
| 111 | + ]⟩ |
| 112 | + |
| 113 | +open Lean Elab Command in |
| 114 | +elab "#my_cmd" : command => do |
| 115 | + let name := `abcde |
| 116 | + let stx ← mkEnum name #[`a, `b, `c] |
| 117 | + let stx' ← `(inductive abcde | a | b | c) |
| 118 | + dbg_trace "{stx}\n\n{stx'} {stx.raw == stx'}" |
| 119 | + elabCommand <| stx |
| 120 | + -- let ctors := [{ name, type := .sort 1, ctors := [ |
| 121 | + -- ⟨name ++ `zero, .const name []⟩, |
| 122 | + -- ⟨name ++ `one , .const name []⟩] }] |
| 123 | + -- let fDecl := .inductDecl [] 0 ctors false |
| 124 | + -- let preDef: PreDefinition := { |
| 125 | + -- ref := mkIdent name |
| 126 | + -- kind := sorry |
| 127 | + -- levelParams := sorry |
| 128 | + -- modifiers := sorry |
| 129 | + -- declName := sorry |
| 130 | + -- type := sorry |
| 131 | + -- value := sorry |
| 132 | + -- termination := sorry |
| 133 | + -- } |
| 134 | + -- liftCoreM (addAndCompile fDecl) |
| 135 | +#my_cmd |
| 136 | + |
| 137 | +#check compileDecls |
| 138 | + |
| 139 | +#check addAndCompileNonRec |
| 140 | + |
| 141 | +-- deriving instance BEq, DecidableEq for abcde |
0 commit comments