import t, c
from stdint import *


# ============================================================
# LinkedNode: Non-polymorphic base class (@t.NoVTable)
#
# Subclasses inheriting from this class gain standard linked list and tree capabilities:
#   - Bidirectional sibling links (next/prev) → O(1) removal
#   - Parent-child tree structure (child/last_child/parent) → O(1) child appending
#   - Child counter (child_count)
#
# Fields are flattened and embedded into subclasses with no vtable overhead
# (equivalent to non-polymorphic inheritance in C++).
# OOP methods are automatically wrapped for subclasses via _generate_inherited_method_wrappers
# (self pointer cast to base type before invocation). Inherited methods can be called directly by subclasses.
#
# Usage:
#   class MyNode(LinkedNode):
#       value: t.CInt
#   root: MyNode = MyNode()
#   child: MyNode = MyNode()
#   root.append(child)             # OOP invocation, self = root
#   child.detach()                 # Remove self from sibling chain
# ============================================================
@t.NoVTable
class LinkedNode:
    next: "LinkedNode" | t.CPtr        # Next sibling node
    prev: "LinkedNode" | t.CPtr        # Previous sibling node (doubly linked list, O(1) removal)
    child: "LinkedNode" | t.CPtr       # First child node
    last_child: "LinkedNode" | t.CPtr  # Last child node (O(1) append)
    parent: "LinkedNode" | t.CPtr      # Parent node
    child_count: t.CSizeT              # Number of child nodes

    def append(self, node: "LinkedNode" | t.CPtr):
        """Append node as the last child of self (O(1)).

        If node is already attached to any list, the caller shall invoke node.detach() prior to append.
        """
        if self is None or node is None: return
        node.parent = self
        node.next = None
        node.prev = self.last_child
        if self.child is None:
            self.child = node
        else:
            self.last_child.next = node
        self.last_child = node
        self.child_count += 1

    def prepend(self, node: "LinkedNode" | t.CPtr):
        """Insert node as the first child of self (O(1))."""
        if self is None or node is None: return
        node.parent = self
        node.prev = None
        node.next = self.child
        if self.child is not None:
            self.child.prev = node
        else:
            self.last_child = node
        self.child = node
        self.child_count += 1

    def insert_before(self, node: "LinkedNode" | t.CPtr,
                      new_node: "LinkedNode" | t.CPtr):
        """Insert new_node before node (O(1)). node must be a direct child of self."""
        if self is None or node is None or new_node is None: return
        new_node.parent = self
        new_node.prev = node.prev
        new_node.next = node
        if node.prev is not None:
            node.prev.next = new_node
        else:
            self.child = new_node
        node.prev = new_node
        self.child_count += 1

    def insert_after(self, node: "LinkedNode" | t.CPtr,
                     new_node: "LinkedNode" | t.CPtr):
        """Insert new_node after node (O(1)). node must be a direct child of self."""
        if self is None or node is None or new_node is None: return
        new_node.parent = self
        new_node.prev = node
        new_node.next = node.next
        if node.next is not None:
            node.next.prev = new_node
        else:
            self.last_child = new_node
        node.next = new_node
        self.child_count += 1

    def remove_child(self, node: "LinkedNode" | t.CPtr):
        """Remove node from self's child linked list (O(1)). The node must be a direct child of self."""
        if self is None or node is None:
            return
        # Patch prev.next
        if node.prev is not None:
            node.prev.next = node.next
        else:
            self.child = node.next
        # Patch next.prev
        if node.next is not None:
            node.next.prev = node.prev
        else:
            self.last_child = node.prev
        # Clear sibling and parent links of node
        node.next = None
        node.prev = None
        node.parent = None
        if self.child_count > 0:
            self.child_count -= 1

    def detach(self):
        """Detach self from its sibling linked list (O(1)).

        After invocation, self.next/self.prev/self.parent are cleared. The child chain remains untouched.
        """
        if self is None:
            return
        # Patch prev.next
        if self.prev is not None:
            self.prev.next = self.next
        elif self.parent is not None:
            self.parent.child = self.next
        # Patch next.prev
        if self.next is not None:
            self.next.prev = self.prev
        elif self.parent is not None:
            self.parent.last_child = self.prev
        # Decrement parent child counter
        if self.parent is not None:
            if self.parent.child_count > 0:
                self.parent.child_count -= 1
        # Clear links of self
        self.next = None
        self.prev = None
        self.parent = None

    def unlink(self):
        """Sever all links of self (siblings and parent). Child nodes are not processed recursively.

        After invocation, self becomes an isolated node, while its child chain still references original children
        (the parent field of child nodes still points to self). For full isolation, the caller shall
        invoke self.remove_child on each child beforehand.
        """
        if self is None:
            return
        # First detach from sibling list
        self.detach()
        # Then break parent-child links
        self.child = None
        self.last_child = None
        self.child_count = 0

    def has_children(self) -> t.CInt:
        """Return 1 if child nodes exist, otherwise return 0."""
        if self is None:
            return 0
        if self.child is not None:
            return 1
        return 0

    def child_at(self, index: t.CSizeT) -> "LinkedNode" | t.CPtr:
        """Return the child node at specified zero-based index (O(n)). Return None if index out of bounds."""
        if self is None:
            return None
        cur: "LinkedNode" | t.CPtr = self.child
        i: t.CSizeT = 0
        while cur is not None:
            if i == index:
                return cur
            i += 1
            cur = cur.next
        return None

    def count_children(self) -> t.CSizeT:
        """Count children by traversal (O(n)), used to validate child_count."""
        if self is None: return 0
        n: t.CSizeT = 0
        cur: "LinkedNode" | t.CPtr = self.child
        while cur is not None:
            n += 1
            cur = cur.next
        return n

    def first_sibling(self) -> "LinkedNode" | t.CPtr:
        """Return the head node of sibling linked list (traverse backward via prev pointers)."""
        if self is None: return None
        cur: "LinkedNode" | t.CPtr = self
        while cur.prev is not None:
            cur = cur.prev
        return cur

    def last_sibling(self) -> "LinkedNode" | t.CPtr:
        """Return the tail node of sibling linked list (traverse forward via next pointers)."""
        if self is None: return None
        cur: "LinkedNode" | t.CPtr = self
        while cur.next is not None:
            cur = cur.next
        return cur


# ============================================================
# SListNode: Singly linked list node (@t.NoVTable)
#
# Lightweight singly linked list with only Next pointer. No prev/parent/child.
# Suitable for queues, stacks and simple linked structures
# (such as Param/BasicBlock/Function/Line/Value in llvmlite).
# O(1) append requires caller to maintain tail pointer (append_after).
# O(n) append works with head pointer only (append).
# ============================================================
@t.NoVTable
class SListNode:
    Next: "SListNode" | t.CPtr      # Next node

    def append(self, node: "SListNode" | t.CPtr) -> "SListNode" | t.CPtr:
        """Append node to the end of the linked list (O(n)). Return self (head).

        If self is None, the caller shall adopt node directly as the new head.
        """
        if self is None:
            return node
        if node is None:
            return self
        node.Next = None
        cur: "SListNode" | t.CPtr = self
        while cur.Next is not None:
            cur = cur.Next
        cur.Next = node
        return self

    def append_after(self, node: "SListNode" | t.CPtr) -> "SListNode" | t.CPtr:
        """Insert node immediately after self (O(1)). Return new tail (node).

        Caller must maintain the head pointer manually. Return node as head if self is None.
        """
        if node is None:
            return self
        node.Next = None
        if self is not None:
            self.Next = node
        return node

    def count(self) -> t.CSizeT:
        """Calculate list length via full traversal (O(n))."""
        if self is None:
            return 0
        n: t.CSizeT = 0
        cur: "SListNode" | t.CPtr = self
        while cur is not None:
            n += 1
            cur = cur.Next
        return n

    def at(self, index: t.CSizeT) -> "SListNode" | t.CPtr:
        """Return node at zero-based index (O(n)). Return None if index out of bounds."""
        if self is None:
            return None
        cur: "SListNode" | t.CPtr = self
        i: t.CSizeT = 0
        while cur is not None:
            if i == index:
                return cur
            i += 1
            cur = cur.Next
        return None

    def remove(self, node: "SListNode" | t.CPtr) -> "SListNode" | t.CPtr:
        """Remove node from list (O(n)). Return updated head.

        The Next pointer of node will be cleared. If node is the original head, return head.Next.
        """
        if self is None or node is None:
            return self
        if self is node:
            new_head: "SListNode" | t.CPtr = self.Next
            self.Next = None
            return new_head
        cur: "SListNode" | t.CPtr = self
        while cur.Next is not None:
            if cur.Next is node:
                cur.Next = node.Next
                node.Next = None
                break
            cur = cur.Next
        return self


# ============================================================
# GSListNode[T]: Generic singly linked list node (@t.NoVTable + PEP 695 generics)
#
# Unlike SListNode (non-generic, Next: SListNode|t.CPtr), the Next field of GSListNode[T]
# is typed as T|t.CPtr. After specialization it becomes a concrete node type directly,
# eliminating downcasts.
#
# Recursive generic usage pattern (subclass inherits from self-specialized variant):
#   class GNode(GSListNode[GNode]):
#       value: t.CInt
#   # At this point GNode.Next: GNode|t.CPtr (strongly typed, no casting required)
#
# Technical validation targets:
#   1. Recursive generics: class GNode(GSListNode[GNode])
#   2. Combination of @t.NoVTable attribute with generics
#   3. Generic class used as field type: list: GSList[GNode]
#   4. Inheritance of generic methods (GSList[T].append available after specialization)
# ============================================================
@t.NoVTable
class GSListNode[T]:
    Next: T | t.CPtr


# ============================================================
# GSList[T]: Generic singly linked list container (@t.NoVTable + PEP 695 generics)
#
# Holds Head, Tail and Count. Provides O(1) append and O(n) indexed access.
# Node type T must inherit from GSListNode[T] (to acquire the Next field).
#
# Usage:
#   list: GSList[GNode] | t.CPtr = GSList[GNode]()
#   list.append(node)   # Method invocation, not free function
# ============================================================
@t.NoVTable
class GSList[T]:
    Head: T | t.CPtr
    Tail: T | t.CPtr
    Count: t.CSizeT

    def __init__(self):
        self.Head = None
        self.Tail = None
        self.Count = 0

    def append(self, node: T):
        """Append node to the end of the list (O(1))."""
        if node is None:
            return
        node.Next = None
        if self.Head is None:
            self.Head = node
        else:
            self.Tail.Next = node
        self.Tail = node
        self.Count += 1

    def count(self) -> t.CSizeT:
        """Return node count (O(1))."""
        return self.Count

    def at(self, index: t.CSizeT) -> T | t.CPtr:
        """Return node at zero-based index (O(n)). Return None if index out of bounds."""
        if self.Head is None:
            return None
        cur: T | t.CPtr = self.Head
        i: t.CSizeT = 0
        while cur is not None:
            if i == index:
                return cur
            i += 1
            cur = cur.Next
        return None


# ============================================================
# GTreeNode[T]: Generic tree node (@t.NoVTable + PEP 695 generics)
#
# Type-safe variant of LinkedNode. All pointer fields are typed T|t.CPtr.
# Capabilities provided:
#   - Bidirectional sibling linked list (Next/Prev) → O(1) removal
#   - Parent-child tree structure (Child/LastChild/Parent) → O(1) child appending
#   - Child counter (Count)
#
# Recursive generic usage pattern (subclass inherits self-specialized variant):
#   @t.CVTable
#   class AST(GTreeNode[AST]):
#       def kind(self) -> t.CInt:
#           return 0
#   # At this point AST.Next/Prev/Child/LastChild/Parent are all AST|t.CPtr (strongly typed)
#
# Fields are flattened and embedded into subclasses with no vtable overhead
# (equivalent to non-polymorphic inheritance in C++).
# If a subclass is marked @t.CVTable, it receives its own vtable (at offset 0),
# and GTreeNode fields are laid out after the vtable.
#
# OOP methods are automatically wrapped for subclasses via _generate_inherited_method_wrappers
# (self pointer cast to base type before invocation). Inherited methods can be called directly by subclasses.
# ============================================================
@t.NoVTable
class GTreeNode[T]:
    Next:       T | t.CPtr        # Next sibling node
    Prev:       T | t.CPtr        # Previous sibling node (doubly linked list, O(1) removal)
    Child:      T | t.CPtr        # First child node
    LastChild:  T | t.CPtr        # Last child node (O(1) append)
    Parent:     T | t.CPtr        # Parent node
    Count:      t.CSizeT          # Number of child nodes

    def append(self, node: T | t.CPtr):
        """Append node as the last child of self (O(1)).

        If node is already attached to any list, the caller shall invoke node.detach() prior to append.
        """
        if self is None or node is None:
            return
        node.Parent = self
        node.Next = None
        node.Prev = self.LastChild
        if self.Child is None:
            self.Child = node
        else:
            self.LastChild.Next = node
        self.LastChild = node
        self.Count += 1

    def prepend(self, node: T | t.CPtr):
        """Insert node as the first child of self (O(1))."""
        if self is None or node is None:
            return
        node.Parent = self
        node.Prev = None
        node.Next = self.Child
        if self.Child is not None:
            self.Child.Prev = node
        else:
            self.LastChild = node
        self.Child = node
        self.Count += 1

    def detach(self):
        """Detach self from its sibling linked list (O(1)).

        After invocation, self.Next/self.Prev/self.Parent are cleared. The child chain remains untouched.
        """
        if self is None:
            return
        if self.Prev is not None:
            self.Prev.Next = self.Next
        elif self.Parent is not None:
            self.Parent.Child = self.Next
        if self.Next is not None:
            self.Next.Prev = self.Prev
        elif self.Parent is not None:
            self.Parent.LastChild = self.Prev
        if self.Parent is not None:
            if self.Parent.Count > 0:
                self.Parent.Count -= 1
        self.Next = None
        self.Prev = None
        self.Parent = None

    def has_children(self) -> t.CInt:
        """Return 1 if child nodes exist, otherwise return 0."""
        if self is None:
            return 0
        if self.Child is not None:
            return 1
        return 0

    def child_at(self, index: t.CSizeT) -> T | t.CPtr:
        """Return the child node at specified zero-based index (O(n)). Return None if index out of bounds."""
        if self is None:
            return None
        cur: T | t.CPtr = self.Child
        i: t.CSizeT = 0
        while cur is not None:
            if i == index:
                return cur
            i += 1
            cur = cur.Next
        return None

    def count_children(self) -> t.CSizeT:
        """Count children by traversal (O(n)), used to validate Count field."""
        if self is None:
            return 0
        n: t.CSizeT = 0
        cur: T | t.CPtr = self.Child
        while cur is not None:
            n += 1
            cur = cur.Next
        return n
