diff --git a/examples/Example/Example.lean b/examples/Example/Example.lean index 40cb3dc..9812c92 100644 --- a/examples/Example/Example.lean +++ b/examples/Example/Example.lean @@ -1,11 +1,12 @@ import Aesop --- Ensure that Aesop is running +/-- Ensure that Aesop is running -/ example : α → α := by aesop example : ∀ (p q: Prop), p ∨ q → q ∨ p := by intro p q h + -- Here are some comments cases h . apply Or.inr assumption diff --git a/examples/README.md b/examples/README.md index 8ccd495..706876d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -7,9 +7,12 @@ pushd Example lake build popd ``` -This would generate compiled `.olean` files. Then run the example from the +This would generate compiled `.olean` files. Then run one of the examples from the project root: ``` sh poetry run examples/aesop.py +poetry run examples/data.py ``` +Warning: If you make modifications to any Lean files, you must re-run `lake build`! + diff --git a/examples/compile-tactics.py b/examples/data.py similarity index 67% rename from examples/compile-tactics.py rename to examples/data.py index d4845da..bb1365b 100755 --- a/examples/compile-tactics.py +++ b/examples/data.py @@ -14,6 +14,10 @@ if __name__ == '__main__': print(f"$PWD: {project_path}") print(f"$LEAN_PATH: {lean_path}") server = Server(imports=['Example'], project_path=project_path, lean_path=lean_path) - data = server.compile_tactics("Example") - for (before, tactic, after) in data: - print(f"{before}\n{tactic}\n{after}\n\n") + units, invocations = server.compile_unit("Example") + for i, u in enumerate(units): + print(f"==== #{i} ====") + print(u) + print("==== Invocations ====") + for i in invocations: + print(f"{i.before}\n{i.tactic}\n{i.after}\n") diff --git a/pantograph/compiler.py b/pantograph/compiler.py new file mode 100644 index 0000000..f2f01bc --- /dev/null +++ b/pantograph/compiler.py @@ -0,0 +1,13 @@ +from dataclasses import dataclass + +@dataclass(frozen=True) +class TacticInvocation: + before: str + after: str + tactic: str + + @staticmethod + def parse(payload: dict): + return TacticInvocation(before=payload["goalBefore"], + after=payload["goalAfter"], + tactic=payload["tactic"]) diff --git a/pantograph/server.py b/pantograph/server.py index af8c7e3..a5d0940 100644 --- a/pantograph/server.py +++ b/pantograph/server.py @@ -5,6 +5,7 @@ interface. import json, pexpect, pathlib, unittest, os from pantograph.expr import parse_expr, Expr, Variable, Goal, GoalState, \ Tactic, TacticHave, TacticCalc +from pantograph.compiler import TacticInvocation def _get_proc_cwd(): return pathlib.Path(__file__).parent @@ -136,12 +137,22 @@ class Server: raise ServerError(result["parseError"]) return GoalState.parse(result, self.to_remove_goal_states) - - def compile_tactics(self, module: str) -> list[tuple[str, str, str]]: - result = self.run('compile.tactics', {'module': module}) + def compile_unit(self, module: str) -> tuple[list[str], list[TacticInvocation]]: + file_path = self.project_path / (module.replace('.', '/') + '.lean') + result = self.run('compile.unit', { + 'module': module, + 'compilationUnits': True, + 'invocations': True + }) if "error" in result: raise ServerError(result["desc"]) - return [(i['goalBefore'], i['tactic'], i['goalAfter']) for i in result['invocations']] + + with open(file_path, 'rb') as f: + content = f.read() + units = [content[begin:end].decode('utf-8') for begin,end in result['units']] + + invocations = [TacticInvocation.parse(i) for i in result['invocations']] + return units, invocations diff --git a/src b/src index b9b16ba..855e771 160000 --- a/src +++ b/src @@ -1 +1 @@ -Subproject commit b9b16ba0e9d99279837527bcb40176277d11e725 +Subproject commit 855e7716098667aff52e7374f6b911ba06a08578