Pantograph/pantograph/expr.py

89 lines
2.1 KiB
Python
Raw Normal View History

2024-04-22 13:00:06 -07:00
"""
2024-05-31 19:00:59 -07:00
Data structuers for expressions and goals
2024-04-22 13:00:06 -07:00
"""
from dataclasses import dataclass
2024-05-21 22:15:45 -07:00
from typing import Optional, Union
2024-04-22 13:00:06 -07:00
Expr = str
def parse_expr(payload: dict) -> Expr:
return payload["pp"]
@dataclass(frozen=True)
class Variable:
t: Expr
v: Optional[Expr] = None
name: Optional[str] = None
@staticmethod
2024-05-21 22:15:45 -07:00
def parse(payload: dict):
2024-04-22 13:00:06 -07:00
name = payload.get("userName")
t = parse_expr(payload["type"])
v = payload.get("value")
if v:
v = parse_expr(v)
return Variable(t, v, name)
def __str__(self):
result = self.name if self.name else "_"
result += f" : {self.t}"
if self.v:
result += f" := {self.v}"
2024-04-22 13:00:06 -07:00
return result
@dataclass(frozen=True)
class Goal:
2024-05-31 19:00:59 -07:00
variables: list[Variable]
2024-04-22 13:00:06 -07:00
target: Expr
name: Optional[str] = None
is_conversion: bool = False
2024-04-22 13:00:06 -07:00
@staticmethod
2024-05-21 22:15:45 -07:00
def sentence(target: Expr):
2024-04-22 13:00:06 -07:00
return Goal(variables=[], target=target)
@staticmethod
2024-05-31 19:00:59 -07:00
def parse(payload: dict):
2024-04-22 13:00:06 -07:00
name = payload.get("userName")
2024-04-22 22:38:20 -07:00
variables = [Variable.parse(v) for v in payload["vars"]]
2024-04-22 13:00:06 -07:00
target = parse_expr(payload["target"])
2024-05-31 19:00:59 -07:00
is_conversion = payload["isConversion"]
return Goal(variables, target, name, is_conversion)
2024-04-22 13:00:06 -07:00
def __str__(self):
front = "|" if self.is_conversion else ""
2024-05-31 19:00:59 -07:00
return "\n".join(str(v) for v in self.variables) + \
f"\n{front} {self.target}"
2024-04-22 13:00:06 -07:00
@dataclass(frozen=True)
class GoalState:
state_id: int
2024-05-31 19:00:59 -07:00
goals: list[Goal]
2024-04-22 13:00:06 -07:00
2024-05-17 19:52:00 -07:00
_sentinel: list[int]
def __del__(self):
self._sentinel.append(self.state_id)
2024-04-22 13:00:06 -07:00
@property
def is_solved(self) -> bool:
2024-04-22 22:38:20 -07:00
"""
WARNING: Does not handle dormant goals.
"""
2024-04-22 13:00:06 -07:00
return not self.goals
2024-04-22 13:11:28 -07:00
2024-04-22 22:38:20 -07:00
@staticmethod
2024-05-21 22:15:45 -07:00
def parse(payload: dict, _sentinel: list[int]):
2024-04-22 22:38:20 -07:00
state_id = payload["nextStateId"]
goals = [Goal.parse(g) for g in payload["goals"]]
2024-05-17 19:52:00 -07:00
return GoalState(state_id, goals, _sentinel)
2024-04-26 19:09:26 -07:00
2024-04-22 13:11:28 -07:00
@dataclass(frozen=True)
class TacticHave:
branch: str
2024-04-22 22:38:20 -07:00
@dataclass(frozen=True)
class TacticCalc:
step: str
2024-04-22 13:11:28 -07:00
2024-04-22 22:38:20 -07:00
Tactic = Union[str, TacticHave, TacticCalc]