# 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__(cls) 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.future 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}'