///|
pub(all) enum Literal {
  F64(Double)
  F32(Float)
  F32Exact(Float)
  F16(Double)
  U16(Int32)
  I16(Int32)
  U32(UInt32)
  I32(Int32)
  U64(UInt64)
  I64(Int64)
  Bool(Bool)
  AbstractInt(Int64)
  AbstractFloat(Double)
} derive(Eq, Debug)

///|
pub(all) struct Override {
  name : String?
  id : Int32?
  ty : Handle
  init : Handle?
} derive(Eq, Debug)

///|
pub(all) struct Constant {
  name : String?
  source_start : Int32
  ty : Handle
  init : Handle
} derive(Eq, Debug)

///|
pub(all) struct ResourceBinding {
  group : Int32
  binding : Int32
} derive(Eq, Debug)

///|
pub(all) struct GlobalVariable {
  name : String?
  space : AddressSpace
  binding : ResourceBinding?
  ty : Handle
  init : Handle?
  memory_decorations : MemoryDecorations
} derive(Eq, Debug)

///|
pub(all) enum LocalVariableKind {
  Var
  Let
} derive(Eq, Debug)

///|
pub(all) struct LocalVariable {
  name : String?
  kind : LocalVariableKind
  generated_temporary : Bool
  mut generated_temporary_store_value_reference : Bool
  short_circuit_result : Bool
  ty : Handle
  init : Handle?
} derive(Eq, Debug)

///|
pub(all) enum UnaryOperator {
  Negate
  LogicalNot
  BitwiseNot
} derive(Eq, Debug)

///|
pub(all) enum BinaryOperator {
  Add
  Subtract
  Multiply
  Divide
  Modulo
  Equal
  NotEqual
  Less
  LessEqual
  Greater
  GreaterEqual
  And
  ExclusiveOr
  InclusiveOr
  LogicalAnd
  LogicalOr
  ShiftLeft
  ShiftRight
} derive(Eq, Debug)

///|
pub(all) enum AtomicFunction {
  Load
  Store
  Add
  Subtract
  And
  ExclusiveOr
  InclusiveOr
  Min
  Max
  Exchange
  CompareExchangeWeak
} derive(Eq, Debug)

///|
pub(all) enum DerivativeControl {
  Coarse
  Fine
  None
} derive(Eq, Debug)

///|
pub(all) enum DerivativeAxis {
  X
  Y
  Width
} derive(Eq, Debug)

///|
pub(all) enum RelationalFunction {
  All
  Any
  IsNan
  IsInf
} derive(Eq, Debug)

///|
pub(all) enum MathFunction {
  Abs
  Min
  Max
  Clamp
  Saturate
  Cos
  Cosh
  Sin
  Sinh
  Tan
  Tanh
  Acos
  Asin
  Atan
  Atan2
  Asinh
  Acosh
  Atanh
  Radians
  Degrees
  Ceil
  Floor
  Round
  Fract
  Trunc
  Modf
  Frexp
  Ldexp
  Exp
  Exp2
  Log
  Log2
  Pow
  Dot
  Dot4I8Packed
  Dot4U8Packed
  Outer
  Cross
  Distance
  Length
  Normalize
  FaceForward
  Reflect
  Refract
  Sign
  Fma
  Mix
  Step
  SmoothStep
  Sqrt
  InverseSqrt
  Inverse
  Transpose
  Determinant
  QuantizeToF16
  CountTrailingZeros
  CountLeadingZeros
  CountOneBits
  ReverseBits
  ExtractBits
  InsertBits
  FirstTrailingBit
  FirstLeadingBit
  Pack4x8snorm
  Pack4x8unorm
  Pack2x16snorm
  Pack2x16unorm
  Pack2x16float
  Pack4xI8
  Pack4xU8
  Pack4xI8Clamp
  Pack4xU8Clamp
  Unpack4x8snorm
  Unpack4x8unorm
  Unpack2x16snorm
  Unpack2x16unorm
  Unpack2x16float
  Unpack4xI8
  Unpack4xU8
} derive(Eq, Debug)

///|
pub fn wgsl_ir_math_primary_result_operand(
  math_function : MathFunction,
  a : Handle,
  b : Handle?,
  c : Handle?,
  d : Handle?,
) -> Handle? {
  ignore(d)
  match math_function {
    Step => b
    SmoothStep => c
    Min
    | Max
    | Clamp
    | FaceForward
    | Reflect
    | Refract
    | Fma
    | Mix
    | Pow
    | Atan2 => Some(a)
    _ => None
  }
}

///|
pub(all) enum SampleLevel {
  Auto
  Zero
  Exact(Handle)
  Bias(Handle)
  Gradient(Handle, Handle)
} derive(Eq, Debug)

///|
pub(all) enum ImageQuery {
  Size(Handle?)
  NumLevels
  NumLayers
  NumSamples
} derive(Eq, Debug)

///|
pub(all) enum SwizzleComponent {
  X
  Y
  Z
  W
} derive(Eq, Debug)

///|
pub(all) enum Direction {
  X
  Y
  Diagonal
} derive(Eq, Debug)

///|
pub(all) enum GatherMode {
  BroadcastFirst
  Broadcast(Handle)
  Shuffle(Handle)
  ShuffleDown(Handle)
  ShuffleUp(Handle)
  ShuffleXor(Handle)
  QuadBroadcast(Handle)
  QuadSwap(Direction)
} derive(Eq, Debug)

///|
pub(all) enum SubgroupOperation {
  All
  Any
  Add
  Mul
  Min
  Max
  And
  Or
  Xor
} derive(Eq, Debug)

///|
pub(all) enum SubgroupFunction {
  Ballot
  All
  Any
  Add
  Mul
  Max
  Min
  And
  Or
  Xor
  ExclusiveAdd
  ExclusiveMul
  InclusiveAdd
  InclusiveMul
  BroadcastFirst
  Broadcast
  Shuffle
  ShuffleDown
  ShuffleUp
  ShuffleXor
  QuadBroadcast
  QuadSwapX
  QuadSwapY
  QuadSwapDiagonal
} derive(Eq, Debug)

///|
pub(all) enum CollectiveOperation {
  Reduce
  InclusiveScan
  ExclusiveScan
} derive(Eq, Debug)

///|
pub(all) struct CooperativeData {
  pointer : Handle
  stride : Handle
  row_major : Bool
} derive(Eq, Debug)

///|
pub(all) enum Expression {
  Literal(Literal)
  Constant(Handle)
  Override(Handle)
  ZeroValue(Handle)
  Compose(Handle, Array[Handle])
  Access(Handle, Handle)
  AccessIndex(Handle, Int32)
  Component(Handle, SwizzleComponent)
  Splat(VectorSize, Handle)
  Swizzle(VectorSize, Handle, Array[SwizzleComponent])
  FunctionArgument(Int32)
  GlobalVariable(Handle)
  LocalVariable(Handle)
  Load(Handle)
  AddressOf(Handle, Handle)
  AtomicCall(AtomicFunction, Array[Handle])
  ImageSample(
    Handle,
    Handle,
    SwizzleComponent?,
    Handle,
    Handle?,
    Handle?,
    SampleLevel,
    Handle?,
    Bool
  )
  ImageLoad(Handle, Handle, Handle?, Handle?, Handle?)
  ImageQuery(Handle, ImageQuery)
  Unary(UnaryOperator, Handle)
  Binary(BinaryOperator, Handle, Handle)
  FunctionCall(Handle, Array[Handle])
  Select(Handle, Handle, Handle)
  Bitcast(Handle, Handle)
  Derivative(DerivativeAxis, DerivativeControl, Handle)
  Relational(RelationalFunction, Handle)
  Math(MathFunction, Handle, Handle?, Handle?, Handle?)
  As(Handle, ScalarKind, Int32?)
  CallResult(Handle)
  AtomicResult(Handle, Bool)
  WorkGroupUniformLoadResult(Handle)
  WorkGroupUniformLoad(Handle)
  ArrayLength(Handle)
  RayQueryInitialize(Handle, Handle, Handle)
  RayQueryProceed(Handle)
  RayQueryGenerateIntersection(Handle, Handle)
  RayQueryConfirmIntersection(Handle)
  RayQueryTerminate(Handle)
  RayQueryVertexPositions(Handle, Bool)
  RayQueryProceedResult
  RayQueryGetIntersection(Handle, Bool)
  SubgroupCall(SubgroupFunction, Array[Handle])
  SubgroupBallotResult
  SubgroupOperationResult(Handle)
  CooperativeLoad(
    CooperativeSize,
    CooperativeSize,
    CooperativeRole,
    CooperativeData
  )
  CooperativeMultiplyAdd(Handle, Handle, Handle)
} derive(Eq, Debug)

///|
pub extend AtomicFunction with Debug::{to_repr}

///|
pub extend AtomicFunction with Eq::{not_equal, equal}

///|
pub extend BinaryOperator with Debug::{to_repr}

///|
pub extend BinaryOperator with Eq::{not_equal, equal}

///|
pub extend CollectiveOperation with Debug::{to_repr}

///|
pub extend CollectiveOperation with Eq::{not_equal, equal}

///|
pub extend Constant with Debug::{to_repr}

///|
pub extend Constant with Eq::{not_equal, equal}

///|
pub extend CooperativeData with Debug::{to_repr}

///|
pub extend CooperativeData with Eq::{not_equal, equal}

///|
pub extend DerivativeAxis with Debug::{to_repr}

///|
pub extend DerivativeAxis with Eq::{not_equal, equal}

///|
pub extend DerivativeControl with Debug::{to_repr}

///|
pub extend DerivativeControl with Eq::{not_equal, equal}

///|
pub extend Direction with Debug::{to_repr}

///|
pub extend Direction with Eq::{not_equal, equal}

///|
pub extend Expression with Debug::{to_repr}

///|
pub extend Expression with Eq::{not_equal, equal}

///|
pub extend GatherMode with Debug::{to_repr}

///|
pub extend GatherMode with Eq::{not_equal, equal}

///|
pub extend GlobalVariable with Debug::{to_repr}

///|
pub extend GlobalVariable with Eq::{not_equal, equal}

///|
pub extend ImageQuery with Debug::{to_repr}

///|
pub extend ImageQuery with Eq::{not_equal, equal}

///|
pub extend Literal with Debug::{to_repr}

///|
pub extend Literal with Eq::{not_equal, equal}

///|
pub extend LocalVariable with Debug::{to_repr}

///|
pub extend LocalVariable with Eq::{not_equal, equal}

///|
pub extend LocalVariableKind with Debug::{to_repr}

///|
pub extend LocalVariableKind with Eq::{not_equal, equal}

///|
pub extend MathFunction with Debug::{to_repr}

///|
pub extend MathFunction with Eq::{not_equal, equal}

///|
pub extend Override with Debug::{to_repr}

///|
pub extend Override with Eq::{not_equal, equal}

///|
pub extend RelationalFunction with Debug::{to_repr}

///|
pub extend RelationalFunction with Eq::{not_equal, equal}

///|
pub extend ResourceBinding with Debug::{to_repr}

///|
pub extend ResourceBinding with Eq::{not_equal, equal}

///|
pub extend SampleLevel with Debug::{to_repr}

///|
pub extend SampleLevel with Eq::{not_equal, equal}

///|
pub extend SubgroupFunction with Debug::{to_repr}

///|
pub extend SubgroupFunction with Eq::{not_equal, equal}

///|
pub extend SubgroupOperation with Debug::{to_repr}

///|
pub extend SubgroupOperation with Eq::{not_equal, equal}

///|
pub extend SwizzleComponent with Debug::{to_repr}

///|
pub extend SwizzleComponent with Eq::{not_equal, equal}

///|
pub extend UnaryOperator with Debug::{to_repr}

///|
pub extend UnaryOperator with Eq::{not_equal, equal}