from dataclasses import dataclass
from typing import Any, Union, List, Optional

from taihe.utils.sources import SourceLocation


class TaiheAST:
    @dataclass(kw_only=True)
    class any:
        loc: SourceLocation

        def _accept(self, visitor) -> Any:
            raise NotImplementedError()


    @dataclass
    class TOKEN(any):
        text: str

        def __str__(self):
            return self.text

        def _accept(self, visitor) -> Any:
            return visitor.visit_token(self)

    @dataclass
    class Spec(any):
        uses: List["TaiheAST.Use"]
        fields: List["TaiheAST.SpecField"]
        inner_attrs: List["TaiheAST.ScopeAttr"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_spec(self)

    Use = Union[
        "TaiheAST.UsePackage",
        "TaiheAST.UseSymbol",
    ]

    @dataclass
    class PkgName(any):
        parts: List["TaiheAST.TOKEN"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_pkg_name(self)

    @dataclass
    class DeclAliasPair(any):
        decl_name: "TaiheAST.TOKEN"
        decl_alias: Optional["TaiheAST.TOKEN"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_decl_alias_pair(self)

    SpecField = Union[
        "TaiheAST.Struct",
        "TaiheAST.GlobalFunction",
        "TaiheAST.Union",
        "TaiheAST.Interface",
        "TaiheAST.Enum",
    ]

    EnumItem = Union[
        "TaiheAST.EnumProperty",
    ]

    StructField = Union[
        "TaiheAST.StructProperty",
    ]

    UnionField = Union[
        "TaiheAST.UnionProperty",
    ]

    InterfaceField = Union[
        "TaiheAST.InterfaceFunction",
    ]

    @dataclass
    class InterfaceParent(any):
        forward_attrs: List["TaiheAST.DeclAttr"]
        ty: "TaiheAST.Type"

        def _accept(self, visitor) -> Any:
            return visitor.visit_interface_parent(self)

    @dataclass
    class Parameter(any):
        forward_attrs: List["TaiheAST.DeclAttr"]
        name: "TaiheAST.TOKEN"
        ty: "TaiheAST.Type"

        def _accept(self, visitor) -> Any:
            return visitor.visit_parameter(self)

    @dataclass
    class ScopeAttr(any):
        name: "TaiheAST.TOKEN"
        args: List["TaiheAST.AttrArg"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_scope_attr(self)

    @dataclass
    class DeclAttr(any):
        name: "TaiheAST.TOKEN"
        args: List["TaiheAST.AttrArg"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_decl_attr(self)

    AttrArg = Union[
        "TaiheAST.NamedAttrArg",
        "TaiheAST.UnnamedAttrArg",
    ]

    Type = Union[
        "TaiheAST.ShortType",
        "TaiheAST.GenericType",
        "TaiheAST.LongType",
        "TaiheAST.CallbackType",
    ]

    AnyExpr = Union[
        "TaiheAST.IntAnyExpr",
        "TaiheAST.FloatAnyExpr",
        "TaiheAST.BoolAnyExpr",
        "TaiheAST.StringAnyExpr",
    ]

    FloatExpr = Union[
        "TaiheAST.ParenthesisFloatExpr",
        "TaiheAST.BinaryFloatExpr",
        "TaiheAST.UnaryFloatExpr",
        "TaiheAST.ConditionalFloatExpr",
        "TaiheAST.LiteralFloatExpr",
    ]

    IntExpr = Union[
        "TaiheAST.ConditionalIntExpr",
        "TaiheAST.ParenthesisIntExpr",
        "TaiheAST.UnaryIntExpr",
        "TaiheAST.BinaryIntExpr",
        "TaiheAST.LiteralIntExpr",
        "TaiheAST.BinaryIntShiftExpr",
    ]

    BoolExpr = Union[
        "TaiheAST.ConditionalBoolExpr",
        "TaiheAST.IntComparisonBoolExpr",
        "TaiheAST.ParenthesisBoolExpr",
        "TaiheAST.UnaryBoolExpr",
        "TaiheAST.LiteralBoolExpr",
        "TaiheAST.FloatComparisonBoolExpr",
        "TaiheAST.BinaryBoolExpr",
    ]

    StringExpr = Union[
        "TaiheAST.LiteralDocStringExpr",
        "TaiheAST.LiteralStringExpr",
        "TaiheAST.BinaryStringExpr",
    ]

    @dataclass
    class UsePackage(any):
        pkg_name: "TaiheAST.PkgName"
        pkg_alias: Optional["TaiheAST.TOKEN"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_use_package(self)

    @dataclass
    class UseSymbol(any):
        pkg_name: "TaiheAST.PkgName"
        decl_alias_pairs: List["TaiheAST.DeclAliasPair"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_use_symbol(self)

    @dataclass
    class Struct(any):
        forward_attrs: List["TaiheAST.DeclAttr"]
        name: "TaiheAST.TOKEN"
        fields: List["TaiheAST.StructField"]
        inner_attrs: List["TaiheAST.ScopeAttr"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_struct(self)

    @dataclass
    class GlobalFunction(any):
        forward_attrs: List["TaiheAST.DeclAttr"]
        name: "TaiheAST.TOKEN"
        parameters: List["TaiheAST.Parameter"]
        return_ty: Optional["TaiheAST.Type"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_global_function(self)

    @dataclass
    class Union(any):
        forward_attrs: List["TaiheAST.DeclAttr"]
        name: "TaiheAST.TOKEN"
        fields: List["TaiheAST.UnionField"]
        inner_attrs: List["TaiheAST.ScopeAttr"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_union(self)

    @dataclass
    class Interface(any):
        forward_attrs: List["TaiheAST.DeclAttr"]
        name: "TaiheAST.TOKEN"
        extends: List["TaiheAST.InterfaceParent"]
        fields: List["TaiheAST.InterfaceField"]
        inner_attrs: List["TaiheAST.ScopeAttr"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_interface(self)

    @dataclass
    class Enum(any):
        forward_attrs: List["TaiheAST.DeclAttr"]
        name: "TaiheAST.TOKEN"
        enum_ty: "TaiheAST.Type"
        fields: List["TaiheAST.EnumItem"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_enum(self)

    @dataclass
    class EnumProperty(any):
        forward_attrs: List["TaiheAST.DeclAttr"]
        name: "TaiheAST.TOKEN"
        val: Optional["TaiheAST.AnyExpr"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_enum_property(self)

    @dataclass
    class StructProperty(any):
        forward_attrs: List["TaiheAST.DeclAttr"]
        name: "TaiheAST.TOKEN"
        ty: "TaiheAST.Type"

        def _accept(self, visitor) -> Any:
            return visitor.visit_struct_property(self)

    @dataclass
    class UnionProperty(any):
        forward_attrs: List["TaiheAST.DeclAttr"]
        name: "TaiheAST.TOKEN"
        ty: Optional["TaiheAST.Type"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_union_property(self)

    @dataclass
    class InterfaceFunction(any):
        forward_attrs: List["TaiheAST.DeclAttr"]
        name: "TaiheAST.TOKEN"
        parameters: List["TaiheAST.Parameter"]
        return_ty: Optional["TaiheAST.Type"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_interface_function(self)

    @dataclass
    class NamedAttrArg(any):
        name: "TaiheAST.TOKEN"
        val: "TaiheAST.AnyExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_named_attr_arg(self)

    @dataclass
    class UnnamedAttrArg(any):
        val: "TaiheAST.AnyExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_unnamed_attr_arg(self)

    @dataclass
    class ShortType(any):
        forward_attrs: List["TaiheAST.DeclAttr"]
        decl_name: "TaiheAST.TOKEN"

        def _accept(self, visitor) -> Any:
            return visitor.visit_short_type(self)

    @dataclass
    class GenericType(any):
        forward_attrs: List["TaiheAST.DeclAttr"]
        decl_name: "TaiheAST.TOKEN"
        args: List["TaiheAST.Type"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_generic_type(self)

    @dataclass
    class LongType(any):
        forward_attrs: List["TaiheAST.DeclAttr"]
        pkg_name: "TaiheAST.PkgName"
        decl_name: "TaiheAST.TOKEN"

        def _accept(self, visitor) -> Any:
            return visitor.visit_long_type(self)

    @dataclass
    class CallbackType(any):
        forward_attrs: List["TaiheAST.DeclAttr"]
        parameters: List["TaiheAST.Parameter"]
        return_ty: Optional["TaiheAST.Type"]

        def _accept(self, visitor) -> Any:
            return visitor.visit_callback_type(self)

    @dataclass
    class IntAnyExpr(any):
        expr: "TaiheAST.IntExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_int_any_expr(self)

    @dataclass
    class FloatAnyExpr(any):
        expr: "TaiheAST.FloatExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_float_any_expr(self)

    @dataclass
    class BoolAnyExpr(any):
        expr: "TaiheAST.BoolExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_bool_any_expr(self)

    @dataclass
    class StringAnyExpr(any):
        expr: "TaiheAST.StringExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_string_any_expr(self)

    @dataclass
    class ParenthesisFloatExpr(any):
        expr: "TaiheAST.FloatExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_parenthesis_float_expr(self)

    @dataclass
    class BinaryFloatExpr(any):
        left: "TaiheAST.FloatExpr"
        op: "TaiheAST.TOKEN"
        right: "TaiheAST.FloatExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_binary_float_expr(self)

    @dataclass
    class UnaryFloatExpr(any):
        op: "TaiheAST.TOKEN"
        expr: "TaiheAST.FloatExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_unary_float_expr(self)

    @dataclass
    class ConditionalFloatExpr(any):
        cond: "TaiheAST.BoolExpr"
        then_expr: "TaiheAST.FloatExpr"
        else_expr: "TaiheAST.FloatExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_conditional_float_expr(self)

    @dataclass
    class LiteralFloatExpr(any):
        val: "TaiheAST.TOKEN"

        def _accept(self, visitor) -> Any:
            return visitor.visit_literal_float_expr(self)

    @dataclass
    class ConditionalIntExpr(any):
        cond: "TaiheAST.BoolExpr"
        then_expr: "TaiheAST.IntExpr"
        else_expr: "TaiheAST.IntExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_conditional_int_expr(self)

    @dataclass
    class ParenthesisIntExpr(any):
        expr: "TaiheAST.IntExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_parenthesis_int_expr(self)

    @dataclass
    class UnaryIntExpr(any):
        op: "TaiheAST.TOKEN"
        expr: "TaiheAST.IntExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_unary_int_expr(self)

    @dataclass
    class BinaryIntExpr(any):
        left: "TaiheAST.IntExpr"
        op: "TaiheAST.TOKEN"
        right: "TaiheAST.IntExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_binary_int_expr(self)

    @dataclass
    class LiteralIntExpr(any):
        val: "TaiheAST.TOKEN"

        def _accept(self, visitor) -> Any:
            return visitor.visit_literal_int_expr(self)

    @dataclass
    class BinaryIntShiftExpr(any):
        left: "TaiheAST.IntExpr"
        ch: "TaiheAST.TOKEN"
        right: "TaiheAST.IntExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_binary_int_shift_expr(self)

    @dataclass
    class ConditionalBoolExpr(any):
        cond: "TaiheAST.BoolExpr"
        then_expr: "TaiheAST.BoolExpr"
        else_expr: "TaiheAST.BoolExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_conditional_bool_expr(self)

    @dataclass
    class IntComparisonBoolExpr(any):
        left: "TaiheAST.IntExpr"
        op: "TaiheAST.TOKEN"
        right: "TaiheAST.IntExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_int_comparison_bool_expr(self)

    @dataclass
    class ParenthesisBoolExpr(any):
        expr: "TaiheAST.BoolExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_parenthesis_bool_expr(self)

    @dataclass
    class UnaryBoolExpr(any):
        op: "TaiheAST.TOKEN"
        expr: "TaiheAST.BoolExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_unary_bool_expr(self)

    @dataclass
    class LiteralBoolExpr(any):
        val: "TaiheAST.TOKEN"

        def _accept(self, visitor) -> Any:
            return visitor.visit_literal_bool_expr(self)

    @dataclass
    class FloatComparisonBoolExpr(any):
        left: "TaiheAST.FloatExpr"
        op: "TaiheAST.TOKEN"
        right: "TaiheAST.FloatExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_float_comparison_bool_expr(self)

    @dataclass
    class BinaryBoolExpr(any):
        left: "TaiheAST.BoolExpr"
        op: "TaiheAST.TOKEN"
        right: "TaiheAST.BoolExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_binary_bool_expr(self)

    @dataclass
    class LiteralDocStringExpr(any):
        val: "TaiheAST.TOKEN"

        def _accept(self, visitor) -> Any:
            return visitor.visit_literal_doc_string_expr(self)

    @dataclass
    class LiteralStringExpr(any):
        val: "TaiheAST.TOKEN"

        def _accept(self, visitor) -> Any:
            return visitor.visit_literal_string_expr(self)

    @dataclass
    class BinaryStringExpr(any):
        left: "TaiheAST.StringExpr"
        right: "TaiheAST.StringExpr"

        def _accept(self, visitor) -> Any:
            return visitor.visit_binary_string_expr(self)

