ddc-source-tetra-0.4.3.1: DDC/Source/Tetra/Parser/Param.hs
-- | Desugaring of function parameter syntax in Source Tetra.
module DDC.Source.Tetra.Parser.Param
( ParamSpec (..)
, expOfParams
, funTypeOfParams
, pBindParamSpec
, pBindParamSpecAnnot)
where
import DDC.Source.Tetra.Parser.Base
import DDC.Source.Tetra.Parser.Type
import DDC.Source.Tetra.Exp.Source
import Data.Maybe
import DDC.Core.Lexer.Tokens as K
import qualified DDC.Control.Parser as P
-- | Specification of a function parameter.
-- We can determine the contribution to the type of the function,
-- as well as its expression based on the parameter.
data ParamSpec
= ParamType Bind (Maybe Type)
| ParamWitness Bind (Maybe Type)
| ParamValue Bind (Maybe Type)
-- | Build the expression of a function from specifications of its parameters,
-- and the expression for the body.
expOfParams
:: [ParamSpec] -- ^ Spec of parameters.
-> Exp -- ^ Body of function.
-> Exp -- ^ Expression of whole function.
expOfParams [] xBody = xBody
expOfParams (p:ps) xBody
= case p of
ParamType b mt
-> XLAM (XBindVarMT b mt) $ expOfParams ps xBody
ParamWitness b mt
-> XLam (XBindVarMT b mt) $ expOfParams ps xBody
ParamValue b mt
-> XLam (XBindVarMT b mt) $ expOfParams ps xBody
-- | Build the type of a function from specifications of its parameters,
-- and the type of the body.
funTypeOfParams
:: [ParamSpec] -- ^ Spec of parameters.
-> Type -- ^ Type of body.
-> Type -- ^ Type of whole function.
funTypeOfParams [] tBody
= tBody
funTypeOfParams (p:ps) tBody
= case p of
ParamType b mt
-> let k = fromMaybe (TBot KData) mt
in TApp (TCon (TyConForall k)) (TAbs b k $ funTypeOfParams ps tBody)
ParamWitness _ mt
-> TImpl (fromMaybe (TBot KData) mt)
$ funTypeOfParams ps tBody
ParamValue _ mt
-> TFun (fromMaybe (TBot KData) mt)
$ funTypeOfParams ps tBody
-- | Parse a function parameter specification,
-- with an optional type (or kind) annotation.
pBindParamSpec :: Parser [ParamSpec]
pBindParamSpec
= P.choice
[ -- Value (or type) binder with a type (or kind) annotation.
pBindParamSpecAnnot
-- Value binder without type annotations.
, do b <- pBind
return $ [ ParamValue b Nothing ]
]
-- | Parse a function parameter specification,
-- requiring a full type (or kind) annotation.
---
-- [BIND1 BIND2 .. BINDN : TYPE]
-- or (BIND : TYPE)
-- or (BIND : TYPE) { EFFECT | CLOSURE }
--
pBindParamSpecAnnot :: Parser [ParamSpec]
pBindParamSpecAnnot
= P.choice
-- Type parameter
-- [BIND1 BIND2 .. BINDN : TYPE]
[ do pSym SSquareBra
bs <- P.many1 pBind
pTok (K.KOp ":")
t <- pType
pSym SSquareKet
return [ ParamType b (Just t) | b <- bs]
-- Witness parameter
-- {BIND : TYPE}
, do pSym SBraceBra
b <- pBind
pTok (K.KOp ":")
t <- pType
pSym SBraceKet
return [ ParamWitness b (Just t) ]
-- Value parameter with type annotations.
-- (BIND1 BIND2 .. BINDN : TYPE)
-- (BIND1 BIND2 .. BINDN : TYPE) { TYPE | TYPE }
, do pSym SRoundBra
bs <- P.many1 pBind
pTok (K.KOp ":")
t <- pType
pSym SRoundKet
return $ [ ParamValue b (Just t) | b <- bs ]
]