packages feed

g2-0.2.0.0: src/G2/Initialization/KnownValues.hs

{-# LANGUAGE CPP, OverloadedStrings #-}

module G2.Initialization.KnownValues (initKnownValues) where

import qualified G2.Language.ExprEnv as E
import G2.Language.KnownValues
import G2.Language.Syntax
import G2.Language.TypeClasses
import G2.Language.TypeEnv
import G2.Language.Typing (PresType (..), tyAppCenter, returnType)

import Data.List
import qualified Data.HashMap.Lazy as HM
import qualified Data.Text as T

initKnownValues :: E.ExprEnv -> TypeEnv -> TypeClasses -> KnownValues
initKnownValues eenv tenv tc =
  let
    numT = typeWithStrName tenv "Num"
    integralT = typeWithStrName tenv "Integral"
    realT = typeWithStrName tenv "Real"
    eqT = typeWithStrName tenv "Eq"
    ordT = typeWithStrName tenv "Ord"
  in
  KnownValues {
      tyInt = typeWithStrName tenv "Int"
    , dcInt = dcWithStrName tenv "Int" "I#"

    , tyFloat = typeWithStrName tenv "Float"
    , dcFloat = dcWithStrName tenv "Float" "F#"

    , tyDouble = typeWithStrName tenv "Double"
    , dcDouble = dcWithStrName tenv "Double" "D#"

    , tyInteger = typeWithStrName tenv "Integer"
    , dcInteger = dcWithStrName tenv "Integer" "Z#"

    , tyChar = typeWithStrName tenv "Char"
    , dcChar = dcWithStrName tenv "Char" "C#"

    , tyBool = typeWithStrName tenv "Bool"
    , dcTrue = dcWithStrName tenv "Bool" "True"
    , dcFalse = dcWithStrName tenv "Bool" "False"

    , tyRational = typeWithStrName tenv "Rational"

#if MIN_VERSION_GLASGOW_HASKELL(9,6,0,0)
    , tyList = typeWithStrName tenv "List"
    , dcCons = dcWithStrName tenv "List" ":"
    , dcEmpty = dcWithStrName tenv "List" "[]"
#else
    , tyList = typeWithStrName tenv "[]"
    , dcCons = dcWithStrName tenv "[]" ":"
    , dcEmpty = dcWithStrName tenv "[]" "[]"
#endif

    , tyMaybe = typeWithStrName tenv "Maybe"
    , dcJust = dcWithStrName tenv "Maybe" "Just"
    , dcNothing = dcWithStrName tenv "Maybe" "Nothing"

    , tyUnit = typeWithStrName tenv "()"
    , dcUnit = dcWithStrName tenv "()" "()"

    , eqTC = eqT
    , numTC = numT
    , ordTC = ordT
    , integralTC = integralT
    , realTC = realT
    , fractionalTC = typeWithStrName tenv "Fractional"

    , integralExtactReal = superClassExtractor tc integralT realT
    , realExtractNum = superClassExtractor tc realT numT
    , realExtractOrd = superClassExtractor tc realT ordT
    , ordExtractEq = superClassExtractor tc ordT eqT

    , eqFunc = exprWithStrName eenv "=="
    , neqFunc = exprWithStrName eenv "/="

    , plusFunc = exprWithStrName eenv "+"
    , minusFunc = exprWithStrName eenv "-"
    , timesFunc = exprWithStrName eenv "*"
    , divFunc = exprWithStrName eenv "/"
    , negateFunc = exprWithStrName eenv "negate"
    , modFunc = exprWithStrName eenv "mod"

    , fromIntegerFunc = exprWithStrName eenv "fromInteger"
    , toIntegerFunc = exprWithStrName eenv "toInteger"

    , toRatioFunc = exprWithStrName eenv "%"
    , fromRationalFunc = exprWithStrName eenv "fromRational"

    , geFunc = exprWithStrName eenv ">="
    , gtFunc = exprWithStrName eenv ">"
    , ltFunc = exprWithStrName eenv "<"
    , leFunc = exprWithStrName eenv "<="

    , impliesFunc = exprWithStrName eenv "implies"
    , iffFunc = exprWithStrName eenv "iff"

    , andFunc = exprWithStrName eenv "&&"
    , orFunc = exprWithStrName eenv "||"
    , notFunc = exprWithStrName eenv "not"

    , errorFunc = exprWithStrName eenv "error"
    , errorEmptyListFunc = exprWithStrName eenv "errorEmptyList"
    , errorWithoutStackTraceFunc = exprWithStrName eenv "errorWithoutStackTrace"
    , patErrorFunc = exprWithStrName eenv "patError"
    }

exprWithStrName :: E.ExprEnv -> T.Text -> Name
exprWithStrName eenv s =
  case filter (\(Name n _ _ _) -> n == s) $ E.keys eenv of
    n:_ -> n
    _ -> error $ "No expr found in exprWithStrName " ++ (show $ T.unpack s)

typeWithStrName :: TypeEnv -> T.Text -> Name
typeWithStrName tenv s =
  case HM.toList $ HM.filterWithKey (\(Name n _ _ _) _ -> n == s) tenv of
    (n, _):_ -> n
    _ -> error $ "No type found in typeWithStrName " ++ (show $ T.unpack s)

dcWithStrName :: TypeEnv -> T.Text -> T.Text -> Name
dcWithStrName tenv ts dcs =
  case concatMap dataCon . HM.elems $ HM.filterWithKey (\(Name n _ _ _) _ -> n == ts) tenv of
    [] -> error $ "No type found in dcWithStrName [" ++
                  (show $ T.unpack ts) ++ "] [" ++ (show $ T.unpack dcs) ++ "]"
    dc -> dcWithStrName' dc dcs

dcWithStrName' :: [DataCon] -> T.Text -> Name
dcWithStrName' (DataCon n@(Name n' _ _ _) _:xs) s =
  if n' == s then n else dcWithStrName' xs s
dcWithStrName' _ s = error $ "No dc found in dcWithStrName [" ++ (show $ T.unpack s) ++ "]"

superClassExtractor :: TypeClasses -> Name -> Name -> Name
superClassExtractor tc tc_n sc_n =
    case lookupTCClass tc_n tc of
        Just c
            | Just (_, i) <- find extractsSC (superclasses c) -> idName i
            | otherwise -> error $ "superClassExtractor: Extractor not found\n" ++ show sc_n ++ "\n" ++ show (superclasses c)
        Nothing -> error $ "superClassExtractor: Class not found " ++ show tc_n
    where
        extractsSC (t, _) =
            let
                t_c = tyAppCenter . returnType . PresType $ t
            in
            case t_c of
                TyCon n _ -> n == sc_n
                _ -> False