packages feed

jsonnet-0.1.0.0: src/Language/Jsonnet/Syntax.hs

{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE TemplateHaskell #-}

module Language.Jsonnet.Syntax where

import Control.Applicative (Const (..))
import Data.Data (Data)
import Data.Functor.Sum
import Data.List.NonEmpty
import Data.Scientific (Scientific)
import qualified Data.Text as T
import Data.Typeable (Typeable)
import GHC.Generics
import Language.Jsonnet.Common
import Text.Show.Deriving
import Unbound.Generics.LocallyNameless

type Ident = String

type Param a = (Ident, Maybe a)

data Field a = Field
  { key :: a,
    value :: a,
    visibility :: Visibility,
    override :: Bool
  }
  deriving
    ( Eq,
      Read,
      Show,
      Typeable,
      Data,
      Generic,
      Functor,
      Foldable,
      Traversable
    )

instance Alpha a => Alpha (Field a)

deriveShow1 ''Field

data ExprF a
  = ELit Literal
  | EIdent Ident
  | EFun [Param a] a
  | EApply a (Args a)
  | ELocal
      { bnds :: NonEmpty (Ident, a),
        expr :: a
      }
  | EObj
      { locals :: [(Ident, a)],
        fields :: [Field a]
        --asserts :: [Assert a]
      }
  | EArr [a]
  | EErr a
  | ELookup a a
  | EIndex a a
  | EAssert (Assert a)
  | EIf a a
  | EIfElse a a a
  | ESlice
      { expr :: a,
        start :: Maybe a,
        end :: Maybe a,
        step :: Maybe a
      }
  | EBinOp BinOp a a
  | EUnyOp UnyOp a
  | EArrComp
      { expr :: a,
        comp :: NonEmpty (CompSpec a)
      }
  | EObjComp
      { field :: Field a,
        locals :: [(Ident, a)],
        comp :: NonEmpty (CompSpec a)
      }
  deriving
    ( Show,
      Functor,
      Foldable,
      Traversable,
      Generic,
      Typeable,
      Data
    )

deriveShow1 ''ExprF

newtype Import = Import FilePath
  deriving (Show, Eq)

type ExprF' = Sum ExprF (Const Import)

mkImportF :: String -> ExprF' a
mkImportF = InR . Const . Import

mkNullF :: ExprF' a
mkNullF = (InL . ELit) Null

mkIntF :: Integral b => b -> ExprF' a
mkIntF = InL . ELit . Number . fromIntegral

mkFloatF :: Scientific -> ExprF' a
mkFloatF = InL . ELit . Number

mkStrF :: String -> ExprF' a
mkStrF = InL . ELit . String . T.pack

mkBoolF :: Bool -> ExprF' a
mkBoolF = InL . ELit . Bool

mkIdentF :: Ident -> ExprF' a
mkIdentF = InL . EIdent

mkFunF :: [Param a] -> a -> ExprF' a
mkFunF a = InL . EFun a

mkApplyF :: a -> Args a -> ExprF' a
mkApplyF a = InL . EApply a

mkIfF :: a -> a -> ExprF' a
mkIfF c = InL . EIf c

mkIfElseF :: a -> a -> a -> ExprF' a
mkIfElseF c a = InL . EIfElse c a

mkLocalF :: NonEmpty (Ident, a) -> a -> ExprF' a
mkLocalF n = InL . ELocal n

mkLookupF :: a -> a -> ExprF' a
mkLookupF e = InL . ELookup e

mkIndexF :: a -> a -> ExprF' a
mkIndexF e = InL . EIndex e

mkSliceF :: a -> Maybe a -> Maybe a -> Maybe a -> ExprF' a
mkSliceF e f g = InL . ESlice e f g

mkObjectF :: [Field a] -> [(Ident, a)] -> ExprF' a
mkObjectF fs ls = InL $ EObj ls fs

mkArrayF :: [a] -> ExprF' a
mkArrayF = InL . EArr

mkErrorF :: a -> ExprF' a
mkErrorF = InL . EErr

mkAssertF :: a -> Maybe a -> a -> ExprF' a
mkAssertF e m = InL . EAssert . Assert e m

mkArrCompF :: a -> NonEmpty (CompSpec a) -> ExprF' a
mkArrCompF e = InL . EArrComp e

mkObjCompF :: Field a -> [(Ident, a)] -> NonEmpty (CompSpec a) -> ExprF' a
mkObjCompF f ls = InL . EObjComp f ls