#  Copyright (c) PARRRATE T&V 2021. All rights reserved.

from bu4.evaluation.constructs.evaluable import Evaluable
from bu4.evaluation.constructs.evalue import EValue

__all__ = ('Probe',)


class Probe(EValue):
    def __new__(cls, *args, **kwargs):
        return object.__new__(ProbeA if cls == Probe else cls)

    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, list(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