# Copyright (c) PARRRATE T&V 2021. All rights reserved. from bu4.evaluation.av.envtype import envtype from bu4.evaluation.constructs.edelayed import EDelayed from bu4.evaluation.constructs.elambda import ELambda 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.linked import Linked 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 __init__(self, name: bytes, value: Linked): self.name = name self.value = value self.future = self.value.future - {name} self.multifuture = self.future self.used = name in value.future self.memoize = name in value.multifuture def attach(self, env: envtype) -> Evaluable: return ( ELambda( {name: env[name] for name in self.future} if self.used else env, self.name, self.value ) if self.used else EDelayed(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}'