Source code for fosf.syntax.base

#!/usr/bin/env python3

from __future__ import annotations

from typing import ClassVar


[docs] class Tag(str): """ Represent a tag symbol in an OSF term or OSF clause. :class:`Tag` is a string subclass used to distinguish tags from regular strings. It is hashable and comparable. Equality is based on both the type and the string value. """ def __repr__(self): return f"Tag({super().__repr__()})" def __hash__(self) -> int: return hash(("Tag", super().__hash__())) def __eq__(self, other: Tag) -> bool: return isinstance(other, Tag) and super().__eq__(other)
[docs] class Feature(str): """ Represent a feature symbol in an OSF term or OSF clause. :class:`Feature` is a string subclass used to distinguish features from regular strings. It is hashable and comparable. Equality is based on both the type and the string value. """ def __repr__(self): return f"Feature({super().__repr__()})" def __hash__(self) -> int: return hash(("Feature", super().__hash__())) def __eq__(self, other: Feature) -> bool: return isinstance(other, Feature) and super().__eq__(other)
[docs] class Sort: """ Represent a single sort, a named element of a sort taxonomy. :class:`Sort` objects are hashable and comparable. Equality is based on both the type and the string value. """ def __init__(self, value: str | Sort): """ Parameters ---------- value : str or Sort The name of the sort, or an existing :class:`Sort` instance. If initialized from another `Sort`, the `.value` attribute is used. Disjunctive sorts (e.g., :class:`DisjunctiveSort`, :class:`FrozenDisjunctiveSort`) are not allowed. Attributes ---------- value : str The name of the sort. Raises ------ TypeError If `value` is not a string or a `Sort` instance. """ if isinstance(value, Sort) and not isinstance(value, (DisjunctiveSort, FrozenDisjunctiveSort)): value = value.value elif not isinstance(value, str): raise TypeError( f"Sort must be initialized with a str or Sort, got {type(value).__name__}") self.value: str = value def __str__(self): return self.value def __repr__(self): return f"Sort({self.value!r})" def __hash__(self): return hash(("Sort", self.value)) def __eq__(self, other): return isinstance(other, Sort) and self.value == other.value def __lt__(self, other): return self.value < other.value
[docs] class DisjunctiveSort(Sort): """ Represent a mutable disjunctive sort. A :class:`DisjunctiveSort` is set of individual :class:`Sort` objects and represents their union. It is mutable: sorts can be added after construction. A frozen variant can be obtained via the :meth:`freeze` method. """ __hash__: ClassVar[None] = None def __init__(self, *sorts: str | Sort): """ Parameters ---------- *sorts : str or Sort One or more sorts to initialize the disjunction. Attributes ---------- value : set[Sort] """ self.value: set[Sort] = set() self.add(*sorts)
[docs] def add(self, *sorts: str | Sort): "Add one or more sorts to the disjunction" for sort in sorts: if isinstance(sort, Sort): self.value.add(sort) else: # TODO: check other types, e.g. str self.value.add(Sort(sort))
[docs] def freeze(self) -> FrozenDisjunctiveSort: "Return an immutable :class:`FrozenDisjunctiveSort` containing the same sorts." return FrozenDisjunctiveSort(*self.value)
def __str__(self): return f'{{ {", ".join(sorted(str(s) for s in self.value))} }}' def __repr__(self): return f"DisjunctiveSort({', '.join(sorted(repr(s) for s in self.value))})" def __eq__(self, other): return isinstance(other, DisjunctiveSort) and self.value == other.value def __iter__(self): return iter(self.value) def __len__(self): return len(self.value)
[docs] class FrozenDisjunctiveSort(Sort): """ Represent an immutable disjunctive sort. A :class:`FrozenDisjunctiveSort` contains a fixed set of `Sort` objects representing their union. Unlike `DisjunctiveSort`, this class is immutable and hashable. The mutable variant can be obtained via the :meth:`thaw` method. """ def __init__(self, *sorts: str | Sort): """ Parameters ---------- *sorts : str or Sort One or more sorts to initialize the frozen disjunction. Attributes ---------- value : frozenset[Sort] """ self.value: frozenset[Sort] = frozenset(Sort(sort) for sort in sorts) self._hash: int | None = None
[docs] def thaw(self) -> DisjunctiveSort: "Return a mutable :class:`DisjunctiveSort` containing the same sorts." return DisjunctiveSort(*self.value)
def __str__(self): return f'{{ {", ".join(sorted(str(s) for s in self.value))} }}' def __repr__(self): return f"FrozenDisjunctiveSort({', '.join(sorted(repr(s) for s in self.value))})" def __hash__(self): if self._hash is None: self._hash = hash(("DisjunctiveSort", self.value)) return self._hash def __eq__(self, other): return isinstance(other, FrozenDisjunctiveSort) and self.value == other.value def __iter__(self): return iter(self.value) def __len__(self): return len(self.value)