namespace NubLang.Syntax;

public abstract record SyntaxNode(List<Token> Tokens);

#region Definitions

public abstract record DefinitionSyntax(List<Token> Tokens, string Name, bool Exported) : SyntaxNode(Tokens);

public record FuncParameterSyntax(List<Token> Tokens, string Name, TypeSyntax Type) : SyntaxNode(Tokens);

public record FuncPrototypeSyntax(List<Token> Tokens, string Name, bool Exported, string? ExternSymbol, List<FuncParameterSyntax> Parameters, TypeSyntax ReturnType) : SyntaxNode(Tokens);

public record FuncSyntax(List<Token> Tokens, FuncPrototypeSyntax Prototype, BlockSyntax? Body) : DefinitionSyntax(Tokens, Prototype.Name, Prototype.Exported);

public record StructFieldSyntax(List<Token> Tokens, string Name, TypeSyntax Type, ExpressionSyntax? Value) : SyntaxNode(Tokens);

public record StructSyntax(List<Token> Tokens, string Name, bool Exported, List<StructFieldSyntax> Fields) : DefinitionSyntax(Tokens, Name, Exported);

public enum UnaryOperatorSyntax
{
    Negate,
    Invert
}

public enum BinaryOperatorSyntax
{
    Equal,
    NotEqual,
    GreaterThan,
    GreaterThanOrEqual,
    LessThan,
    LessThanOrEqual,
    LogicalAnd,
    LogicalOr,
    Plus,
    Minus,
    Multiply,
    Divide,
    Modulo,
    LeftShift,
    RightShift,
    BitwiseAnd,
    BitwiseXor,
    BitwiseOr,
}

#endregion

#region Statements

public abstract record StatementSyntax(List<Token> Tokens) : SyntaxNode(Tokens);

public record BlockSyntax(List<Token> Tokens, List<StatementSyntax> Statements) : StatementSyntax(Tokens);

public record StatementExpressionSyntax(List<Token> Tokens, ExpressionSyntax Expression) : StatementSyntax(Tokens);

public record ReturnSyntax(List<Token> Tokens, ExpressionSyntax? Value) : StatementSyntax(Tokens);

public record AssignmentSyntax(List<Token> Tokens, ExpressionSyntax Target, ExpressionSyntax Value) : StatementSyntax(Tokens);

public record IfSyntax(List<Token> Tokens, ExpressionSyntax Condition, BlockSyntax Body, Variant<IfSyntax, BlockSyntax>? Else) : StatementSyntax(Tokens);

public record VariableDeclarationSyntax(List<Token> Tokens, string Name, TypeSyntax? ExplicitType, ExpressionSyntax? Assignment) : StatementSyntax(Tokens);

public record ContinueSyntax(List<Token> Tokens) : StatementSyntax(Tokens);

public record BreakSyntax(List<Token> Tokens) : StatementSyntax(Tokens);

public record DeferSyntax(List<Token> Tokens, StatementSyntax Statement) : StatementSyntax(Tokens);

public record WhileSyntax(List<Token> Tokens, ExpressionSyntax Condition, BlockSyntax Body) : StatementSyntax(Tokens);

#endregion

#region Expressions

public abstract record ExpressionSyntax(List<Token> Tokens) : SyntaxNode(Tokens);

public record BinaryExpressionSyntax(List<Token> Tokens, ExpressionSyntax Left, BinaryOperatorSyntax Operator, ExpressionSyntax Right) : ExpressionSyntax(Tokens);

public record UnaryExpressionSyntax(List<Token> Tokens, UnaryOperatorSyntax Operator, ExpressionSyntax Operand) : ExpressionSyntax(Tokens);

public record FuncCallSyntax(List<Token> Tokens, ExpressionSyntax Expression, List<ExpressionSyntax> Parameters) : ExpressionSyntax(Tokens);

public record LocalIdentifierSyntax(List<Token> Tokens, string Name) : ExpressionSyntax(Tokens);

public record ModuleIdentifierSyntax(List<Token> Tokens, string Module, string Name) : ExpressionSyntax(Tokens);

public record ArrayInitializerSyntax(List<Token> Tokens, ExpressionSyntax Capacity, TypeSyntax ElementType) : ExpressionSyntax(Tokens);

public record ArrayIndexAccessSyntax(List<Token> Tokens, ExpressionSyntax Target, ExpressionSyntax Index) : ExpressionSyntax(Tokens);

public record AddressOfSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens);

public record IntLiteralSyntax(List<Token> Tokens, string Value, int Base) : ExpressionSyntax(Tokens);

public record StringLiteralSyntax(List<Token> Tokens, string Value) : ExpressionSyntax(Tokens);

public record BoolLiteralSyntax(List<Token> Tokens, bool Value) : ExpressionSyntax(Tokens);

public record FloatLiteralSyntax(List<Token> Tokens, string Value) : ExpressionSyntax(Tokens);

public record MemberAccessSyntax(List<Token> Tokens, ExpressionSyntax Target, string Member) : ExpressionSyntax(Tokens);

public record StructInitializerSyntax(List<Token> Tokens, TypeSyntax? StructType, Dictionary<string, ExpressionSyntax> Initializers) : ExpressionSyntax(Tokens);

public record DereferenceSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens);

public record SizeBuiltinSyntax(List<Token> Tokens, TypeSyntax Type) : ExpressionSyntax(Tokens);

public record InterpretBuiltinSyntax(List<Token> Tokens, TypeSyntax Type, ExpressionSyntax Target) : ExpressionSyntax(Tokens);

public record FloatToIntBuiltinSyntax(List<Token> Tokens, TypeSyntax Type, ExpressionSyntax Value) : ExpressionSyntax(Tokens);

#endregion

#region Types

public abstract record TypeSyntax(List<Token> Tokens) : SyntaxNode(Tokens);

public record FuncTypeSyntax(List<Token> Tokens, List<TypeSyntax> Parameters, TypeSyntax ReturnType) : TypeSyntax(Tokens);

public record PointerTypeSyntax(List<Token> Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens);

public record VoidTypeSyntax(List<Token> Tokens) : TypeSyntax(Tokens);

public record IntTypeSyntax(List<Token> Tokens, bool Signed, int Width) : TypeSyntax(Tokens);

public record FloatTypeSyntax(List<Token> Tokens, int Width) : TypeSyntax(Tokens);

public record BoolTypeSyntax(List<Token> Tokens) : TypeSyntax(Tokens);

public record StringTypeSyntax(List<Token> Tokens) : TypeSyntax(Tokens);

public record CStringTypeSyntax(List<Token> Tokens) : TypeSyntax(Tokens);

public record SliceTypeSyntax(List<Token> Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens);

public record ArrayTypeSyntax(List<Token> Tokens, TypeSyntax BaseType) : TypeSyntax(Tokens);

public record ConstArrayTypeSyntax(List<Token> Tokens, TypeSyntax BaseType, long Size) : TypeSyntax(Tokens);

public record CustomTypeSyntax(List<Token> Tokens, string Module, string Name) : TypeSyntax(Tokens);

#endregion