import math
import hashlib

# -------------------------------
# φ-only Turing-complete BTC VM
# -------------------------------
PHI = 1.6180339887
INV_PHI = PHI - 1

def DNA_n(n):
    """Recursive φ braid encoding numbers/operators"""
    if n == 0:
        return PHI
    return PHI ** DNA_n(n - 1)

class PHI_Turing_VM:
    def __init__(self, slots=32):
        self.slots = {}
        self.bits = {}
        self.stack = []
        self.slots_count = slots

    def provision_lattice(self):
        for n in range(1, self.slots_count + 1):
            val = DNA_n(n)
            self.slots[n] = val
            self.bits[n] = self.discretize(val)

    def discretize(self, value, threshold=PHI):
        return 1 if value >= threshold else 0

    def execute_stream(self, program):
        ip = 0
        call_stack = []
        while ip < len(program):
            instr = program[ip]

            if isinstance(instr, (int, float)):
                self.stack.append(instr)

            elif instr.startswith("DNA"):
                k = int(instr[3:])
                self.stack.append(DNA_n(k))

            elif instr == "ADD":
                b, a = self.stack.pop(), self.stack.pop()
                self.stack.append(a + b)

            elif instr == "MUL":
                b, a = self.stack.pop(), self.stack.pop()
                self.stack.append(a * b)

            elif instr == "SIN":
                a = self.stack.pop()
                self.stack.append(math.sin(a))

            elif instr == "WHILE":
                cond = self.stack.pop()
                if cond:
                    call_stack.append(ip)  # remember loop start
                else:
                    # skip to END
                    depth = 1
                    while depth > 0:
                        ip += 1
                        if program[ip] == "WHILE":
                            depth += 1
                        elif program[ip] == "END":
                            depth -= 1

            elif instr == "END":
                if call_stack:
                    ip = call_stack[-1] - 1  # loop back
                else:
                    call_stack.pop()

            elif instr == "SHA256":
                bitstring = ''.join(str(self.discretize(v)) for v in self.slots.values())
                h = hashlib.sha256(bitstring.encode()).hexdigest()
                self.slots[32] = int(h[:8], 16)

            else:
                raise ValueError(f"Unknown instruction: {instr}")

            ip += 1

    def report(self):
        print("\n[Final Slots State]")
        for n, val in sorted(self.slots.items()):
            print(f"D_{n}(r) = {val} → {self.bits.get(n, 0)}")
        bitstring = ''.join(str(self.bits.get(n, 0)) for n in sorted(self.slots.keys(), reverse=True))
        print("Binary:", bitstring)
        print("Hex   :", hex(int(bitstring, 2)) if bitstring else "0x0")
        print("Stack :", self.stack)
        print("Covenant ID (slot 32):", hex(self.slots.get(32, 0)))

# -------------------------------
# Example Turing-complete φ covenant
# -------------------------------
if __name__ == "__main__":
    vm = PHI_Turing_VM()
    vm.provision_lattice()

    # Infinite loop in practice is bounded by interpreter for safety
    program = [
        "DNA1", "DNA2", "ADD",
        "DNA3", "MUL",
        "SIN",
        1, "WHILE",          # loop while top-of-stack != 0
            "DNA4", "MUL",
            0.1, "ADD",       # increment to eventually break
        "END",
        "SHA256"
    ]

    vm.execute_stream(program)
    vm.report()
