{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} module Language.Symantic.Expr.Alt where import Language.Symantic.Type import Language.Symantic.Expr.Root -- * Type 'Expr_Alt' -- | Expression making an alternative between two expressions. data Expr_Alt curr next (root:: *) = Expr_Alt_Curr (curr root) | Expr_Alt_Next (next root) -- | Convenient alias. Requires @TypeOperators@. -- -- TODO: see if using a type-level list is better. type (.|.) = Expr_Alt infixr 5 .|. type instance Root_of_Expr (Expr_Alt curr next root) = root type instance Type_of_Expr (Expr_Alt curr next root) = Type_of_Expr_Alt (Type_of_Expr (curr root)) (Type_of_Expr (next root)) -- ** Type family 'Type_of_Expr_Alt' -- | Remove 'No_Type' type when building 'Type_of_Expr'. type family Type_of_Expr_Alt (type_curr:: (* -> *) -> * -> *) (type_next:: (* -> *) -> * -> *) where Type_of_Expr_Alt No_Type next = next Type_of_Expr_Alt curr No_Type = curr Type_of_Expr_Alt curr next = Type_Alt curr next -- ** Type family 'Is_Last_Expr' -- | Return whether a given expression is the last one in a given expression stack. -- -- NOTE: each expression parser uses this type family -- when it encounters unsupported syntax: -- to know if it is the last expression parser component that will be tried -- (and thus return 'Error_Expr_Unsupported') -- or if some other expression parser component shall be tried -- (and thus return 'Error_Expr_Unsupported_here', -- which is then handled accordingly by the 'Expr_From' instance of 'Expr_Alt'). type family Is_Last_Expr (ex:: *) (exs:: *) :: Bool where Is_Last_Expr ex ex = 'True Is_Last_Expr ex (Expr_Root exs) = Is_Last_Expr ex (exs (Expr_Root exs)) Is_Last_Expr (ex root) (Expr_Alt ex next root) = 'False Is_Last_Expr other (Expr_Alt curr next root) = Is_Last_Expr other (next root)