packages feed

g2-0.2.0.0: src/G2/Preprocessing/AdjustTypes.hs

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}

module G2.Preprocessing.AdjustTypes (adjustTypes) where

import G2.Language.AST
import G2.Language

adjustTypes :: ASTContainer t Expr => State t -> State t
adjustTypes = wrapInteger . unpackString

-- | wrapInteger
-- GHC may represent an Integer as:
-- ((fromInteger [Dict]) LitInt)
-- Which makes it hard for us to correctly implement fromInteger in G2.
-- So we put in our Prelude:
-- data Integer = Integer Int#
-- and change ((fromInteger [Dict]) LitInteger) to:
-- ((fromInteger [Dict]) (dcInteger LitInt))
wrapInteger :: ASTContainer t Expr => State t -> State t
wrapInteger s@(State {known_values = kv, type_env = tenv}) = modifyASTs (wrapInteger' (mkDCInteger kv tenv)) s

wrapInteger' :: Expr -> Expr -> Expr
wrapInteger' dcIntgr (Lit (LitInteger i)) = App dcIntgr (Lit . LitInt $ fromInteger i)
wrapInteger' _ e = e

-- | GHC may represent strings as:
-- (App 
--      (Var 
--          (Id 
--              (Name "$unpackCString" (Just "GHC.CString") 0) 
--              (TyFun (TyCon (Name "Addr#" (Just "GHC.Prim") 3674937295934324738) []) (TyCon (Name "$" (Just "GHC.Types") 0) [TyCon (Name "Char" (Just "GHC.Types") 8214565720323798834) []]))
--          )
--      ) 
--      (Lit (LitString "\"HERE\""))
-- )
-- We remove $unpackCString, and convert the LitString to a list
unpackString :: ASTContainer t Expr => State t -> State t
unpackString s@(State {type_env = tenv, known_values = kv}) = modifyASTs (unpackString' tenv kv) s

unpackString' :: TypeEnv -> KnownValues -> Expr -> Expr
unpackString' tenv kv (App (Var (Id (Name "unpackCString#" _ _ _) _)) e) = unpackString' tenv kv e
unpackString' tenv kv (Lit (LitString s)) = 
    let
        cns = App (mkCons kv tenv) (Type (tyChar kv))
        em = App (mkEmpty kv tenv) (Type (tyChar kv))

        char = mkDCChar kv tenv
    in
    foldr App em $ map (App cns . App char . Lit . LitChar) s
unpackString' _ _ e = e