packages feed

tempus-0.1.0: Tempus/Syntax.hs

{-# LANGUAGE DeriveDataTypeable, FlexibleInstances #-}

-- | Tempus abstract syntax tree types.
module Tempus.Syntax (
    Program,
    Decl (..),
    Type (..),
    MuType (..),
    NuType (..),
    Expr (..),
    Var (..),

    SrcCode (..)
) where

import Data.Data
import Data.Generics.Uniplate.Data ()
import Data.List

import Tempus.Loc


-- | A Tempus program as a list of definitions.
type Program = [Decl]

-- | A Tempus type or value definition.
data Decl = DeclType SrcLoc Var [Var] Type
          | DeclVal SrcLoc Var Expr
          deriving (Eq, Show)


-- | A Tempus type.
data Type = TyMu MuType
          | TyNu NuType
          | TyFun Type Type
          | TyPlus Type Type
          | TyPair Type Type
          | TyApp Var [Type]
          | TyBehav Type
          | TyEvent Type
          | TyNat
          | TyZero
          | TyUnit

          -- only used for type checking
          | TyVar Integer
          | TyCon Integer
          deriving (Eq, Show, Data, Typeable)


-- | A mu type.
data MuType = MuType Var Type
            deriving (Eq, Show, Data, Typeable)


-- | A nu type.
data NuType = NuType Var Type
            deriving (Eq, Show, Data, Typeable)


-- | A Tempus expression.
data Expr = ExPair Expr Expr
          | ExLam Var Expr
          | ExLiftAppB Expr Expr
          | ExLiftAppE Expr Expr
          | ExApp Expr Expr
          | ExConst Expr
          | ExVar Var
          | ExNatLit Integer
          | ExBehav Expr
          | ExEvent Expr Expr
          | ExNull
          | ExUnit
          | ExLeft
          | ExRight
          | ExCase
          | ExExpand
          | ExFst
          | ExSnd
          | ExNever
          | ExRace
          | ExReflect
          | ExFold Type Expr
          | ExUnfold Type Expr
          | ExPack Type
          | ExUnpack Type
          | ExUJump
          | ExUSwitch
          deriving (Eq, Show, Data, Typeable)


-- | A variable.
newtype Var = Var String deriving (Eq, Show, Data, Typeable)


-- | Wrapper for displaying values as source code.
newtype SrcCode a = SrcCode a

instance Show (SrcCode Decl) where
    showsPrec _ (SrcCode (DeclType _ v vs t)) = 
        showString "type " . showsVars (map SrcCode (v:vs)) . showString " = " . shows (SrcCode t)
    showsPrec _ (SrcCode (DeclVal _ v e)) = 
        showString "value " . shows (SrcCode v) . showString " = " . shows (SrcCode e)

showsVars :: [SrcCode Var] -> ShowS
showsVars []     = id
showsVars [v]    = shows v
showsVars (v:vs) = shows v . showChar ' ' . showsVars vs

instance Show (SrcCode Expr) where
    showsPrec p (SrcCode (ExPair e1 e2)) = showParen (p > 0) $
        showsPrec 1 (SrcCode e1) . showString " , " . showsPrec 0 (SrcCode e2)
    showsPrec p (SrcCode (ExLam v e)) = showParen (p > 1) $
        showString "\\ " . shows (SrcCode v) . showString " . " . showsPrec 1 (SrcCode e)
    showsPrec p (SrcCode (ExLiftAppB e1 e2)) = showParen (p > 2) $
        showsPrec 2 (SrcCode e1) . showString " <*> " . showsPrec 3 (SrcCode e2)
    showsPrec p (SrcCode (ExLiftAppE e1 e2)) = showParen (p > 2) $
        showsPrec 2 (SrcCode e1) . showString " <.> " . showsPrec 3 (SrcCode e2)
    showsPrec p (SrcCode (ExApp e1 e2)) = showParen (p > 3) $
        showsPrec 3 (SrcCode e1) . showChar ' ' . showsPrec 4 (SrcCode e2)
    showsPrec p (SrcCode (ExConst e)) = showParen (p > 3) $
        showString "const " . showsPrec 4 (SrcCode e)
    showsPrec p (SrcCode (ExBehav f)) = showParen (p > 3) $
        showString "behavior " . showsPrec 4 (SrcCode f)
    showsPrec p (SrcCode (ExEvent t e)) = showParen (p > 3) $
        showString "event " . showsPrec 4 (SrcCode t) . showChar ' ' . showsPrec 4 (SrcCode e)
    showsPrec p (SrcCode (ExFold t f)) = showParen (p > 3) $
        showString "fold [" . shows (SrcCode t) . showString "] " . showsPrec 4 (SrcCode f)
    showsPrec p (SrcCode (ExUnfold t f)) = showParen (p > 3) $
        showString "unfold [" . shows (SrcCode t) . showString "] " . showsPrec 4 (SrcCode f)
    showsPrec _ (SrcCode (ExVar v)) = shows (SrcCode v)
    showsPrec _ (SrcCode (ExNatLit i)) = shows i
    showsPrec _ (SrcCode ExNull) = showChar '?'
    showsPrec _ (SrcCode ExUnit) = showString "()"
    showsPrec _ (SrcCode ExLeft) = showString "left"
    showsPrec _ (SrcCode ExRight) = showString "right"
    showsPrec _ (SrcCode ExCase) = showString "case"
    showsPrec _ (SrcCode ExFst) = showString "first"
    showsPrec _ (SrcCode ExSnd) = showString "second"
    showsPrec _ (SrcCode ExExpand) = showString "expand"
    showsPrec _ (SrcCode ExNever) = showString "never"
    showsPrec _ (SrcCode ExRace) = showString "race"
    showsPrec _ (SrcCode ExReflect) = showString "reflect"
    showsPrec _ (SrcCode ExUSwitch) = showString "ultraswitch"
    showsPrec _ (SrcCode (ExPack t)) = showString "pack [" . shows (SrcCode t) . showChar ']'
    showsPrec _ (SrcCode (ExUnpack t)) = showString "unpack [" . shows (SrcCode t) . showChar ']'
    showsPrec _ (SrcCode ExUJump) = showString "ultrajump"

instance Show (SrcCode Type) where
    showsPrec p (SrcCode (TyMu mu)) = showParen (p > 0) $ shows (SrcCode mu)
    showsPrec p (SrcCode (TyNu nu)) = showParen (p > 0) $ shows (SrcCode nu)
    showsPrec p (SrcCode (TyFun t1 t2)) = showParen (p > 1) $
        showsPrec 2 (SrcCode t1) . showString " -> " . showsPrec 1 (SrcCode t2)
    showsPrec p (SrcCode (TyPlus t1 t2)) = showParen (p > 2) $
        showsPrec 3 (SrcCode t1) . showString " + " . showsPrec 2 (SrcCode t2)
    showsPrec p (SrcCode (TyPair t1 t2)) = showParen (p > 3) $
        showsPrec 4 (SrcCode t1) . showString " * " . showsPrec 3 (SrcCode t2)
    showsPrec p (SrcCode (TyApp v [])) = shows (SrcCode v)
    showsPrec p (SrcCode (TyApp v vs)) = showParen (p > 4) $
        foldl (\f t -> f . showChar ' ' . (showsPrec 5 . SrcCode $ t)) (shows . SrcCode $ v) vs
    showsPrec p (SrcCode (TyBehav t)) = showParen (p > 4) $
        showString "behavior " . showsPrec 5 (SrcCode t)
    showsPrec p (SrcCode (TyEvent t)) = showParen (p > 4) $
        showString "event " . showsPrec 5 (SrcCode t)
    showsPrec _ (SrcCode TyNat) = showString "positive"
    showsPrec _ (SrcCode TyZero) = showChar '0'
    showsPrec _ (SrcCode TyUnit) = showChar '1'
    showsPrec _ (SrcCode (TyVar i)) = showChar '_' . showShortVar ['a'..'z'] 'v' i
    showsPrec _ (SrcCode (TyCon i)) = showChar '_' . showShortVar ['A'..'Z'] 'T' i

showShortVar :: [Char] -> Char -> Integer -> ShowS
showShortVar ls c i = if i<26 then showChar $ ls !! (fromInteger i)
                                  else showChar c . shows (i-26)

instance Show (SrcCode MuType) where
    showsPrec _ (SrcCode (MuType x t)) =
        showString "mu " . shows (SrcCode x) . showString " . " . showsPrec 1 (SrcCode t)


instance Show (SrcCode NuType) where
    showsPrec _ (SrcCode (NuType x t)) =
        showString "nu " . shows (SrcCode x) . showString " . " . showsPrec 1 (SrcCode t)


instance Show (SrcCode Var) where
    showsPrec _ (SrcCode (Var s)) = showString s