import t, c
from stdint import *
import memhub
import string
from .base import (
    AST, ASTKind, ASTCtx, OpKind,
    _init_ast, _copy_str, _set_parent_list,
    _emit, _emit_str, _emit_int, _dump_list, _dump_op_list, _op_name,
    CONST_INT, CONST_FLOAT, CONST_STR, CONST_BOOL, CONST_NONE
)


# ============================================================
# Name 节点
# ============================================================

class Name(AST):
    """Name(id: str, ctx: ASTCtx)"""
    id:  str
    ctx: t.CInt

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

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

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "Name(id='")
        pos = _emit_str(buf, size, pos, self.id)
        pos = _emit(buf, size, pos, "', ctx=")
        if self.ctx == ASTCtx.Load:
            pos = _emit(buf, size, pos, "Load")
        elif self.ctx == ASTCtx.Store:
            pos = _emit(buf, size, pos, "Store")
        else:
            pos = _emit(buf, size, pos, "Del")
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# Constant 节点（用 const_kind 标识子类型）
# ============================================================

class Constant(AST):
    """Constant(int_val/float_val/str_val, const_kind)"""
    int_val:    t.CInt64T
    float_val:  t.CDouble
    str_val:    str
    const_kind: t.CInt

    def __new__(self, pool: memhub.MemManager | t.CPtr,
                const_kind: t.CInt, int_val: t.CInt64T,
                float_val: t.CDouble, str_val: str,
                lineno: t.CInt, col: t.CInt):
        ptr: Constant | t.CPtr = pool.alloc(Constant.__sizeof__())
        if ptr:
            string.memset(ptr, 0, Constant.__sizeof__())
        return ptr

    def __init__(self, pool: memhub.MemManager | t.CPtr,
                 const_kind: t.CInt, int_val: t.CInt64T,
                 float_val: t.CDouble, str_val: str,
                 lineno: t.CInt, col: t.CInt):
        _init_ast(self, pool, lineno, col)
        self.const_kind = const_kind
        self.int_val = int_val
        self.float_val = float_val
        if str_val is not None:
            self.str_val = _copy_str(pool, str_val)
        else:
            self.str_val = None

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "Constant(value=")
        if self.const_kind == CONST_INT:
            pos = _emit_int(buf, size, pos, self.int_val)
        elif self.const_kind == CONST_FLOAT:
            pos = _emit(buf, size, pos, "<float>")
        elif self.const_kind == CONST_STR:
            pos = _emit(buf, size, pos, "'")
            if self.str_val is not None:
                pos = _emit_str(buf, size, pos, self.str_val)
            else:
                pos = _emit(buf, size, pos, "(null)")
            pos = _emit(buf, size, pos, "'")
        elif self.const_kind == CONST_BOOL:
            if self.int_val != 0:
                pos = _emit(buf, size, pos, "True")
            else:
                pos = _emit(buf, size, pos, "False")
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# BinOp 节点
# ============================================================

class BinOp(AST):
    """BinOp(left: AST, op: OpKind, right: AST)"""
    left:  AST | t.CPtr
    op:    t.CInt
    right: AST | t.CPtr

    def __new__(self, pool: memhub.MemManager | t.CPtr,
                left: AST | t.CPtr, op: t.CInt, right: AST | t.CPtr):
        ptr: BinOp | t.CPtr = pool.alloc(BinOp.__sizeof__())
        if ptr:
            string.memset(ptr, 0, BinOp.__sizeof__())
        return ptr

    def __init__(self, pool: memhub.MemManager | t.CPtr,
                 left: AST | t.CPtr, op: t.CInt, right: AST | t.CPtr):
        _init_ast(self, pool, 0, 0)
        self.left = left
        self.op = op
        self.right = right

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "BinOp(left=")
        if self.left is not None:
            pos = self.left.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ", op=")
        pos = _emit(buf, size, pos, _op_name(self.op))
        pos = _emit(buf, size, pos, ", right=")
        if self.right is not None:
            pos = self.right.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# UnaryOp 节点
# ============================================================

class UnaryOp(AST):
    """UnaryOp(op: OpKind, operand: AST)"""
    op:      t.CInt
    operand: AST | t.CPtr

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

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

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "UnaryOp(op=")
        pos = _emit(buf, size, pos, _op_name(self.op))
        pos = _emit(buf, size, pos, ", operand=")
        if self.operand is not None:
            pos = self.operand.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# Compare 节点
# ============================================================

class Compare(AST):
    """Compare(left: AST, ops: list[CInt], comparators: list[AST | CPtr])"""
    left:        AST | t.CPtr
    ops:         t.CPtr
    comparators: list[AST | t.CPtr] | t.CPtr

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

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

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "Compare(left=")
        if self.left is not None:
            pos = self.left.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ", ops=")
        pos = _dump_op_list(self.ops, buf, size, pos)
        pos = _emit(buf, size, pos, ", comparators=")
        pos = _dump_list(self.comparators, buf, size, pos)
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# Call 节点
# ============================================================

class Call(AST):
    """Call(func: AST, args: list[AST | CPtr], keywords: list[AST | CPtr])"""
    func:     AST | t.CPtr
    args:     list[AST | t.CPtr] | t.CPtr
    keywords: list[AST | t.CPtr] | t.CPtr

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

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

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "Call(func=")
        if self.func is not None:
            pos = self.func.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ", args=")
        pos = _dump_list(self.args, buf, size, pos)
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# BoolOp 节点
# ============================================================

class BoolOp(AST):
    """BoolOp(op: CInt, values: list[AST | CPtr])"""
    op:     t.CInt
    values: list[AST | t.CPtr] | t.CPtr

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

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

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "BoolOp(op=")
        pos = _emit(buf, size, pos, _op_name(self.op))
        pos = _emit(buf, size, pos, ", values=")
        pos = _dump_list(self.values, buf, size, pos)
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# Lambda 节点
# ============================================================

class Lambda(AST):
    """Lambda(args: AST, body: AST)"""
    args: AST | t.CPtr
    body: AST | t.CPtr

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

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

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

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

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


# ============================================================
# IfExp 节点
# ============================================================

class IfExp(AST):
    """IfExp(test: AST, body: AST, orelse: AST)"""
    test:   AST | t.CPtr
    body:   AST | t.CPtr
    orelse: AST | t.CPtr

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

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

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "IfExp(test=")
        if self.test is not None:
            pos = self.test.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ", body=")
        if self.body is not None:
            pos = self.body.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ", orelse=")
        if self.orelse is not None:
            pos = self.orelse.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# Dict 节点
# ============================================================

class Dict(AST):
    """Dict(keys: list[AST | CPtr], values: list[AST | CPtr])"""
    keys:   list[AST | t.CPtr] | t.CPtr
    values: list[AST | t.CPtr] | t.CPtr

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

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

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

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

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


# ============================================================
# Set 节点
# ============================================================

class Set(AST):
    """Set(elts: list[AST | CPtr])"""
    elts: list[AST | t.CPtr] | t.CPtr

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

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

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

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

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


# ============================================================
# ListComp 节点
# ============================================================

class ListComp(AST):
    """ListComp(elt: AST, generators: list[AST | CPtr])"""
    elt:        AST | t.CPtr
    generators: list[AST | t.CPtr] | t.CPtr

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

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

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "ListComp(elt=")
        if self.elt is not None:
            pos = self.elt.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ", generators=")
        pos = _dump_list(self.generators, buf, size, pos)
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# SetComp 节点
# ============================================================

class SetComp(AST):
    """SetComp(elt: AST, generators: list[AST | CPtr])"""
    elt:        AST | t.CPtr
    generators: list[AST | t.CPtr] | t.CPtr

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

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

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "SetComp(elt=")
        if self.elt is not None:
            pos = self.elt.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ", generators=")
        pos = _dump_list(self.generators, buf, size, pos)
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# DictComp 节点
# ============================================================

class DictComp(AST):
    """DictComp(key: AST, value: AST, generators: list[AST | CPtr])"""
    key:        AST | t.CPtr
    value:      AST | t.CPtr
    generators: list[AST | t.CPtr] | t.CPtr

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

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

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

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

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


# ============================================================
# GeneratorExp 节点
# ============================================================

class GeneratorExp(AST):
    """GeneratorExp(elt: AST, generators: list[AST | CPtr])"""
    elt:        AST | t.CPtr
    generators: list[AST | t.CPtr] | t.CPtr

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

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

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "GeneratorExp(elt=")
        if self.elt is not None:
            pos = self.elt.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ", generators=")
        pos = _dump_list(self.generators, buf, size, pos)
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# Await 节点
# ============================================================

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

    def __new__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
        ptr: Await | t.CPtr = pool.alloc(Await.__sizeof__())
        if ptr:
            string.memset(ptr, 0, Await.__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.Await

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

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


# ============================================================
# Yield 节点
# ============================================================

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

    def __new__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
        ptr: Yield | t.CPtr = pool.alloc(Yield.__sizeof__())
        if ptr:
            string.memset(ptr, 0, Yield.__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.Yield

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

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


# ============================================================
# YieldFrom 节点
# ============================================================

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

    def __new__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
        ptr: YieldFrom | t.CPtr = pool.alloc(YieldFrom.__sizeof__())
        if ptr:
            string.memset(ptr, 0, YieldFrom.__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.YieldFrom

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

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


# ============================================================
# FormattedValue 节点
# ============================================================

class FormattedValue(AST):
    """FormattedValue(value: AST, conversion: CInt, format_spec: AST)"""
    value:       AST | t.CPtr
    conversion:  t.CInt
    format_spec: AST | t.CPtr

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

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

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "FormattedValue(value=")
        if self.value is not None:
            pos = self.value.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ", conversion=")
        pos = _emit_int(buf, size, pos, t.CInt64T(self.conversion))
        pos = _emit(buf, size, pos, ", format_spec=")
        if self.format_spec is not None:
            pos = self.format_spec.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# JoinedStr 节点
# ============================================================

class JoinedStr(AST):
    """JoinedStr(values: list[AST | CPtr])"""
    values: list[AST | t.CPtr] | t.CPtr

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

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

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

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

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


# ============================================================
# Attribute 节点
# ============================================================

class Attribute(AST):
    """Attribute(value: AST, attr: str, ctx: CInt)"""
    value: AST | t.CPtr
    attr:  str
    ctx:   t.CInt

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

    def __init__(self, pool: memhub.MemManager | t.CPtr,
                 value: AST | t.CPtr, attr: str, ctx: t.CInt):
        _init_ast(self, pool, 0, 0)
        self.value = value
        self.attr = _copy_str(pool, attr)
        self.ctx = ctx

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "Attribute(value=")
        if self.value is not None:
            pos = self.value.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ", attr='")
        pos = _emit_str(buf, size, pos, self.attr)
        pos = _emit(buf, size, pos, "', ctx=")
        pos = _emit_int(buf, size, pos, t.CInt64T(self.ctx))
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# Subscript 节点
# ============================================================

class Subscript(AST):
    """Subscript(value: AST, slice: AST, ctx: CInt)"""
    value: AST | t.CPtr
    slice: AST | t.CPtr
    ctx:   t.CInt

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

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

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "Subscript(value=")
        if self.value is not None:
            pos = self.value.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ", slice=")
        if self.slice is not None:
            pos = self.slice.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ", ctx=")
        pos = _emit_int(buf, size, pos, t.CInt64T(self.ctx))
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# Starred 节点
# ============================================================

class Starred(AST):
    """Starred(value: AST, ctx: CInt)"""
    value: AST | t.CPtr
    ctx:   t.CInt

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

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

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

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

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


# ============================================================
# List 节点
# ============================================================

class List(AST):
    """List(elts: list[AST | CPtr], ctx: CInt)"""
    elts: list[AST | t.CPtr] | t.CPtr
    ctx:  t.CInt

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

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

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "List(elts=")
        pos = _dump_list(self.elts, buf, size, pos)
        pos = _emit(buf, size, pos, ", ctx=")
        pos = _emit_int(buf, size, pos, t.CInt64T(self.ctx))
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# Tuple 节点
# ============================================================

class Tuple(AST):
    """Tuple(elts: list[AST | CPtr], ctx: CInt)"""
    elts: list[AST | t.CPtr] | t.CPtr
    ctx:  t.CInt

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

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

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "Tuple(elts=")
        pos = _dump_list(self.elts, buf, size, pos)
        pos = _emit(buf, size, pos, ", ctx=")
        pos = _emit_int(buf, size, pos, t.CInt64T(self.ctx))
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# Slice 节点
# ============================================================

class Slice(AST):
    """Slice(lower: AST, upper: AST, step: AST)"""
    lower: AST | t.CPtr
    upper: AST | t.CPtr
    step:  AST | t.CPtr

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

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

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "Slice(lower=")
        if self.lower is not None:
            pos = self.lower.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ", upper=")
        if self.upper is not None:
            pos = self.upper.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ", step=")
        if self.step is not None:
            pos = self.step.dump(buf, size, pos)
        else:
            pos = _emit(buf, size, pos, "None")
        pos = _emit(buf, size, pos, ")")
        return pos


# ============================================================
# NamedExpr 节点
# ============================================================

class NamedExpr(AST):
    """NamedExpr(target: AST, value: AST)"""
    target: AST | t.CPtr
    value:  AST | t.CPtr

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

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

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

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

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


# ============================================================
# OpNode 节点
# ============================================================

class OpNode(AST):
    """OpNode(op: CInt)"""
    op: t.CInt

    def __new__(self, pool: memhub.MemManager | t.CPtr, op: t.CInt):
        ptr: OpNode | t.CPtr = pool.alloc(OpNode.__sizeof__())
        if ptr:
            string.memset(ptr, 0, OpNode.__sizeof__())
        return ptr

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

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

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

    def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
             pos: t.CSizeT) -> t.CSizeT:
        pos = _emit(buf, size, pos, "OpNode(op=")
        pos = _emit(buf, size, pos, _op_name(self.op))
        pos = _emit(buf, size, pos, ")")
        return pos
