packages feed

apple-0.1.0.0: src/CGen.hs

{-# LANGUAGE OverloadedStrings #-}

module CGen (CType(..), TTE(..), tCTy, pCty) where

import           A
import           Control.Exception (Exception)
import           Data.Bifunctor    (first)
import qualified Data.Text         as T
import           Prettyprinter     (Doc, Pretty (..), braces, parens, tupled, (<+>))
import           Prettyprinter.Ext

data CType = CR | CI | CB | Af | Ai | Ab

instance Pretty CType where
    pretty CR="F"; pretty CI="J"; pretty CB="B"; pretty Af="Af"; pretty Ai="Ai"; pretty Ab="Ab"

data CF = CF !T.Text [CType] CType

instance Pretty CF where
    pretty (CF n ins out) =
        let args = zip ins ['a'..] in
        "extern" <+> pretty out <+> pretty n <+> tupled (px<$>ins) <> ";"
            <#> px out <+> pretty n <> "_wrapper" <+> tupled (fmap (\(t,var) -> pretty t <+> pretty var) args)
            <> braces
                (foldMap d args
                <> pretty out <+> "res" <> "=" <> ax out (pretty n<>tupled (l.snd<$>args))<>";"
                <> foldMap f args
                <> "R res;")
        where px CR="F"; px CI="J"; px CB="B"; px _="U"
              ax Af=("poke_af"<>).parens;ax Ai=("poke_ai"<>).parens;ax Ab=error "not implemented.";ax _=id
              d (t,var) = px t <+> l var <> "=" <> ax t (pretty var) <> ";"
              f (Af,var) = "free" <> parens (l var) <> ";"
              f (Ai,var) = "free" <> parens (l var) <> ";"
              f (Ab,var) = "free" <> parens (l var) <> ";"
              f _        = mempty
              l var = "_" <> pretty var

-- type translation error
data TTE = HO | Poly | FArg | ArrFn deriving Show

instance Pretty TTE where
    pretty HO = "Higher order"; pretty Poly = "Too polymorphic"; pretty FArg = "Function as argument"; pretty ArrFn = "Arrays of functions are not supported."

pCty :: T.Text -> T a -> Either TTE (Doc ann)
pCty nm t = ("#include<apple_abi.h>" <#>) . pretty <$> nmtCTy nm t

nmtCTy :: T.Text -> T a -> Either TTE CF
nmtCTy nm t = do{(ins,out) <- irTy (rLi t); CF nm<$>traverse cTy ins<*>cTy out}

tCTy :: T a -> Either TTE ([CType], CType)
tCTy t = do{(ins,out) <- irTy (rLi t); (,)<$>traverse cTy ins<*>cTy out}

cTy :: T a -> Either TTE CType
cTy F                 = pure CR
cTy I                 = pure CI
cTy B                 = pure CB
cTy (Arr _ F)         = pure Af
cTy (Arr _ I)         = pure Ai
cTy (Arr _ B)         = pure Ab
cTy (Arrow Arrow{} _) = Left FArg
cTy (Arr _ Arrow{})   = Left ArrFn

instance Exception TTE where

irTy :: T a -> Either TTE ([T a], T a)
irTy F                 = pure ([], F)
irTy I                 = pure ([], I)
irTy B                 = pure ([], B)
irTy t@Arr{}           = pure ([], t)
irTy (Arrow Arrow{} _) = Left HO
irTy (Arrow t0 t1)     = first (t0:) <$> irTy t1
irTy TVar{}            = Left Poly
irTy Ρ{}               = Left Poly