123 lines
3.6 KiB
Python
123 lines
3.6 KiB
Python
"""
|
|
Base data and types for supporting Pyoo operations.
|
|
"""
|
|
|
|
from collections import namedtuple
|
|
from typing import Callable, List, Tuple, Type, Sequence, Union, Iterable, Protocol
|
|
|
|
|
|
PREPOSITIONS = (
|
|
"with/using",
|
|
"at/to",
|
|
# 'in front of',
|
|
"in/inside/into",
|
|
# 'on top of/on/onto/upon',
|
|
"on/onto/upon",
|
|
# 'out of/from inside/from',
|
|
"from",
|
|
"over",
|
|
"through",
|
|
"under/underneath/beneath",
|
|
"behind",
|
|
"beside",
|
|
"for/about",
|
|
"is",
|
|
"as",
|
|
"off",
|
|
)
|
|
"""`tuple[str]`: A list of preposition strings (equivilancies are / separated)"""
|
|
|
|
NORMALIZED_PREPS = tuple([x.split("/") for x in PREPOSITIONS])
|
|
"""A list of prepositions with equiviliants split."""
|
|
|
|
|
|
class PyooError(Exception):
|
|
"""Generic Pyoo error."""
|
|
|
|
|
|
class PyooVerbNotFound(PyooError):
|
|
"""Pyoo Error which indicates a verb was not found."""
|
|
|
|
|
|
class PyooObjectNotFound(PyooError):
|
|
"""Pyoo Error which indicates an object was not found."""
|
|
|
|
|
|
VerbCallFrame = namedtuple("VerbCallFrame", "environment,player,verbname,dobj,dobjstr,prepstr,iobj,iobjstr,argstr")
|
|
"""Namedtuple which contains the call frame (all arguments) for a verb call."""
|
|
|
|
|
|
class Verb:
|
|
"""This is a wrapper for a callable to give it the properties required for verbs."""
|
|
def __init__(self,
|
|
function: Callable,
|
|
names: List[str],
|
|
callspec: Tuple[str, List[str], str]):
|
|
self.function = function
|
|
self.name = names[0]
|
|
self.names = names
|
|
self.callspec = callspec
|
|
|
|
def __call__(self, *args, **kwargs) -> None:
|
|
return self.function(*args, **kwargs)
|
|
|
|
def __get__(self, obj, objtype: Type):
|
|
class VerbFunction:
|
|
def __init__(self, func: Callable, obj, typ: Type, verb: "Verb"):
|
|
self._func = func
|
|
self._obj = obj
|
|
self._typ = typ
|
|
self.is_verb = True
|
|
self.name = verb.name
|
|
self.names = verb.names
|
|
self.callspec = verb.callspec
|
|
|
|
def __call__(self, *args, **kwargs):
|
|
return self._func.__get__(self._obj, self._typ)(*args, **kwargs)
|
|
|
|
return VerbFunction(self.function, obj, objtype, self)
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<Verb {self.name} {self.callspec}>"
|
|
|
|
|
|
def make_verb(verbname: str, dobjspec: str, prepspec: str, iobjspec: str) -> Callable[..., Verb]:
|
|
"""This simple decorator adds verb metadata to a method or function.
|
|
|
|
Arguments:
|
|
verbname (str): List of verb names, comma separated, with wildcards.
|
|
dobjspec (str): 'this' or 'that' or 'none' or 'any'
|
|
(this = the object which defines the verb, that = an object in the soup, any = any string,
|
|
none = blank)
|
|
iobjspec (str): 'this' or 'that' or 'none' or 'any' (as above)
|
|
prepspec (str): one of prepositions strings (as in the PREPOSITIONS list)
|
|
"""
|
|
def verb_decorate(verbfunc: Callable[[VerbCallFrame, ], None]) -> Verb:
|
|
names = [x.strip() for x in verbname.split(",")]
|
|
ps: List[str] = []
|
|
if prepspec.find("/") > 0:
|
|
ps = prepspec.split("/")
|
|
else:
|
|
for prep in NORMALIZED_PREPS:
|
|
if prepspec in prep:
|
|
ps = prep
|
|
break
|
|
ps = [prepspec]
|
|
return Verb(verbfunc, names, (dobjspec, ps, iobjspec))
|
|
|
|
return verb_decorate
|
|
|
|
|
|
#
|
|
# type things
|
|
#
|
|
|
|
|
|
class InterpreterProtocol(Protocol):
|
|
"""Defines minimal protocol for interpreter objects."""
|
|
def update(self) -> None:
|
|
...
|
|
|
|
|
|
SingleMultiString = Union[Sequence[str], str, Iterable[str]]
|