    {-# LANGUAGE ScopedTypeVariables #-}
    {-# LANGUAGE DataKinds, GADTs, RankNTypes, KindSignatures #-}
    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE PatternSynonyms #-}

    module GHC.Wasm.ControlFlow
      ( WasmControl(..), (<>), pattern WasmIf
      , BrTableInterval(..), inclusiveInterval

      , WasmType, WasmTypeTag(..)
      , TypeList(..)
      , WasmFunctionType(..)
      )
    where

    import GHC.Prelude

    import GHC.CmmToAsm.Wasm.Types
    import GHC.Utils.Panic

    {-|
    Module      : GHC.Wasm.ControlFlow
    Description : Representation of control-flow portion of the WebAssembly instruction set
    -}

    inclusiveInterval :: Integer -> Integer -> BrTableInterval
    inclusiveInterval :: Integer -> Integer -> BrTableInterval
    inclusiveInterval Integer
    lo Integer
    hi
        | Integer
    lo Integer -> Integer -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Integer
    hi = let count :: Integer
    count = Integer
    hi Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    - Integer
    lo Integer -> Integer -> Integer
    forall a. Num a => a -> a -> a
    + Integer
    1
                     in  Integer -> Integer -> BrTableInterval
    BrTableInterval Integer
    lo Integer
    count
        | Bool
    otherwise = String -> BrTableInterval
    forall a. HasCallStack => String -> a
    panic String
    "GHC.Wasm.ControlFlow: empty interval"

    (<>) :: forall s e pre mid post
          . WasmControl s e pre mid
         -> WasmControl s e mid post
         -> WasmControl s e pre post
    <> :: forall s e (pre :: [WasmType]) (mid :: [WasmType])
           (post :: [WasmType]).
    WasmControl s e pre mid
    -> WasmControl s e mid post -> WasmControl s e pre post
    (<>) = WasmControl s e pre mid
    -> WasmControl s e mid post -> WasmControl s e pre post
    forall s e (pre :: [WasmType]) (mid :: [WasmType])
           (post :: [WasmType]).
    WasmControl s e pre mid
    -> WasmControl s e mid post -> WasmControl s e pre post
    WasmSeq
    -- N.B. Fallthrough can't be optimized away because of type checking.

    -- Syntactic sugar.
    pattern WasmIf :: WasmFunctionType pre post
                   -> e
                   -> WasmControl s e pre post
                   -> WasmControl s e pre post
                   -> WasmControl s e pre post

    pattern $mWasmIf :: forall {r} {pre :: [WasmType]} {post :: [WasmType]} {e} {s}.
    WasmControl s e pre post
    -> (WasmFunctionType pre post
        -> e -> WasmControl s e pre post -> WasmControl s e pre post -> r)
    -> ((# #) -> r)
    -> r
    $bWasmIf :: forall (pre :: [WasmType]) (post :: [WasmType]) e s.
    WasmFunctionType pre post
    -> e
    -> WasmControl s e pre post
    -> WasmControl s e pre post
    -> WasmControl s e pre post
    WasmIf ty e t f =
        WasmPush TagI32 e `WasmSeq` WasmIfTop ty t f