| from pantograph.message import Severity, Message |
| from pantograph.expr import GoalState |
|
|
| from typing import Optional, Tuple |
| from dataclasses import dataclass, field |
| from enum import Enum |
|
|
| @dataclass(frozen=True) |
| class TacticInvocation: |
| """ |
| One tactic invocation with the before/after goals extracted from Lean source |
| code. |
| """ |
| before: str |
| after: str |
| tactic: str |
| used_constants: list[str] |
|
|
| @staticmethod |
| def parse(payload: dict): |
| return TacticInvocation( |
| before=payload["goalBefore"], |
| after=payload["goalAfter"], |
| tactic=payload["tactic"], |
| used_constants=payload.get('usedConstants', []), |
| ) |
|
|
| @dataclass(frozen=True) |
| class CompilationUnit: |
|
|
| |
| i_begin: int |
| i_end: int |
|
|
| messages: list[Message] = field(default_factory=lambda: []) |
|
|
| invocations: Optional[list[TacticInvocation]] = None |
| |
| goal_state: Optional[GoalState] = None |
| goal_src_boundaries: Optional[list[Tuple[int, int]]] = None |
|
|
| new_constants: Optional[list[str]] = None |
|
|
| @staticmethod |
| def parse(payload: dict, goal_state_sentinel=None, invocations=None): |
| i_begin = payload["boundary"][0] |
| i_end = payload["boundary"][1] |
| messages = [Message.parse(m) for m in payload["messages"]] |
|
|
| if invocations: |
| invocations = [ |
| TacticInvocation.parse(i) for i in invocations |
| ] |
| else: |
| invocations = None |
|
|
| if (state_id := payload.get("goalStateId")) is not None: |
| goal_state = GoalState.parse_inner(int(state_id), payload["goals"], [], goal_state_sentinel) |
| goal_src_boundaries = payload["goalSrcBoundaries"] |
| else: |
| goal_state = None |
| goal_src_boundaries = None |
|
|
| new_constants = payload.get("newConstants") |
|
|
| return CompilationUnit( |
| i_begin, |
| i_end, |
| messages, |
| invocations, |
| goal_state, |
| goal_src_boundaries, |
| new_constants |
| ) |
|
|
| @dataclass |
| class CheckTrackResult: |
|
|
| src_messages : list[Message] |
| dst_messages : list[Message] |
| failure : Optional[str] = None |
|
|
| @property |
| def hasSrcError(self): |
| return any(m.severity == Severity.ERROR for m in self.src_messages) |
| @property |
| def hasDstError(self): |
| return any(m.severity == Severity.ERROR for m in self.dst_messages) |
| @property |
| def succeeded(self): |
| return not self.hasSrcError and not self.hasDstError and self.failure is None |
| @property |
| def feedback(self): |
| """ |
| Feedback based on the dst |
| """ |
| result = [str(s) for s in self.dst_messages] |
| if self.failure: |
| result.append(self.failure) |
| return result |
|
|
| @dataclass(frozen=True) |
| class SearchTarget: |
| goal_state: GoalState |
|
|
| @staticmethod |
| def parse(payload: dict, goal_state_sentinel=None): |
| state_id = payload.get("stateId") |
| goal_state = GoalState.parse_inner(int(state_id), payload["goals"], [], goal_state_sentinel) |
|
|
| return SearchTarget( |
| goal_state, |
| ) |
|
|