summaryrefslogtreecommitdiff
path: root/src/AST
diff options
context:
space:
mode:
Diffstat (limited to 'src/AST')
-rw-r--r--src/AST/Pretty.hs166
1 files changed, 166 insertions, 0 deletions
diff --git a/src/AST/Pretty.hs b/src/AST/Pretty.hs
new file mode 100644
index 0000000..c1d6c88
--- /dev/null
+++ b/src/AST/Pretty.hs
@@ -0,0 +1,166 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE PolyKinds #-}
+{-# LANGUAGE EmptyCase #-}
+{-# LANGUAGE DeriveFunctor #-}
+{-# LANGUAGE TupleSections #-}
+module AST.Pretty where
+
+import Control.Monad (ap)
+import Data.List (intersperse)
+import Data.Functor.Const
+
+import AST
+
+
+data Val f env where
+ VTop :: Val f '[]
+ VPush :: f t -> Val f env -> Val f (t : env)
+
+type SVal = Val (Const String)
+
+valprj :: Val f env -> Idx env t -> f t
+valprj (VPush x _) IZ = x
+valprj (VPush _ env) (IS i) = valprj env i
+valprj VTop i = case i of {}
+
+newtype M a = M { runM :: Int -> (a, Int) }
+ deriving (Functor)
+instance Applicative M where { pure x = M (\i -> (x, i)) ; (<*>) = ap }
+instance Monad M where { M f >>= g = M (\i -> let (x, j) = f i in runM (g x) j) }
+
+genId :: M Int
+genId = M (\i -> (i, i + 1))
+
+genName :: M String
+genName = ('x' :) . show <$> genId
+
+ppExpr :: SList STy env -> Expr x env t -> String
+ppExpr senv e = fst (runM (mkVal senv >>= \val -> ppExpr' 0 val e) 1) ""
+ where
+ mkVal :: SList STy env -> M (SVal env)
+ mkVal SNil = return VTop
+ mkVal (SCons _ v) = do
+ val <- mkVal v
+ name <- genName
+ return (VPush (Const name) val)
+
+ppExpr' :: Int -> SVal env -> Expr x env t -> M ShowS
+ppExpr' d val = \case
+ EVar _ _ i -> return $ showString $ getConst $ valprj val i
+
+ etop@ELet{} -> do
+ let collect :: SVal env -> Expr x env t -> M ([(String, ShowS)], ShowS)
+ collect val' (ELet _ rhs body) = do
+ name <- genName
+ (binds, core) <- collect (VPush (Const name) val') body
+ rhs' <- ppExpr' 0 val' rhs
+ return ((name, rhs') : binds, core)
+ collect val' e = ([],) <$> ppExpr' 0 val' e
+
+ (binds, core) <- collect val etop
+ let (open, close) = case binds of
+ [_] -> ("{ ", " }")
+ _ -> ("", "")
+ return $ showParen (d > 0) $
+ showString ("let " ++ open)
+ . foldr (.) id (intersperse (showString " ; ")
+ (map (\(name, rhs) -> showString (name ++ " = ") . rhs) binds))
+ . showString (close ++ " in ")
+ . core
+
+ EPair _ a b -> do
+ a' <- ppExpr' 0 val a
+ b' <- ppExpr' 0 val b
+ return $ showString "(" . a' . showString ", " . b' . showString ")"
+
+ EFst _ e -> do
+ e' <- ppExpr' 11 val e
+ return $ showParen (d > 10) $ showString "fst " . e'
+
+ ESnd _ e -> do
+ e' <- ppExpr' 11 val e
+ return $ showParen (d > 10) $ showString "snd " . e'
+
+ ENil _ -> return $ showString "()"
+
+ EInl _ _ e -> do
+ e' <- ppExpr' 11 val e
+ return $ showParen (d > 10) $ showString "inl " . e'
+
+ EInr _ _ e -> do
+ e' <- ppExpr' 11 val e
+ return $ showParen (d > 10) $ showString "inr " . e'
+
+ ECase _ e a b -> do
+ e' <- ppExpr' 0 val e
+ name1 <- genName
+ a' <- ppExpr' 0 (VPush (Const name1) val) a
+ name2 <- genName
+ b' <- ppExpr' 0 (VPush (Const name2) val) b
+ return $ showParen (d > 0) $
+ showString "case " . e' . showString (" of { Inl " ++ name1 ++ " -> ") . a'
+ . showString (" ; Inr " ++ name2 ++ " -> ") . b' . showString " }"
+
+ EConst _ ty v -> return $ showString $ case ty of
+ STI32 -> show v ; STI64 -> show v ; STF32 -> show v ; STF64 -> show v ; STBool -> show v
+
+ EOp _ op (EPair _ a b)
+ | (Infix, ops) <- operator op -> do
+ a' <- ppExpr' 9 val a
+ b' <- ppExpr' 9 val b
+ return $ showParen (d > 8) $ a' . showString (" " ++ ops ++ " ") . b'
+
+ EOp _ op e -> do
+ e' <- ppExpr' 11 val e
+ let ops = case operator op of
+ (Infix, s) -> "(" ++ s ++ ")"
+ (Prefix, s) -> s
+ return $ showParen (d > 10) $ showString (ops ++ " ") . e'
+
+ EMOne venv i e -> do
+ let venvlen = length (unSList venv)
+ varname = 'v' : show (venvlen - idx2int i)
+ e' <- ppExpr' 11 val e
+ return $ showParen (d > 10) $
+ showString ("one " ++ show varname ++ " ") . e'
+
+ EMScope e -> do
+ let venv = case typeOf e of STEVM v _ -> v
+ venvlen = length (unSList venv)
+ varname = 'v' : show venvlen
+ e' <- ppExpr' 11 val e
+ return $ showParen (d > 10) $
+ showString ("scope " ++ show varname ++ " ") . e'
+
+ EMReturn _ e -> do
+ e' <- ppExpr' 11 val e
+ return $ showParen (d > 10) $ showString ("return ") . e'
+
+ EMBind a b -> do
+ a' <- ppExpr' 0 val a
+ name <- genName
+ b' <- ppExpr' 0 (VPush (Const name) val) b
+ return $ showParen (d > 10) $ a' . showString (" >>= \\" ++ name ++ " -> ") . b'
+
+ EError _ s -> return $ showParen (d > 10) $ showString ("error " ++ show s)
+
+ _ -> undefined
+
+data Fixity = Prefix | Infix
+ deriving (Show)
+
+operator :: SOp a t -> (Fixity, String)
+operator OAdd{} = (Infix, "+")
+operator OMul{} = (Infix, "*")
+operator ONeg{} = (Prefix, "negate")
+operator OLt{} = (Infix, "<")
+operator OLe{} = (Infix, "<=")
+operator OEq{} = (Infix, "==")
+operator ONot = (Prefix, "not")
+
+idx2int :: Idx env t -> Int
+idx2int IZ = 0
+idx2int (IS n) = 1 + idx2int n