Skip to content

Instantly share code, notes, and snippets.

@TheArcherST
Last active December 20, 2022 21:25
Show Gist options
  • Save TheArcherST/3dc9688cc9af2f45c97f333295ecd5a1 to your computer and use it in GitHub Desktop.
Save TheArcherST/3dc9688cc9af2f45c97f333295ecd5a1 to your computer and use it in GitHub Desktop.
from typing import Any
from dataclasses import dataclass
class FunctionType:
const = 'const'
call = 'call'
@dataclass
class FunctionSpec:
name: str
type: str
body: Any
class Function:
def __init__(self, spec: FunctionSpec):
self.spec = spec
def __call__(self, *args):
if self.spec.type == FunctionType.const:
return self.spec.body
elif self.spec.type == FunctionType.call:
obj, *other = args
return getattr(obj, self.spec.body).__call__(*other)
else:
raise ValueError(f"Bad function type `{self.spec.type}`")
class FunctionsFactory:
""" Builds functions by provided specs """
def __init__(self, spec: list[FunctionSpec]):
self._spec = spec
self._functions: dict[str, Function] = dict()
self._generate()
def _generate(self):
for i in self._spec:
self._functions.update({i.name: Function(i)})
def __getattr__(self, item) -> Function:
if item in self._functions:
return self._functions[item]
else:
return self.__getattribute__(item)
def main():
commands = [
{'name': 'zero', 'type': 'const', 'body': 0},
{'name': 'one', 'type': 'const', 'body': 1},
{'name': 'two', 'type': 'const', 'body': 2},
{'name': 'three', 'type': 'const', 'body': 3},
{'name': 'four', 'type': 'const', 'body': 4},
{'name': 'five', 'type': 'const', 'body': 5},
{'name': 'six', 'type': 'const', 'body': 6},
{'name': 'seven', 'type': 'const', 'body': 7},
{'name': 'eight', 'type': 'const', 'body': 8},
{'name': 'nine', 'type': 'const', 'body': 9},
{'name': 'add', 'type': 'call', 'body': '__add__'},
{'name': 'mul', 'type': 'call', 'body': '__mul__'},
{'name': 'sub', 'type': 'call', 'body': '__sub__'},
{'name': 'div', 'type': 'call', 'body': '__truediv__'},
]
factory = FunctionsFactory([FunctionSpec(**data) for data in commands])
f = factory
print(
f.mul(f.add(f.one(), f.two()), f.two()) # 6
)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment