{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}

module Earthling.Types where

import           Data.Text (Text)
import           Data.Sequence (Seq)

data Phase = Raw | Typed

type family TypeAnnot (p :: Phase) where
  TypeAnnot 'Raw   = ()
  TypeAnnot 'Typed = WordType

data WordType = WordType
  { stackIn  :: StackType
  , stackOut :: StackType
  } deriving (Eq, Show)

data StackType = StackType
  { baseStackType :: StackBase
  , topStackType  :: Seq ItemType
  } deriving (Eq, Show)

data StackBase
  = EmptyStack
  | StackVar Text
    deriving (Eq, Show)

data ItemType
  = VarType Text
  | ConstrType Text
  | AtomType WordType
    deriving (Eq, Show)

data Decl p = Decl
  { declName :: Text
  , declType :: WordType
  , declDefn :: Seq (Item p)
  }

deriving instance Eq (TypeAnnot p) => Eq (Decl p)
deriving instance Show (TypeAnnot p) => Show (Decl p)

data Item p = Item
  { itemTok  :: Atom
  , itemType :: TypeAnnot p
  }

deriving instance Eq (TypeAnnot p) => Eq (Item p)
deriving instance Show (TypeAnnot p) => Show (Item p)

data Atom
  = AtomIdent Text
  | AtomConstr Text
  | AtomLiteral Literal
  deriving (Eq, Show)

data Literal
  = IntLiteral Integer
  | DoubleLiteral Double
    deriving (Eq, Show)
