# Copyright (c) PARRRATE T&V 2021. All rights reserved. from bu4.evaluation.constructs.elambda import ELambda from bu4.evaluation.constructs.evaluable import Evaluable from bu4.evaluation.constructs.evalue import EValue from bu4.evaluation.sync import sync class Probe(EValue): def call(self, argument: Evaluable) -> Evaluable: return ProbeB(self, argument) def start_and_list(self): probe = self list_ = [] while isinstance(probe, ProbeB): list_.append(probe.argument) probe = probe.prev assert isinstance(probe, ProbeA) return probe.start, reversed(list_) def __str__(self): start, list_ = self.start_and_list() return f'probe {start} [ {" ; ".join(map(str, list_))} ]' class ProbeA(Probe): def __init__(self, start): self.start = start class ProbeB(Probe): def __init__(self, prev: Probe, argument): self.prev = prev self.argument = argument _probe_index = 0 def trace(lambda_: EValue): global _probe_index size = 0 while True: if not isinstance(lambda_, ELambda): return size, lambda_ lambda_ = sync(lambda_.call(ProbeA(_probe_index))) _probe_index += 1 size += 1