expandSugar dsl (PDoBlock ds)
    = expandSugar dsl $ debind (dsl_bind dsl) (block (dsl_bind dsl) ds)
  where
    block b [DoExp fc tm] = tm
    block b [a] = PElabError (Msg "Last statement in do block must be an expression")
    block b (DoBind fc n nfc tm : rest)
        = PApp fc b [pexp tm, pexp (PLam fc n nfc Placeholder (block b rest))]
    block b (DoBindP fc p tm alts : rest)
        = PApp fc b [pexp tm, pexp (PLam fc (sMN 0 "__bpat") NoFC Placeholder
                                   (PCase fc (PRef fc [] (sMN 0 "__bpat"))
                                             ((p, block b rest) : alts)))]
    block b (DoLet fc rc n nfc ty tm : rest)
        = PLet fc rc n nfc ty tm (block b rest)
    block b (DoLetP fc p tm alts : rest)
        = PCase fc tm ((p, block b rest) : alts)
    block b (DoRewrite fc h : rest)
        = PRewrite fc Nothing h (block b rest) Nothing
    block b (DoExp fc tm : rest)
        = PApp fc b
            [pexp tm,
             pexp (PLam fc (sMN 0 "__bindx") NoFC (mkTy tm) (block b rest))]
        where mkTy (PCase _ _ _) = PRef fc [] unitTy
              mkTy (PMetavar _ _) = PRef fc [] unitTy
              mkTy _ = Placeholder
    block b _ = PElabError (Msg "Invalid statement in do block")
expandSugar dsl (PDoBlock ds)
    = expandSugar dsl $ debind (dsl_bind dsl) (block (dsl_bind dsl) ds)
  where
    block b [DoExp fc tm] = tm
    block b [a] = PElabError (Msg "Last statement in do block must be an expression")
    block b (DoBind fc n nfc tm : rest)
        = PApp fc b [pexp tm, pexp (PLam fc n nfc Placeholder (block b rest))]
    block b (DoBindP fc p tm alts : rest)
        = PApp fc b [pexp tm, pexp (PLam fc (sMN 0 "__bpat") NoFC Placeholder
                                   (PCase fc (PRef fc [] (sMN 0 "__bpat"))
                                             ((p, block b rest) : alts)))]
    block b (DoLet fc rc n nfc ty tm : rest)
        = PLet fc rc n nfc ty tm (block b rest)
    block b (DoLetP fc p tm alts : rest)
        = PCase fc tm ((p, block b rest) : alts)
    block b (DoRewrite fc h : rest)
        = PRewrite fc Nothing h (block b rest) Nothing
    block b (DoExp fc tm : rest)
        = PApp fc b
            [pexp tm,
             pexp (PLam fc (sMN 0 "__bindx") NoFC (mkTy tm) (block b rest))]
        where mkTy (PCase _ _ _) = PRef fc [] unitTy
              mkTy (PMetavar _ _) = PRef fc [] unitTy
              mkTy _ = Placeholder
    block b _ = PElabError (Msg "Invalid statement in do block")
expandSugar dsl (PDoBlock ds)
    = expandSugar dsl $ debind (dsl_bind dsl) (block (dsl_bind dsl) ds)
  where
    block b [DoExp fc tm] = tm
    block b [a] = PElabError (Msg "Last statement in do block must be an expression")
    block b (DoBind fc n nfc tm : rest)
        = PApp fc b [pexp tm, pexp (PLam fc n nfc Placeholder (block b rest))]
    block b (DoBindP fc p tm alts : rest)
        = PApp fc b [pexp tm, pexp (PLam fc (sMN 0 "__bpat") NoFC Placeholder
                                   (PCase fc (PRef fc [] (sMN 0 "__bpat"))
                                             ((p, block b rest) : alts)))]
    block b (DoLet fc rc n nfc ty tm : rest)
        = PLet fc rc n nfc ty tm (block b rest)
    block b (DoLetP fc p tm alts : rest)
        = PCase fc tm ((p, block b rest) : alts)
    block b (DoRewrite fc h : rest)
        = PRewrite fc Nothing h (block b rest) Nothing
    block b (DoExp fc tm : rest)
        = PApp fc b
            [pexp tm,
             pexp (PLam fc (sMN 0 "__bindx") NoFC (mkTy tm) (block b rest))]
        where mkTy (PCase _ _ _) = PRef fc [] unitTy
              mkTy (PMetavar _ _) = PRef fc [] unitTy
              mkTy _ = Placeholder
    block b _ = PElabError (Msg "Invalid statement in do block")