{-# LANGUAGE OverloadedStrings #-}
module Language.Virgil.AST where
import Data.ByteString.Lazy (ByteString)
import Data.HashMap.Strict (HashMap, fromList)
import qualified Data.HashMap.Strict as HM
import Data.Scientific (Scientific)
import Data.Text (Text)
import Data.Vector (Vector)
import qualified Data.Vector as V
type Ident = ByteString
-- | A top-level declaration.
data Decl
= Fragment ChValue
| DFun FunDec
| DTyp TypDec
deriving (Eq, Show)
type ChObject = HashMap Text ChValue
type ChArray = Vector ChValue
mkArray :: [ChValue] -> ChValue
mkArray = ChArray . V.fromList
mkObject :: [(Text, ChValue)] -> ChValue
mkObject = ChObject . HM.fromList
data ChValue
= ChObject ChObject
| ChArray ChArray
| ChString Text
| ChNumber Scientific
| ChBool Bool
| ChNull
| ChQuote Expr
deriving (Eq, Show)
data Typ
= TApp Typ Typ
| TNamed Ident
| TArrow
| TUnit
| TVar Ident
| TFix Ident Typ
| TSum [(Ident, Typ)]
| TProd [(Ident, Typ)]
| TTup [Typ]
deriving (Eq, Show)
data TypDec = TypDec
{ tdName :: Ident
, tdVars :: [Ident]
, tdBody :: Typ
} deriving (Eq, Show)
data FunDec = FunDec
{ fdName :: Ident
, fdTyp :: Maybe Typ
, fdCases :: [FnCase]
} deriving (Eq, Show)
data FnCase = FnCase
{ fcPat :: Pattern
, fcBody :: Expr
} deriving (Eq, Show)
data Pattern
= PConstr Ident Pattern
| PVar Ident
| PLit Literal
| PTup [Pattern]
| PUnderscore
deriving (Eq, Show)
type Env = HashMap Ident Value
data Value
= VConstr Ident Value
| VRecord [(Ident, Value)]
| VTup [Value]
| VLam [FnCase] Env
| VLit Literal
deriving (Eq, Show)
data Expr
= ELit Literal
| EConstr Ident
| EApp Expr Expr
| EVar Ident
| ETup [Expr]
| EList [Expr]
| ERecord [(Ident, Expr)]
| ELam [FnCase]
| ETyped Expr Typ
| EAccess Expr Ident
deriving (Eq, Show)
data Literal
= LInt Integer
| LDouble Double
| LString Text
| LBool Bool
deriving (Eq, Show)
{-
with fact : Int -> Int
0 = 1
n = n * fact (n - 1)
-}
fact :: Decl
fact = DFun $ FunDec
{ fdName = "fact"
, fdTyp = Just (TApp (TApp TArrow (TNamed "Int"))
(TNamed "Int"))
, fdCases = [ FnCase { fcPat = PLit (LInt 0)
, fcBody = ELit (LInt 1)
}
, FnCase { fcPat = PVar "n"
, fcBody = EApp (EApp (EVar "mul") (EVar "n"))
(EApp (EVar "fact")
(EApp (EApp
(EVar "sub")
(EVar "n"))
(ELit (LInt 1))))
}
]
}
{-
foo:
bar: '(fact 5)
baz: '(fact 10)
-}
foo :: Decl
foo = Fragment $ ChObject $ fromList
[ ("foo", ChObject $ fromList
[ ("bar", ChQuote (EApp (EVar "fact") (ELit (LInt 5))))
, ("baz", ChQuote (EApp (EVar "fact") (ELit (LInt 10))))
]
)
]