descript-lang-0.2.0.0: src/Descript/BasicInj/Data/Atom/Inject.hs
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE OverloadedStrings #-}
module Descript.BasicInj.Data.Atom.Inject
( PrimType (..)
, InjSymbol (..)
, isInjSymbol
, forceToInjSymbol
, isPrimInstance
) where
import Descript.Lex.Data.Atom
import Descript.Misc
import Data.Semigroup
-- | A type of built-in primitive.
data PrimType an
= PrimTypeNumber an
| PrimTypeString an
deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable)
-- | An identifier for a built-in primitive or injected function.
data InjSymbol an
= InjSymbol an String
deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable)
instance Ann PrimType where
getAnn (PrimTypeNumber ann) = ann
getAnn (PrimTypeString ann) = ann
instance Ann InjSymbol where
getAnn (InjSymbol ann _) = ann
instance EAnn InjSymbol where
InjSymbol xKeyAnn xKeyStr `eappend` InjSymbol yKeyAnn yKeyStr
| xKeyStr /= yKeyStr = error "Injected symbols have different content"
| otherwise = InjSymbol (xKeyAnn <> yKeyAnn) xKeyStr
instance Printable PrimType where
aprint (PrimTypeNumber _) = plex "#Number[]"
aprint (PrimTypeString _) = plex "#String[]"
instance Printable InjSymbol where
aprint (InjSymbol _ str) = plex $ '#' : str
instance (Show an) => Summary (PrimType an) where
summary = pprintSummary
instance (Show an) => Summary (InjSymbol an) where
summary = pprintSummary
-- | Whether the symbol refers to something injected - a primtive type
-- or an injected function.
isInjSymbol :: Symbol an -> Bool
isInjSymbol (Symbol _ ('#' : _)) = True
isInjSymbol (Symbol _ _) = False
-- | Assuming the symbol refers to something injected, converts it to an
-- injected symbol, making this reference explicit.
-- Raises an error otherwise.
forceToInjSymbol :: Symbol an -> InjSymbol an
forceToInjSymbol (Symbol ann ('#' : xs)) = InjSymbol ann xs
forceToInjSymbol (Symbol _ _) = error "Symbol doesn't refer to injected function."
-- | Whether the primitive is an instance of the type.
isPrimInstance :: Prim an1 -> PrimType an2 -> Bool
isPrimInstance (PrimNumber _ _) (PrimTypeNumber _) = True
isPrimInstance (PrimText _ _) (PrimTypeString _) = True
isPrimInstance _ _ = False