50 lines
1.2 KiB
Python
50 lines
1.2 KiB
Python
# 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
|