descript-lang-0.2.0.0: src/Descript/Lex/Data/Atom.hs
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE OverloadedStrings #-}
module Descript.Lex.Data.Atom
( Symbol (..)
, Prim (..)
, codeSym
, codeLangSym
, codeContentSym
, undefinedSym
, primExt
, encodePrim
) where
import Descript.Misc
import Data.Semigroup
import Data.Text (Text)
import qualified Data.Text.Encoding as Text
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as ByteString
-- | An identifier. Used to distinguish records and record properties.
data Symbol an
= Symbol
{ symbolAnn :: an
, symbolLiteral :: String
} deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable)
-- | A built-in primitive. A piece of data in code not represented by a record.
--
-- In Descript, most values are typically represented by records. While
-- /theoretically/ every value /could/ be a record, converting some
-- values like strings and numbers is verbose and inefficient.
--
-- Currently, the only primitives are numbers and strings. In the
-- future, images and other arbitrary data could be added.
data Prim an
= PrimNumber an Rational
| PrimText an Text
deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable)
instance Ann Symbol where
getAnn = symbolAnn
instance EAnn Symbol where
Symbol xKeyAnn xKeyStr `eappend` Symbol yKeyAnn yKeyStr
| xKeyStr /= yKeyStr = error "Symbols have different content"
| otherwise = Symbol (xKeyAnn <> yKeyAnn) xKeyStr
instance Ann Prim where
getAnn (PrimNumber ann _) = ann
getAnn (PrimText ann _) = ann
instance Printable Symbol where
aprint (Symbol _ str) = plex str
instance Printable Prim where
aprint (PrimNumber _ num) = pprim num
aprint (PrimText _ str) = pprim str
instance (Show an) => Summary (Symbol an) where
summary = pprintSummary
instance (Show an) => Summary (Prim an) where
summary = pprintSummary
-- | The record head for code blocks.
codeSym :: Symbol ()
codeSym = Symbol () "Code"
-- | The property key for a code block's language
codeLangSym :: Symbol ()
codeLangSym = Symbol () "lang"
-- | The property key for a code block's content.
codeContentSym :: Symbol ()
codeContentSym = Symbol () "content"
-- | A symbol for an undefined value - e.g. an unresolved implicit
-- property.
undefinedSym :: Symbol ()
undefinedSym = Symbol () "{undefined}"
-- | The extension of a file with the given primitive.
primExt :: Prim () -> String
primExt _ = "txt" -- So far everything is just text.
-- | Write a primitive into a 'ByteString'. Just encodes the underlying
-- number or string.
encodePrim :: Prim () -> ByteString
encodePrim (PrimNumber () x) = ByteString.pack $ show x
encodePrim (PrimText () x) = Text.encodeUtf8 x