{-# 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