{-# LANGUAGE DeriveDataTypeable #-}

module Data.SExp.Data 
  ( Atom(..), AntiAtom(..)
  , OpenLink(..) , OpenSExp(..)
  , SExp(..), SExpLink(..)
  , DualSExp(..), DualSExpLink(..)
  ) where

import Data.Generics

-- Atoms and Anti-Atoms

data Atom =
    StringAtom String
  | BooleanAtom Bool
  | IntegerAtom Integer
  | FloatingAtom Double
  | SymbolAtom String
  deriving (Eq, Ord, Show, Typeable, Data)

data AntiAtom =
  -- | Created with QuasiQuotes of form @[sexp| \@:name |]@. Will be converted
  -- to expression or pattern of type 'SExp'.
    ValueAntiAtom String
  -- | Created with QuasiQuotes of form @[sexp| \@atom:name |]@. Will be
  -- converted to expression or pattern of type 'Atom'.
  | AtomAntiAtom String
  -- | Created with QuasiQuotes of form @[sexp| \@str:name |]@. Will be
  -- converted to expression or pattern of type 'Atom'.
  | StringAntiAtom String
  -- | Created with QuasiQuotes of form @[sexp| \@bool:name |]@.  Will be
  -- converted to expression or pattern of type 'Atom'.
  | BooleanAntiAtom String
  -- | Created with QuasiQuotes of form @[sexp| \@int:name |]@.  Will be
  -- converted to expression or pattern of type 'Atom'.
  | IntegerAntiAtom String
  -- | Created with QuasiQuotes of form @[sexp| \@float:name |]@.  Will be
  -- converted to expression or pattern of type 'Atom'.
  | FloatingAntiAtom String
  -- | Created with QuasiQuotes of form @[sexp| \@sym:name |]@.  Will be
  -- converted to expression or pattern of type 'Atom'.
  | SymbolAntiAtom String
  deriving (Eq, Ord, Show, Typeable, Data)

-- Generic Link Structure

data OpenLink sd sl =
    NullLink
  | ConsLink sd sl
  deriving (Eq, Ord, Show, Typeable, Data)

-- Standard S-Expressions

data OpenSExp sl =
    AtomSExp Atom
  | LinkSExp sl
  deriving (Eq, Ord, Show, Typeable, Data)

newtype SExp = SExp { unSExp :: OpenSExp SExpLink } 
  deriving (Eq, Ord, Show, Typeable, Data)
newtype SExpLink = SExpLink { unSExpLink :: OpenLink SExp SExpLink } 
  deriving (Eq, Ord, Show, Typeable, Data)

-- Anti S-Expressions

data DualSExp =
    PositiveDualSExp (OpenSExp DualSExpLink)
  | AntiAtomDualSExp AntiAtom
  deriving (Eq, Ord, Show, Typeable, Data)

data DualSExpLink =
    PositiveDualSExpLink (OpenLink DualSExp DualSExpLink)
  | AntiConsDualSExpLink String
  deriving (Eq, Ord, Show, Typeable, Data)