import t, c
from stdint import *
import memhub
import string


# ============================================================
# Token 类型枚举（参考 CPython Lib/token.py）
# 用 t.CEnum 组织为类型安全枚举；旧名 XXX 保留为兼容别名
# ============================================================

class TokenType(t.CEnum):
    EndMarker:      t.State
    NewLine:        t.State
    Indent:         t.State
    Dedent:         t.State
    Name:           t.State
    Number:         t.State
    String:         t.State
    FStringStart:   t.State
    FStringMiddle:  t.State
    FStringEnd:     t.State
    Op:             t.State
    Nl:             t.State
    Comment:        t.State
    Encoding:       t.State


# ============================================================
# 关键字枚举（参考 CPython Lib/keyword.py）
# 用 t.CEnum 组织为类型安全枚举；旧名 KW_XXX 保留为兼容别名
# NotKeyword(0) 表示非关键字（哨兵，避免 False_=0 与 kw_subtype=0 冲突）
# ============================================================

class Keyword(t.CEnum):
    NotKeyword: t.State
    False_:     t.State
    None_:      t.State
    True_:      t.State
    And:        t.State
    As:         t.State
    Assert:     t.State
    Async:      t.State
    Await:      t.State
    Break:      t.State
    Class:      t.State
    Continue:   t.State
    Def:        t.State
    Del:        t.State
    Elif:       t.State
    Else:       t.State
    Except:     t.State
    Finally:    t.State
    For:        t.State
    From:       t.State
    Global:     t.State
    If:         t.State
    Import:     t.State
    In:         t.State
    Is:         t.State
    Lambda:     t.State
    Nonlocal:   t.State
    Not:        t.State
    Or:         t.State
    Pass:       t.State
    Raise:      t.State
    Return:     t.State
    Try:        t.State
    While:      t.State
    With:       t.State
    Yield:      t.State
    Match:      t.State
    Case:       t.State
    Type:       t.State


# ============================================================
# 运算符/分隔符枚举
# 用 t.CEnum 组织为类型安全枚举；旧名 OP_XXX 保留为兼容别名
# 存储在 token.op_subtype 字段
# ============================================================

class TokOp(t.CEnum):
    LPar:        t.State     # (
    RPar:        t.State     # )
    Lsqb:        t.State     # [
    Rsqb:        t.State     # ]
    LBrace:      t.State     # {
    RBrace:      t.State     # }
    Comma:       t.State     # ,
    Colon:       t.State     # :
    Dot:         t.State     # .
    Semi:        t.State    # ;
    At:          t.State    # @
    Equal:       t.State    # =
    RArrow:      t.State    # ->
    PlusEq:      t.State    # +=
    MinusEq:     t.State    # -=
    StarEq:      t.State    # *=
    SlashEq:     t.State    # /=
    DSlashEq:    t.State    # //=
    PercentEq:   t.State    # %=
    AtEq:        t.State    # @=
    AmpEq:       t.State    # &=
    VBarEq:      t.State    # |=
    CaretEq:     t.State    # ^=
    GtGtEq:      t.State    # >>=
    LtLtEq:      t.State    # <<=
    StarEqEq:    t.State    # **=
    DSlash:      t.State    # //
    StarStar:    t.State    # **
    LtLt:        t.State    # <<
    GtGt:        t.State    # >>
    LessEq:      t.State    # <=
    GreaterEq:   t.State    # >=
    EqEq:        t.State    # ==
    ExclaimEq:   t.State    # !=
    Less:        t.State    # <
    Greater:     t.State    # >
    Plus:        t.State    # +
    Minus:       t.State    # -
    Star:        t.State    # *
    Slash:       t.State    # /
    Percent:     t.State    # %
    Amp:         t.State    # &
    VBar:        t.State    # |
    Caret:       t.State    # ^
    Tilde:       t.State    # ~
    ColonEq:     t.State    # :=
    Ellipsis:    t.State    # ...
    Bang:        t.State    # ! (非标准，用于解析容错)


# ============================================================
# Token 结构体
# ============================================================
class Token:
    type: t.CInt               # Token 类型（TokenType.EndMarker/TokenType.NewLine/TokenType.Name/...）
    op_subtype: t.CInt         # 运算符子类型（OP_*），仅 type==TokenType.Op 时有效
    kw_subtype: t.CInt         # 关键字子类型（KW_*），仅 type==TokenType.Name 且是关键字时有效
    str_val: str  # token 文本（NUL 结尾，从 pool 分配）
    int_val: t.CInt64T         # 整数值（TokenType.Number 用）
    float_val: t.CDouble       # 浮点值（TokenType.Number 用）
    is_float: t.CInt           # 1=浮点数, 0=整数
    is_complex: t.CInt         # 1=复数, 0=实数
    lineno: t.CInt             # 起始行号
    col_offset: t.CInt         # 起始列偏移
    end_lineno: t.CInt         # 结束行号
    end_col_offset: t.CInt     # 结束列偏移
    next: Token | t.CPtr       # 链表下一个 token

    def __new__(self, pool: memhub.MemManager | t.CPtr):
        """从 mpool 分配 Token 结构体内存并零初始化"""
        ptr: Token | t.CPtr = pool.alloc(Token.__sizeof__())
        if ptr:
            string.memset(ptr, 0, Token.__sizeof__())
        return ptr


# ============================================================
# 关键字查找表
# 由于 TransPyC 无 dict 字面量，用链表实现
# ============================================================
class KwEntry:
    name: str
    kw_id: t.CInt
    next: KwEntry | t.CPtr

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


# 全局关键字链表头（懒初始化）
_kw_head: KwEntry | t.CPtr = None
_kw_pool: memhub.MemManager | t.CPtr = None


def _kw_intern(pool: memhub.MemManager | t.CPtr, name: str, kw_id: t.CInt):
    """将关键字名注册到链表"""
    global _kw_head
    entry: KwEntry | t.CPtr = KwEntry(pool)
    if entry == None: return
    slen: t.CSizeT = string.strlen(name)
    buf: str = pool.alloc(slen + 1)
    if buf == None: return
    string.memcpy(buf, name, slen + 1)
    entry.name = buf
    entry.kw_id = kw_id
    entry.next = _kw_head
    _kw_head = entry


def _kw_lookup(name: str) -> t.CInt:
    """查找关键字，返回 kw_id（0 表示非关键字）"""
    cur: KwEntry | t.CPtr = _kw_head
    while cur != None:
        if string.strcmp(cur.name, name) == 0:
            return cur.kw_id
        cur = cur.next
    return 0


def _init_keywords(pool: memhub.MemManager | t.CPtr):
    """初始化关键字表（仅一次）"""
    global _kw_head, _kw_pool
    if _kw_head != None: return
    _kw_pool = pool
    _kw_intern(pool, "False", Keyword.False_)
    _kw_intern(pool, "None", Keyword.None_)
    _kw_intern(pool, "True", Keyword.True_)
    _kw_intern(pool, "and", Keyword.And)
    _kw_intern(pool, "as", Keyword.As)
    _kw_intern(pool, "assert", Keyword.Assert)
    _kw_intern(pool, "async", Keyword.Async)
    _kw_intern(pool, "await", Keyword.Await)
    _kw_intern(pool, "break", Keyword.Break)
    _kw_intern(pool, "class", Keyword.Class)
    _kw_intern(pool, "continue", Keyword.Continue)
    _kw_intern(pool, "def", Keyword.Def)
    _kw_intern(pool, "del", Keyword.Del)
    _kw_intern(pool, "elif", Keyword.Elif)
    _kw_intern(pool, "else", Keyword.Else)
    _kw_intern(pool, "except", Keyword.Except)
    _kw_intern(pool, "finally", Keyword.Finally)
    _kw_intern(pool, "for", Keyword.For)
    _kw_intern(pool, "from", Keyword.From)
    _kw_intern(pool, "global", Keyword.Global)
    _kw_intern(pool, "if", Keyword.If)
    _kw_intern(pool, "import", Keyword.Import)
    _kw_intern(pool, "in", Keyword.In)
    _kw_intern(pool, "is", Keyword.Is)
    _kw_intern(pool, "lambda", Keyword.Lambda)
    _kw_intern(pool, "nonlocal", Keyword.Nonlocal)
    _kw_intern(pool, "not", Keyword.Not)
    _kw_intern(pool, "or", Keyword.Or)
    _kw_intern(pool, "pass", Keyword.Pass)
    _kw_intern(pool, "raise", Keyword.Raise)
    _kw_intern(pool, "return", Keyword.Return)
    _kw_intern(pool, "try", Keyword.Try)
    _kw_intern(pool, "while", Keyword.While)
    _kw_intern(pool, "with", Keyword.With)
    _kw_intern(pool, "yield", Keyword.Yield)
    _kw_intern(pool, "match", Keyword.Match)
    _kw_intern(pool, "case", Keyword.Case)
    _kw_intern(pool, "type", Keyword.Type)


# ============================================================
# 运算符查找表
# 由于 TransPyC 无 dict，用数组+线性查找
# 运算符按长度降序排列，以便贪婪匹配
# ============================================================
class OpEntry:
    name: str   # 运算符文本（如 "==", "+="）
    op_id: t.CInt
    length: t.CInt
    next: OpEntry | t.CPtr

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


_op_head: OpEntry | t.CPtr = None


def _op_intern(pool: memhub.MemManager | t.CPtr, name: str, op_id: t.CInt):
    global _op_head
    slen: t.CSizeT = string.strlen(name)
    entry: OpEntry | t.CPtr = OpEntry(pool)
    if entry == None: return
    buf: str = pool.alloc(slen + 1)
    if buf == None: return
    string.memcpy(buf, name, slen + 1)
    entry.name = buf
    entry.op_id = op_id
    entry.length = t.CInt(slen)
    entry.next = _op_head
    _op_head = entry


def _init_operators(pool: memhub.MemManager | t.CPtr):
    """初始化运算符表（按长度降序注册，便于贪婪匹配）"""
    global _op_head
    if _op_head != None: return
    # 3 字符运算符
    _op_intern(pool, "**=", TokOp.StarEqEq)
    _op_intern(pool, "//=", TokOp.DSlashEq)
    _op_intern(pool, ">>=", TokOp.GtGtEq)
    _op_intern(pool, "<<=", TokOp.LtLtEq)
    _op_intern(pool, "...", TokOp.Ellipsis)
    # 2 字符运算符
    _op_intern(pool, "->", TokOp.RArrow)
    _op_intern(pool, "+=", TokOp.PlusEq)
    _op_intern(pool, "-=", TokOp.MinusEq)
    _op_intern(pool, "*=", TokOp.StarEq)
    _op_intern(pool, "/=", TokOp.SlashEq)
    _op_intern(pool, "%=", TokOp.PercentEq)
    _op_intern(pool, "@=", TokOp.AtEq)
    _op_intern(pool, "&=", TokOp.AmpEq)
    _op_intern(pool, "|=", TokOp.VBarEq)
    _op_intern(pool, "^=", TokOp.CaretEq)
    _op_intern(pool, "//", TokOp.DSlash)
    _op_intern(pool, "**", TokOp.StarStar)
    _op_intern(pool, "<<", TokOp.LtLt)
    _op_intern(pool, ">>", TokOp.GtGt)
    _op_intern(pool, "<=", TokOp.LessEq)
    _op_intern(pool, ">=", TokOp.GreaterEq)
    _op_intern(pool, "==", TokOp.EqEq)
    _op_intern(pool, "!=", TokOp.ExclaimEq)
    _op_intern(pool, ":=", TokOp.ColonEq)
    # 1 字符运算符
    _op_intern(pool, "(", TokOp.LPar)
    _op_intern(pool, ")", TokOp.RPar)
    _op_intern(pool, "[", TokOp.Lsqb)
    _op_intern(pool, "]", TokOp.Rsqb)
    _op_intern(pool, "{", TokOp.LBrace)
    _op_intern(pool, "}", TokOp.RBrace)
    _op_intern(pool, ",", TokOp.Comma)
    _op_intern(pool, ":", TokOp.Colon)
    _op_intern(pool, ".", TokOp.Dot)
    _op_intern(pool, ";", TokOp.Semi)
    _op_intern(pool, "@", TokOp.At)
    _op_intern(pool, "=", TokOp.Equal)
    _op_intern(pool, "<", TokOp.Less)
    _op_intern(pool, ">", TokOp.Greater)
    _op_intern(pool, "+", TokOp.Plus)
    _op_intern(pool, "-", TokOp.Minus)
    _op_intern(pool, "*", TokOp.Star)
    _op_intern(pool, "/", TokOp.Slash)
    _op_intern(pool, "%", TokOp.Percent)
    _op_intern(pool, "&", TokOp.Amp)
    _op_intern(pool, "|", TokOp.VBar)
    _op_intern(pool, "^", TokOp.Caret)
    _op_intern(pool, "~", TokOp.Tilde)


def _init_tables(pool: memhub.MemManager | t.CPtr):
    """初始化所有查找表（幂等）"""
    _init_keywords(pool)
    _init_operators(pool)


# ============================================================
# Token 创建辅助函数
# ============================================================

def new_token(pool: memhub.MemManager | t.CPtr, ttype: t.CInt, lineno: t.CInt,
              col_offset: t.CInt) -> Token | t.CPtr:
    """创建一个空 Token，调用方填充字段"""
    tok: Token | t.CPtr = Token(pool)
    if tok == None: return None
    tok.type = ttype
    tok.lineno = lineno
    tok.col_offset = col_offset
    tok.end_lineno = lineno
    tok.end_col_offset = col_offset
    return tok


def token_set_str(pool: memhub.MemManager | t.CPtr, tok: Token | t.CPtr,
                  src: str, start: t.CSizeT, length: t.CSizeT):
    """从 src[start:start+length] 复制文本到 token.str_val

    注意：length == 0 时也分配 1 字节存 NUL，让空字符串与 NULL 指针区分开。
    """
    if tok == None: return
    buf: str = pool.alloc(length + 1)
    if buf == None: return
    i: t.CSizeT = 0
    while i < length:
        buf[i] = src[start + i]
        i += 1
    buf[length] = '\0'
    tok.str_val = buf


def token_set_str_literal(pool: memhub.MemManager | t.CPtr, tok: Token | t.CPtr,
                          text: str):
    """直接复制一个 C 字符串到 token.str_val"""
    if tok == None or text == None: return
    slen: t.CSizeT = string.strlen(text)
    buf: str = pool.alloc(slen + 1)
    if buf == None: return
    string.memcpy(buf, text, slen + 1)
    tok.str_val = buf
