ddc-core-salt-0.4.2.1: DDC/Core/Salt/Name.hs
{-# LANGUAGE PatternSynonyms #-}
-- | Names used in the Disciple Core Salt language profile.
module DDC.Core.Salt.Name
( Name (..)
-- * Primitive Type Constructors
, PrimTyCon (..)
, pprPrimTyConStem
, readPrimTyCon, readPrimTyConStem
, primTyConIsIntegral
, primTyConIsFloating
, primTyConIsUnsigned
, primTyConIsSigned
, primTyConWidth
-- * Primitive Values
, PrimVal (..)
, readPrimVal
, pattern NamePrimOp
, pattern NamePrimLit
-- * Primitive Operators
, PrimOp (..)
, readPrimOp
-- * Primitive Arithmetic
, PrimArith (..)
, readPrimArith
-- * Primitive Calls
, PrimCall (..)
, readPrimCall
-- * Primitive Casts
, PrimCast (..)
, readPrimCast
, primCastPromoteIsValid
, primCastTruncateIsValid
-- * Primitive Control
, PrimControl (..)
, readPrimControl
-- * Primitive Store
, PrimStore (..)
, readPrimStore
-- * Primitive Vector
, PrimVec (..)
, readPrimVec
, multiOfPrimVec
, liftPrimArithToVec
, lowerPrimVecToArith
-- * Primitive Literals
, PrimLit (..)
, readPrimLit
, readLitInteger
, readLitNat
, readLitInt
, readLitSize
, readLitWordOfBits
, readLitFloatOfBits
, pattern NameLitVoid
, pattern NameLitBool
, pattern NameLitNat
, pattern NameLitInt
, pattern NameLitSize
, pattern NameLitWord
, pattern NameLitFloat
, pattern NameLitTextLit
, pattern NameLitTag
-- * Name Parsing
, readName
, takeNameVar )
where
import DDC.Core.Salt.Name.PrimArith
import DDC.Core.Salt.Name.PrimCall
import DDC.Core.Salt.Name.PrimCast
import DDC.Core.Salt.Name.PrimControl
import DDC.Core.Salt.Name.PrimStore
import DDC.Core.Salt.Name.PrimTyCon
import DDC.Core.Salt.Name.PrimVec
import DDC.Core.Salt.Name.Lit
import DDC.Core.Lexer.Names (isVarStart)
import DDC.Data.ListUtils
import DDC.Base.Pretty
import DDC.Base.Name
import Data.Typeable
import Data.Char
import Data.List
import Control.DeepSeq
import Data.Text (Text)
import qualified Data.Text as T
-- | Names of things used in Disciple Core Salt.
data Name
-- | A type or value variable.
= NameVar !String
-- | Constructor names.
| NameCon !String
-- | An extended name.
| NameExt !Name !String
-- | The abstract heap object type constructor.
| NameObjTyCon
-- | A primitive type constructor.
| NamePrimTyCon !PrimTyCon
-- | A primitive value.
| NamePrimVal !PrimVal
deriving (Eq, Ord, Show, Typeable)
instance NFData Name where
rnf name
= case name of
NameVar s -> rnf s
NameExt n s -> rnf n `seq` rnf s
NameCon s -> rnf s
NameObjTyCon -> ()
NamePrimTyCon con -> rnf con
NamePrimVal val -> rnf val
instance Pretty Name where
ppr nn
= case nn of
NameVar n -> text n
NameCon n -> text n
NameExt n ext -> ppr n <> text "$" <> text ext
NameObjTyCon -> text "Obj"
NamePrimTyCon tc -> ppr tc
NamePrimVal val -> ppr val
instance CompoundName Name where
extendName n str
= NameExt n str
splitName nn
= case nn of
NameExt n str -> Just (n, str)
_ -> Nothing
-- | Read the name of a variable, constructor or literal.
readName :: String -> Maybe Name
readName str
-- Obj
| str == "Obj"
= Just $ NameObjTyCon
-- PrimTyCon
| Just p <- readPrimTyCon str
= Just $ NamePrimTyCon p
-- PrimVal
| Just p <- readPrimVal str
= Just $ NamePrimVal p
-- Constructors.
| c : _ <- str
, isUpper c
= Just $ NameVar str
-- Variables.
| c : _ <- str
, isVarStart c || c == '_'
= Just $ NameVar str
| otherwise
= Nothing
-- | Take the string of a non-primitive name. Supports extended names.
takeNameVar :: Name -> Maybe String
takeNameVar (NameVar n)
= Just n
takeNameVar (NameExt n str)
| Just n' <- takeNameVar n
= Just (n' ++ "$" ++ str)
takeNameVar _
= Nothing
-- PrimVal --------------------------------------------------------------------
-- | Primitive values, meaning both operators and literals.
data PrimVal
= PrimValOp !PrimOp
| PrimValLit !PrimLit
deriving (Eq, Ord, Show)
pattern NamePrimOp op = NamePrimVal (PrimValOp op)
pattern NamePrimLit lit = NamePrimVal (PrimValLit lit)
instance NFData PrimVal where
rnf p
= case p of
PrimValOp op -> rnf op
PrimValLit lit -> rnf lit
instance Pretty PrimVal where
ppr p
= case p of
PrimValOp op -> ppr op
PrimValLit lit -> ppr lit
-- | Read a primitive value.
readPrimVal :: String -> Maybe PrimVal
readPrimVal str
| Just op <- readPrimOp str
= Just $ PrimValOp op
| Just lit <- readPrimLit str
= Just $ PrimValLit lit
| otherwise
= Nothing
-- PrimOp ---------------------------------------------------------------------
-- | Primitive operators implemented directly by the machine or runtime system.
data PrimOp
-- | Arithmetic, logic, comparison and bit-wise operators.
= PrimArith !PrimArith
-- | Casting between numeric types.
| PrimCast !PrimCast
-- | Raw store access.
| PrimStore !PrimStore
-- | Special function calling conventions.
| PrimCall !PrimCall
-- | Non-functional control flow.
| PrimControl !PrimControl
deriving (Eq, Ord, Show)
instance NFData PrimOp where
rnf op
= case op of
PrimArith pa -> rnf pa
PrimCast pc -> rnf pc
PrimStore ps -> rnf ps
PrimCall pc -> rnf pc
PrimControl pc -> rnf pc
instance Pretty PrimOp where
ppr pp
= case pp of
PrimArith op -> ppr op
PrimCast c -> ppr c
PrimStore p -> ppr p
PrimCall c -> ppr c
PrimControl c -> ppr c
-- | Read a primitive operator.
readPrimOp :: String -> Maybe PrimOp
readPrimOp str
-- PrimArith
| Just p <- readPrimArith str
= Just $ PrimArith p
-- PrimCast
| Just p <- readPrimCast str
= Just $ PrimCast p
-- PrimCall
| Just p <- readPrimCall str
= Just $ PrimCall p
-- PrimControl
| Just p <- readPrimControl str
= Just $ PrimControl p
-- PrimStore
| Just p <- readPrimStore str
= Just $ PrimStore p
| otherwise
= Nothing
-- PrimLit --------------------------------------------------------------------
-- | Primitive literals.
data PrimLit
-- | The void literal.
= PrimLitVoid
-- | A boolean literal.
| PrimLitBool !Bool
-- | A natural number literal.
| PrimLitNat !Integer
-- | An integer number literal.
| PrimLitInt !Integer
-- | A size literal.
| PrimLitSize !Integer
-- | A word literal, of the given width.
| PrimLitWord !Integer !Int
-- | A floating point literal, of the given width.
| PrimLitFloat !Double !Int
-- | A text literal.
| PrimLitTextLit !Text
-- | A constructor tag literal.
| PrimLitTag !Integer
deriving (Eq, Ord, Show)
pattern NameLitVoid = NamePrimVal (PrimValLit PrimLitVoid)
pattern NameLitBool x = NamePrimVal (PrimValLit (PrimLitBool x))
pattern NameLitNat x = NamePrimVal (PrimValLit (PrimLitNat x))
pattern NameLitInt x = NamePrimVal (PrimValLit (PrimLitInt x))
pattern NameLitSize x = NamePrimVal (PrimValLit (PrimLitSize x))
pattern NameLitWord x s = NamePrimVal (PrimValLit (PrimLitWord x s))
pattern NameLitFloat x s = NamePrimVal (PrimValLit (PrimLitFloat x s))
pattern NameLitTextLit x = NamePrimVal (PrimValLit (PrimLitTextLit x))
pattern NameLitTag x = NamePrimVal (PrimValLit (PrimLitTag x))
instance NFData PrimLit where
rnf p
= case p of
PrimLitVoid -> ()
PrimLitBool b -> rnf b
PrimLitNat i -> rnf i
PrimLitInt i -> rnf i
PrimLitSize i -> rnf i
PrimLitWord i bits -> rnf i `seq` rnf bits
PrimLitFloat f bits -> rnf f `seq` rnf bits
PrimLitTextLit bs -> rnf bs
PrimLitTag i -> rnf i
instance Pretty PrimLit where
ppr p
= case p of
PrimLitVoid -> text "V#"
PrimLitBool True -> text "True#"
PrimLitBool False -> text "False#"
PrimLitNat i -> integer i <> text "#"
PrimLitInt i -> integer i <> text "i#"
PrimLitSize i -> integer i <> text "s#"
PrimLitWord i bits -> integer i <> text "w" <> int bits <> text "#"
PrimLitFloat f bits -> double f <> text "f" <> int bits <> text "#"
PrimLitTextLit tx -> (text $ show $ T.unpack tx) <> text "#"
PrimLitTag i -> text "TAG" <> integer i <> text "#"
-- | Read a primitive literal.
readPrimLit :: String -> Maybe PrimLit
readPrimLit str
-- Literal void
| str == "V#"
= Just $ PrimLitVoid
-- Literal Bools
| str == "True#" = Just $ PrimLitBool True
| str == "False#" = Just $ PrimLitBool False
-- Literal Nats
| Just str' <- stripSuffix "#" str
, Just val <- readLitNat str'
= Just $ PrimLitNat val
-- Literal Ints
| Just str' <- stripSuffix "#" str
, Just val <- readLitInt str'
= Just $ PrimLitInt val
-- Literal Sizes
| Just str' <- stripSuffix "s#" str
, Just val <- readLitSize str'
= Just $ PrimLitSize val
-- Literal Words
| Just str' <- stripSuffix "#" str
, Just (val, bits) <- readLitWordOfBits str'
, elem bits [8, 16, 32, 64]
= Just $ PrimLitWord val bits
-- Literal Floats
| Just str' <- stripSuffix "#" str
, Just (val, bits) <- readLitFloatOfBits str'
, elem bits [32, 64]
= Just $ PrimLitFloat val bits
-- Literal Tags
| Just rest <- stripPrefix "TAG" str
, (ds, "#") <- span isDigit rest
= Just $ PrimLitTag (read ds)
| otherwise
= Nothing