-- TODO:
-- Account for Instr & Instr being empty
-- Account for jumpoffset being > 2^15 - 1
gbranch :: (FieldType -> Stack -> Stack)
        -> FieldType -> Opcode -> Instr -> Instr -> Instr
gbranch f ft oc ok ko = Instr $ do
  [defaultLabel, okLabel] <- mkSystemLabels 2
  jumpOffset <- offsetToLabel okLabel
  lb <- saveLastBranch
  unInstr ifop
  InstrState { isCtrlFlow = cf
             , isLabelTable = lt } <- get
  writeBytes . packI16 $ jumpOffset
  (koCF, koLT, mkoLB) <- withCFState cf lt $ unInstr $
    ko <> condGoto Special defaultLabel
  (okCF, okLT, mokLB) <- withCFState cf lt $ unInstr $
    putLabel okLabel <> ok
  putCtrlFlow' $ CF.merge cf [okCF, koCF]
  mergeLabels [koLT, okLT]
  unInstr $ putLabel defaultLabel
  resetLastBranch $ fromMaybe lb (selectLatestLB mkoLB mokLB)
  where ifop = op oc <> modifyStack (f ft)
gbranch :: (FieldType -> Stack -> Stack)
        -> FieldType -> Opcode -> Instr -> Instr -> Instr
gbranch f ft oc ok ko = Instr $ do
  [defaultLabel, okLabel] <- mkSystemLabels 2
  jumpOffset <- offsetToLabel okLabel
  lb <- saveLastBranch
  unInstr ifop
  InstrState { isCtrlFlow = cf
             , isLabelTable = lt } <- get
  writeBytes . packI16 $ jumpOffset
  (koCF, koLT, mkoLB) <- withCFState cf lt $ unInstr $
    ko <> condGoto Special defaultLabel
  (okCF, okLT, mokLB) <- withCFState cf lt $ unInstr $
    putLabel okLabel <> ok
  putCtrlFlow' $ CF.merge cf [okCF, koCF]
  mergeLabels [koLT, okLT]
  unInstr $ putLabel defaultLabel
  resetLastBranch $ fromMaybe lb (selectLatestLB mkoLB mokLB)
  where ifop = op oc <> modifyStack (f ft)
gbranch f ft oc ok ko = Instr $ do
  [defaultLabel, okLabel] <- mkSystemLabels 2
  jumpOffset <- offsetToLabel okLabel
  lb <- saveLastBranch
  unInstr ifop
  InstrState { isCtrlFlow = cf
             , isLabelTable = lt } <- get
  writeBytes . packI16 $ jumpOffset
  (koCF, koLT, mkoLB) <- withCFState cf lt $ unInstr $
    ko <> condGoto Special defaultLabel
  (okCF, okLT, mokLB) <- withCFState cf lt $ unInstr $
    putLabel okLabel <> ok
  putCtrlFlow' $ CF.merge cf [okCF, koCF]
  mergeLabels [koLT, okLT]
  unInstr $ putLabel defaultLabel
  resetLastBranch $ fromMaybe lb (selectLatestLB mkoLB mokLB)
  where ifop = op oc <> modifyStack (f ft)