packages feed

descript-lang-0.2.0.0: src/Descript/Free/Data/Atom/PropPath.hs

{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE OverloadedStrings #-}

module Descript.Free.Data.Atom.PropPath
  ( PropPath (..)
  , SubPropPath
  , PathElem (..)
  , immPath
  , subPath
  , mkPathElem
  ) where

import Descript.Lex.Data.Atom
import Descript.Misc
import Data.Monoid
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as NonEmpty

-- | A property path. Refers to a top-level value's property, or
-- property of a property, or property of a property of a property, etc.
data PropPath an
  = PropPath an (NonEmpty (PathElem an))
  deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable)

-- | A part of a property path. It can refer to a top-level value, or
-- a property, or a property of a property, etc.
type SubPropPath an = [PathElem an]

-- | A property path element. Refers to a property key in a type of
-- record. For example, `a<Foo` would refer to `5` in `Foo[a: 5]`.
data PathElem an
  = PathElemImp (Symbol an)
  | PathElemExp an (Symbol an) (Symbol an)
  deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable)

instance Ann PropPath where
  getAnn (PropPath ann _) = ann

instance Ann PathElem where
  getAnn (PathElemImp x) = getAnn x
  getAnn (PathElemExp ann _ _) = ann

instance Printable PropPath where
  aprintRec sub (PropPath _ elems) = pintercal ">" $ map sub $ NonEmpty.toList elems

instance Printable PathElem where
  aprintRec sub (PathElemImp key) = sub key
  aprintRec sub (PathElemExp _ key head') = sub key <> "<" <> sub head'

instance (Show an) => Summary (PropPath an) where
  summaryRec = pprintSummaryRec

instance (Show an) => Summary (PathElem an) where
  summaryRec = pprintSummaryRec

-- | A 'PropPath' with 1 element.
immPath :: PathElem () -> PropPath ()
immPath x = PropPath () $ x :| []

-- | Prepends the element to the path.
subPath :: PathElem () -> PropPath () -> PropPath ()
subPath x (PropPath () xs) = PropPath () $ x NonEmpty.<| xs

-- | Creates an implicit element if the head reference is 'Nothing', or
-- an explicit one if it's something.
mkPathElem :: an -> Symbol an -> Maybe (Symbol an) -> PathElem an
mkPathElem _ key Nothing = PathElemImp key
mkPathElem ann key (Just head') = PathElemExp ann key head'