()
| 13 | |
| 14 | |
| 15 | def main() -> None: |
| 16 | lake_dir = Path(__file__).resolve().parent.parent / "lean" |
| 17 | lib = LeanLibrary.from_lake(lake_dir, "PantographDemo", build=True) |
| 18 | |
| 19 | # ---- Init env ------------------------------------------------------- |
| 20 | k = Kernel(lib) |
| 21 | k.init_search("") |
| 22 | k.load(["Init"]) |
| 23 | print(f"environment loaded: {k.is_loaded()}, {k.decl_count()} decls") |
| 24 | |
| 25 | # ---- Goal state (do this first, before MetaM-heavy ops, to dodge |
| 26 | # the cumulative state churn issue documented in |
| 27 | # docs/ARCHITECTURE.md "GoalState lifecycle") ------------------------ |
| 28 | print("\n== Goal state — basic queries ==") |
| 29 | s = k.goal_create("∀ n : Nat, n + 0 = n") |
| 30 | print(f" n_goals: {s.n_goals()}") |
| 31 | print(f" main goal mvar: {s.main_goal_name()}") |
| 32 | print(f" is_solved: {s.is_solved()}") |
| 33 | |
| 34 | print("\n== Goal state — pretty (one shot) ==") |
| 35 | s = k.goal_create("∀ n : Nat, n + 0 = n") |
| 36 | pretty = s.pretty() |
| 37 | print(textwrap_indent(pretty, " ")) |
| 38 | |
| 39 | print("\n== Goal state — tactic (one shot) ==") |
| 40 | s = k.goal_create("∀ n : Nat, n + 0 = n") |
| 41 | res = s.try_tactic("intro n") |
| 42 | print(f" intro n -> status={res.status}") |
| 43 | if res.ok and res.state is not None: |
| 44 | # NB: querying res.state's heavy ops after try_tactic re-triggers |
| 45 | # the lifecycle issue, so we just print the new main-goal mvar |
| 46 | # name (a cheap field access). |
| 47 | print(f" new main goal mvar: {res.state.main_goal_name()}") |
| 48 | |
| 49 | # ---- Declaration introspection ------------------------------------- |
| 50 | print("\n== Decl introspection ==") |
| 51 | print(f" Nat.succ exists: {k.decl_exists('Nat.succ')}") |
| 52 | print(f" Nat.succ module: {k.module_of('Nat.succ')}") |
| 53 | print(f" Nat.succ type: {k.decl_type('Nat.succ')}") |
| 54 | |
| 55 | # ---- Elaboration --------------------------------------------------- |
| 56 | print("\n== Elaboration ==") |
| 57 | print(f" infer_type 'Nat.succ Nat.zero' = {k.infer_type('Nat.succ Nat.zero')}") |
| 58 | print(f" whnf '(fun x => x + 1) 4' = {k.whnf('(fun x => x + 1) 4')}") |
| 59 | print(f" parse_type 'Nat → Nat' = {k.parse_type('Nat → Nat')}") |
| 60 | print(f" decide '1 + 1 = 2' = {k.decide('1 + 1 = 2')}") |
| 61 | print(f" decide '3 < 2' = {k.decide('3 < 2')}") |
| 62 | |
| 63 | # ---- Frontend processing ------------------------------------------- |
| 64 | print("\n== Frontend processing ==") |
| 65 | process_out = k.process("def myExampleFn : Nat := 42\n") |
| 66 | new_consts = process_out.split("\n---\n")[0].split("\n") |
| 67 | print(f" process(def myExampleFn …): defined {new_consts}") |
| 68 | src_path = k.find_source_path("Init.Prelude") |
| 69 | print(f" find_source_path Init.Prelude: {src_path}") |
| 70 | state, msg = k.collect_sorrys("def f : Nat := 42\n") |
| 71 | print(f" collect_sorrys (no sorries): state={state}, msg={msg!r}") |
| 72 |
no test coverage detected