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

module SML.AST where

type Ident = String
type Label = String

--

data Phase
  = Raw
    deriving (Eq, Show)

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

--

data Exp (p :: Phase)
  = SconExp
  | LongviExp
  | RowExp (ExpRow p)
  | RecordSelExp Ident
  | UnitExp [Exp p]
  | ListExp [Exp p]
  | SequenceExp [Exp p]
  | LetExp (Dec p) [Exp p]
  | AppExp (Exp p) (Exp p)
  | InfExp (Exp p) Ident (Exp p)
  | TypExp (Exp p) (Ty p)
  | AndAlsoExp (Exp p) (Exp p)
  | OrElseExp (Exp p) (Exp p)
  | HandleExp (Exp p) (Match p)
  | RaiseExp (Exp p)
  | ITEExp (Exp p) (Exp p) (Exp p)
  | WhileExp (Exp p) (Exp p)
  | CaseExp (Exp p) (Exp p)
  | FnExp (Match p)

deriving instance Show (TypeAnnot p) => Show (Exp p)

--

data ExpRow (p :: Phase)
  = ExpRow [(Label, Exp p)]

deriving instance Show (TypeAnnot p) => Show (ExpRow p)

--

data Match (p :: Phase)
  = Match [(Pat p, Exp p)]
deriving instance Show (TypeAnnot p) => Show (Match p)

--

data Pat (p :: Phase)
  = WildPat
  | SconPat
  | ValuePat
  | RecordPat (PatRow p)
  | UnitPat
  | TuplePat [Pat p]
  | ListPat [Pat p]
  | ConstrPat Ident (Pat p)


deriving instance Show (TypeAnnot p) => Show (Pat p)

--

data PatRow (p :: Phase)
  = PatRow [(Label, Exp p)]

deriving instance Show (TypeAnnot p) => Show (PatRow p)

--

data Ty (p :: Phase)
deriving instance Show (TypeAnnot p) => Show (Ty p)

--

data Dec (p :: Phase)
  -- = ValDec (TyVarSeq p) (ValBind p)
  -- | FunDec (TyVarSeq p) (FunBind p)
  -- | TypeDec (TypBind p)

deriving instance Show (TypeAnnot p) => Show (Dec p)

data ValBind (p :: Phase)
  = ValbindEq (Pat p) (Exp p) (Maybe (ValBind p))
  | Rec (ValBind p)

deriving instance Show (TypeAnnot p) => Show (ValBind p)

data FunBind (p :: Phase)
deriving instance Show (TypeAnnot p) => Show (FunBind p)

--

data Literal
  = IntLiteral Integer
    deriving (Eq, Show)
