builtup4/bu4/linking/constructs/llambda.py

75 lines
2.7 KiB
Python

# Copyright (c) PARRRATE T&V 2021. All rights reserved.
from bu4.evaluation.constructs.eattachable import EAttachable
from bu4.evaluation.constructs.edelayed import EDelayed
from bu4.evaluation.constructs.evaluable import Evaluable
from bu4.indexing.constructs.idelayed import IDelayed
from bu4.indexing.constructs.ilambda import ILambda
from bu4.indexing.constructs.indexed import Indexed
from bu4.linking.constructs.ldelayed import LDelayed
from bu4.linking.constructs.linked import Linked
from bu4.linking.evaluation.ellambda import ELLambda
from bu4.linking.evaluation.elvtype import elvtype
from bu4.transform.states.aftertransform import AfterTransform
from bu4.transform.states.transformfinished import TransformFinished
from bu4.transform.states.transformstart import TransformStart
from bu4.transform.states.transformstate import TransformState
from bu4.transform.targets.atlambda import ATLambda
__all__ = ('LLambda',)
class LLambda(Linked):
value: Linked
def __new__(cls, name: bytes, value: Linked):
return Linked.__new__(LLambda) if name in value.future else LDelayed(value)
def __init__(self, name: bytes, value: Linked):
self.name = name
self.value = value
self.used = name in value.future
self.memoize = name in value.multifuture
self.future = self.value.future - {name}
self.multifuture = self.future if self.used else self.value.multifuture
def attach(self, env: elvtype) -> Evaluable:
return (
ELLambda(
{name: env[name] for name in self.future} if self.used else env,
self.name,
self.value
)
if
self.used
else
EDelayed(EAttachable(
env,
self.value
))
)
def index(self, promise: list[bytes]) -> TransformState[Indexed]:
if not self.used:
return AfterTransform(
TransformStart(lambda: self.value.index(promise)),
ATLambda(
lambda value: TransformFinished(IDelayed(value))
)
)
else:
table = [i for i in range(len(promise)) if promise[i] in self.future]
return AfterTransform(
TransformStart(lambda: self.value.index([self.name] + [promise[i] for i in table])),
ATLambda(
lambda value: TransformFinished(ILambda(
value,
table,
memoize=self.memoize
))
)
)
def __str__(self):
return f'({self.name.decode()}){self.value}'