import t, c
from stdint import *
import memhub
import string
from .base import (
    AST, ASTKind,
    _init_ast, _copy_str, _set_parent_list,
    _emit, _emit_str, _emit_int, _dump_list,
)


# ============================================================
# MatchCase 节点
# ============================================================

class MatchCase(AST):
    """MatchCase(pattern: AST, guard: AST)"""
    pattern: AST | t.CPtr
    guard:   AST | t.CPtr

    def __new__(self, pool: memhub.MemManager | t.CPtr,
                pattern: AST | t.CPtr, guard: AST | t.CPtr):
        ptr: MatchCase | t.CPtr = pool.alloc(MatchCase.__sizeof__())
        if ptr:
            string.memset(ptr, 0, MatchCase.__sizeof__())
        return ptr

    def __init__(self, pool: memhub.MemManager | t.CPtr,
                 pattern: AST | t.CPtr, guard: AST | t.CPtr):
        _init_ast(self, pool, 0, 0)
        self.pattern = pattern
        self.guard = guard

    def kind(self) -> t.CInt:
        return ASTKind.MatchCase

    def type_name(self) -> str:
        return "MatchCase"

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "MatchCase(pattern=")
        if self.pattern is not None:
            pos = self.pattern.dump(buf, size, pos)
        pos = _emit(buf, size, pos, ", guard=")
        if self.guard is not None:
            pos = self.guard.dump(buf, size, pos)
        pos = _emit(buf, size, pos, ", body=")
        pos = _dump_list(self.children, buf, size, pos)
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# MatchValue 节点
# ============================================================

class MatchValue(AST):
    """MatchValue(value: AST)"""
    value: AST | t.CPtr

    def __new__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
        ptr: MatchValue | t.CPtr = pool.alloc(MatchValue.__sizeof__())
        if ptr:
            string.memset(ptr, 0, MatchValue.__sizeof__())
        return ptr

    def __init__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
        _init_ast(self, pool, 0, 0)
        self.value = value

    def kind(self) -> t.CInt:
        return ASTKind.MatchValue

    def type_name(self) -> str:
        return "MatchValue"

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "MatchValue(value=")
        if self.value is not None:
            pos = self.value.dump(buf, size, pos)
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# MatchSingleton 节点
# ============================================================

class MatchSingleton(AST):
    """MatchSingleton(value: AST)"""
    value: AST | t.CPtr

    def __new__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
        ptr: MatchSingleton | t.CPtr = pool.alloc(MatchSingleton.__sizeof__())
        if ptr:
            string.memset(ptr, 0, MatchSingleton.__sizeof__())
        return ptr

    def __init__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
        _init_ast(self, pool, 0, 0)
        self.value = value

    def kind(self) -> t.CInt:
        return ASTKind.MatchSingleton

    def type_name(self) -> str:
        return "MatchSingleton"

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "MatchSingleton(value=")
        if self.value is not None:
            pos = self.value.dump(buf, size, pos)
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# MatchSequence 节点
# ============================================================

class MatchSequence(AST):
    """MatchSequence(patterns: list[AST | t.CPtr])"""
    patterns: list[AST | t.CPtr] | t.CPtr

    def __new__(self, pool: memhub.MemManager | t.CPtr,
                patterns: list[AST | t.CPtr] | t.CPtr):
        ptr: MatchSequence | t.CPtr = pool.alloc(MatchSequence.__sizeof__())
        if ptr:
            string.memset(ptr, 0, MatchSequence.__sizeof__())
        return ptr

    def __init__(self, pool: memhub.MemManager | t.CPtr,
                 patterns: list[AST | t.CPtr] | t.CPtr):
        _init_ast(self, pool, 0, 0)
        self.patterns = patterns
        _set_parent_list(patterns, self)

    def kind(self) -> t.CInt:
        return ASTKind.MatchSequence

    def type_name(self) -> str:
        return "MatchSequence"

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "MatchSequence(patterns=")
        pos = _dump_list(self.patterns, buf, size, pos)
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# MatchMapping 节点
# ============================================================

class MatchMapping(AST):
    """MatchMapping(keys: list[AST | t.CPtr], patterns: list[AST | t.CPtr], rest: str)"""
    keys:     list[AST | t.CPtr] | t.CPtr
    patterns: list[AST | t.CPtr] | t.CPtr
    rest:     str

    def __new__(self, pool: memhub.MemManager | t.CPtr,
                keys: list[AST | t.CPtr] | t.CPtr,
                patterns: list[AST | t.CPtr] | t.CPtr,
                rest: str):
        ptr: MatchMapping | t.CPtr = pool.alloc(MatchMapping.__sizeof__())
        if ptr:
            string.memset(ptr, 0, MatchMapping.__sizeof__())
        return ptr

    def __init__(self, pool: memhub.MemManager | t.CPtr,
                 keys: list[AST | t.CPtr] | t.CPtr,
                 patterns: list[AST | t.CPtr] | t.CPtr,
                 rest: str):
        _init_ast(self, pool, 0, 0)
        self.keys = keys
        self.patterns = patterns
        self.rest = _copy_str(pool, rest)
        _set_parent_list(keys, self)
        _set_parent_list(patterns, self)

    def kind(self) -> t.CInt:
        return ASTKind.MatchMapping

    def type_name(self) -> str:
        return "MatchMapping"

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "MatchMapping(keys=")
        pos = _dump_list(self.keys, buf, size, pos)
        pos = _emit(buf, size, pos, ", patterns=")
        pos = _dump_list(self.patterns, buf, size, pos)
        pos = _emit(buf, size, pos, ", rest='")
        pos = _emit_str(buf, size, pos, self.rest)
        pos = _emit(buf, size, pos, "')")
        return pos


# ============================================================
# MatchClass 节点
# ============================================================

class MatchClass(AST):
    """MatchClass(cls: AST, patterns: list[AST | t.CPtr],
                  kwd_attrs: list[AST | t.CPtr], kwd_patterns: list[AST | t.CPtr])"""
    cls:           AST | t.CPtr
    patterns:      list[AST | t.CPtr] | t.CPtr
    kwd_attrs:     list[AST | t.CPtr] | t.CPtr
    kwd_patterns:  list[AST | t.CPtr] | t.CPtr

    def __new__(self, pool: memhub.MemManager | t.CPtr,
                cls: AST | t.CPtr,
                patterns: list[AST | t.CPtr] | t.CPtr,
                kwd_attrs: list[AST | t.CPtr] | t.CPtr,
                kwd_patterns: list[AST | t.CPtr] | t.CPtr):
        ptr: MatchClass | t.CPtr = pool.alloc(MatchClass.__sizeof__())
        if ptr:
            string.memset(ptr, 0, MatchClass.__sizeof__())
        return ptr

    def __init__(self, pool: memhub.MemManager | t.CPtr,
                 cls: AST | t.CPtr,
                 patterns: list[AST | t.CPtr] | t.CPtr,
                 kwd_attrs: list[AST | t.CPtr] | t.CPtr,
                 kwd_patterns: list[AST | t.CPtr] | t.CPtr):
        _init_ast(self, pool, 0, 0)
        self.cls = cls
        self.patterns = patterns
        self.kwd_attrs = kwd_attrs
        self.kwd_patterns = kwd_patterns
        _set_parent_list(patterns, self)
        _set_parent_list(kwd_attrs, self)
        _set_parent_list(kwd_patterns, self)

    def kind(self) -> t.CInt:
        return ASTKind.MatchClass

    def type_name(self) -> str:
        return "MatchClass"

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "MatchClass(cls=")
        if self.cls is not None:
            pos = self.cls.dump(buf, size, pos)
        pos = _emit(buf, size, pos, ", patterns=")
        pos = _dump_list(self.patterns, buf, size, pos)
        pos = _emit(buf, size, pos, ", kwd_attrs=")
        pos = _dump_list(self.kwd_attrs, buf, size, pos)
        pos = _emit(buf, size, pos, ", kwd_patterns=")
        pos = _dump_list(self.kwd_patterns, buf, size, pos)
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# MatchStar 节点
# ============================================================

class MatchStar(AST):
    """MatchStar(name: str)"""
    name: str

    def __new__(self, pool: memhub.MemManager | t.CPtr, name: str):
        ptr: MatchStar | t.CPtr = pool.alloc(MatchStar.__sizeof__())
        if ptr:
            string.memset(ptr, 0, MatchStar.__sizeof__())
        return ptr

    def __init__(self, pool: memhub.MemManager | t.CPtr, name: str):
        _init_ast(self, pool, 0, 0)
        self.name = _copy_str(pool, name)

    def kind(self) -> t.CInt:
        return ASTKind.MatchStar

    def type_name(self) -> str:
        return "MatchStar"

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "MatchStar(name='")
        pos = _emit_str(buf, size, pos, self.name)
        pos = _emit(buf, size, pos, "')")
        return pos


# ============================================================
# MatchAs 节点
# ============================================================

class MatchAs(AST):
    """MatchAs(pattern: AST, name: str)"""
    pattern: AST | t.CPtr
    name:    str

    def __new__(self, pool: memhub.MemManager | t.CPtr,
                pattern: AST | t.CPtr, name: str):
        ptr: MatchAs | t.CPtr = pool.alloc(MatchAs.__sizeof__())
        if ptr:
            string.memset(ptr, 0, MatchAs.__sizeof__())
        return ptr

    def __init__(self, pool: memhub.MemManager | t.CPtr,
                 pattern: AST | t.CPtr, name: str):
        _init_ast(self, pool, 0, 0)
        self.pattern = pattern
        self.name = _copy_str(pool, name)

    def kind(self) -> t.CInt:
        return ASTKind.MatchAs

    def type_name(self) -> str:
        return "MatchAs"

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "MatchAs(pattern=")
        if self.pattern is not None:
            pos = self.pattern.dump(buf, size, pos)
        pos = _emit(buf, size, pos, ", name='")
        pos = _emit_str(buf, size, pos, self.name)
        pos = _emit(buf, size, pos, "')")
        return pos


# ============================================================
# MatchOr 节点
# ============================================================

class MatchOr(AST):
    """MatchOr(patterns: list[AST | t.CPtr])"""
    patterns: list[AST | t.CPtr] | t.CPtr

    def __new__(self, pool: memhub.MemManager | t.CPtr,
                patterns: list[AST | t.CPtr] | t.CPtr):
        ptr: MatchOr | t.CPtr = pool.alloc(MatchOr.__sizeof__())
        if ptr:
            string.memset(ptr, 0, MatchOr.__sizeof__())
        return ptr

    def __init__(self, pool: memhub.MemManager | t.CPtr,
                 patterns: list[AST | t.CPtr] | t.CPtr):
        _init_ast(self, pool, 0, 0)
        self.patterns = patterns
        _set_parent_list(patterns, self)

    def kind(self) -> t.CInt:
        return ASTKind.MatchOr

    def type_name(self) -> str:
        return "MatchOr"

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "MatchOr(patterns=")
        pos = _dump_list(self.patterns, buf, size, pos)
        pos = _emit(buf, size, pos, ")")
        return pos
