Coverage for src/starlord/code_components.py: 72%
40 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-10-01 05:55 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2025-10-01 05:55 +0000
1from __future__ import annotations
3import re
4from dataclasses import dataclass
5from typing import Union
8class Symb(str):
10 def __new__(cls, source: str) -> Symb:
11 if re.fullmatch(r"[pcbla]\.[A-Za-z_]\w*", source) is not None:
12 return super().__new__(cls, source)
13 try:
14 value: float = float(source)
15 except ValueError:
16 raise ValueError(f'Could not interpret "{source}" as a symbol or literal.') from None
17 return super().__new__(cls, str(value))
19 @property
20 def name(self) -> str:
21 return self[2:]
23 @property
24 def label(self) -> str:
25 return self[0]
27 @property
28 def var(self) -> str:
29 return self.label + "_" + self.name
32@dataclass(frozen=True)
33class Component:
34 '''Represents a section of code for CodeGenerator.'''
35 requires: set[Symb]
36 provides: set[Symb]
37 code: str
39 def __repr__(self) -> str:
40 return f"ExprComponent({', '.join(self.requires)}) -> ({', '.join(self.provides)})"
42 def generate_code(self, name_map: Union[dict, None] = None) -> str:
43 if name_map is None:
44 return self.code
45 else:
46 return self.code.format_map(name_map)
49class AssignmentComponent(Component):
50 def __repr__(self) -> str:
51 return f"{list(self.requires)[0]} = {self.code}"
54class DistributionComponent(Component):
55 pass
58class InterpolateComponent(Component):
59 pass