{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE InstanceSigs #-}
module Axel.Parse.AST where
import Data.IORef (IORef, modifyIORef, newIORef, readIORef)
import System.IO.Unsafe (unsafePerformIO)
data Expression
= LiteralChar Char
| LiteralInt Int
| LiteralString String
| SExpression [Expression]
| Symbol String
deriving (Eq, Show)
toAxel :: Expression -> String
toAxel (LiteralChar x) = ['{', x, '}']
toAxel (LiteralInt x) = show x
toAxel (LiteralString xs) = "\"" ++ xs ++ "\""
toAxel (SExpression xs) = "(" ++ unwords (map toAxel xs) ++ ")"
toAxel (Symbol x) = x
{-# NOINLINE gensymCounter #-}
gensymCounter :: IORef Int
gensymCounter = unsafePerformIO $ newIORef 0
gensym :: IO Expression
gensym = do
suffix <- readIORef gensymCounter
let identifier = "aXEL_AUTOGENERATED_IDENTIFIER_" ++ show suffix
modifyIORef gensymCounter succ
pure $ Symbol identifier
class ToExpressionList a where
toExpressionList :: a -> [Expression]
instance ToExpressionList [Expression] where
toExpressionList :: [Expression] -> [Expression]
toExpressionList = id
instance ToExpressionList Expression where
toExpressionList :: Expression -> [Expression]
toExpressionList (SExpression xs) = xs
toExpressionList x =
error
(show x <>
" cannot be splice-unquoted, because it is not an s-expression!")