packages feed

disco-0.1.6: src/Disco/Syntax/Prims.hs

{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}

-----------------------------------------------------------------------------

-----------------------------------------------------------------------------

-- SPDX-License-Identifier: BSD-3-Clause

-- |
-- Module      :  Disco.Syntax.Prims
-- Copyright   :  disco team and contributors
-- Maintainer  :  byorgey@gmail.com
--
-- Concrete syntax for the prims (i.e. built-in constants) supported
-- by the language.
module Disco.Syntax.Prims (
  Prim (..),
  PrimInfo (..),
  primTable,
  toPrim,
  primMap,
) where

import GHC.Generics (Generic)
import Unbound.Generics.LocallyNameless

import Data.Map (Map)
import qualified Data.Map as M

import Data.Data (Data)
import Disco.Syntax.Operators

------------------------------------------------------------
-- Prims
------------------------------------------------------------

-- | Primitives, /i.e./ built-in constants.
data Prim where
  PrimUOp ::
    UOp ->
    -- | Unary operator
    Prim
  PrimBOp ::
    BOp ->
    -- | Binary operator
    Prim
  PrimLeft ::
    -- | Left injection into a sum type.
    Prim
  PrimRight ::
    -- | Right injection into a sum type.
    Prim
  PrimSqrt ::
    -- | Integer square root (@sqrt@)
    Prim
  PrimFloor ::
    -- | Floor of fractional type (@floor@)
    Prim
  PrimCeil ::
    -- | Ceiling of fractional type (@ceiling@)
    Prim
  PrimAbs ::
    -- | Absolute value (@abs@)
    Prim
  PrimPower ::
    -- | Power set (XXX or bag?)
    Prim
  PrimList ::
    -- | Container -> list conversion
    Prim
  PrimBag ::
    -- | Container -> bag conversion
    Prim
  PrimSet ::
    -- | Container -> set conversion
    Prim
  PrimB2C ::
    -- | bag -> set of counts conversion
    Prim
  PrimC2B ::
    -- | set of counts -> bag conversion
    Prim
  PrimUC2B ::
    -- | unsafe set of counts -> bag conversion
    --   that assumes all distinct
    Prim
  PrimMapToSet ::
    -- | Map k v -> Set (k × v)
    Prim
  PrimSetToMap ::
    -- | Set (k × v) -> Map k v
    Prim
  PrimSummary ::
    -- | Get Adjacency list of Graph
    Prim
  PrimVertex ::
    -- | Construct a graph Vertex
    Prim
  PrimEmptyGraph ::
    -- | Empty graph
    Prim
  PrimOverlay ::
    -- | Overlay two Graphs
    Prim
  PrimConnect ::
    -- | Connect Graph to another with directed edges
    Prim
  PrimInsert ::
    -- | Insert into map
    Prim
  PrimLookup ::
    -- | Get value associated with key in map
    Prim
  PrimEach ::
    -- | Each operation for containers
    Prim
  PrimReduce ::
    -- | Reduce operation for containers
    Prim
  PrimFilter ::
    -- | Filter operation for containers
    Prim
  PrimJoin ::
    -- | Monadic join for containers
    Prim
  PrimMerge ::
    -- | Generic merge operation for bags/sets
    Prim
  PrimIsPrime ::
    -- | Efficient primality test
    Prim
  PrimFactor ::
    -- | Factorization
    Prim
  PrimFrac ::
    -- | Turn a rational into a pair (num, denom)
    Prim
  PrimCrash ::
    -- | Crash
    Prim
  PrimUntil ::
    -- | @[x, y, z .. e]@
    Prim
  PrimHolds ::
    -- | Test whether a proposition holds
    Prim
  PrimLookupSeq ::
    -- | Lookup OEIS sequence
    Prim
  PrimExtendSeq ::
    -- | Extend OEIS sequence
    Prim
  deriving (Show, Read, Eq, Ord, Generic, Alpha, Subst t, Data)

------------------------------------------------------------
-- Concrete syntax for prims
------------------------------------------------------------

-- | An info record for a single primitive name, containing the
--   primitive itself, its concrete syntax, and whether it is
--   "exposed", /i.e./ available to be used in the surface syntax of
--   the basic language.  Unexposed prims can only be referenced by
--   enabling the Primitives language extension and prefixing their
--   name by @$@.
data PrimInfo = PrimInfo
  { thePrim :: Prim
  , primSyntax :: String
  , primExposed :: Bool
  -- Is the prim available in the normal syntax of the language?
  --
  --   primExposed = True means that the bare primSyntax can be used
  --   in the surface syntax, and the prim will be pretty-printed as
  --   the primSyntax.
  --
  --   primExposed = False means that the only way to enter it is to
  --   enable the Primitives language extension and write a $
  --   followed by the primSyntax.  The prim will be pretty-printed with a $
  --   prefix.
  --
  --   In no case is a prim a reserved word.
  }

-- | A table containing a 'PrimInfo' record for every non-operator
--   'Prim' recognized by the language.
primTable :: [PrimInfo]
primTable =
  [ PrimInfo PrimLeft "left" True
  , PrimInfo PrimRight "right" True
  , PrimInfo (PrimUOp Not) "not" True
  , PrimInfo PrimSqrt "sqrt" True
  , PrimInfo PrimFloor "floor" True
  , PrimInfo PrimCeil "ceiling" True
  , PrimInfo PrimAbs "abs" True
  , PrimInfo PrimPower "power" True
  , PrimInfo PrimList "list" True
  , PrimInfo PrimBag "bag" True
  , PrimInfo PrimSet "set" True
  , PrimInfo PrimB2C "bagCounts" True
  , PrimInfo PrimC2B "bagFromCounts" True
  , PrimInfo PrimUC2B "unsafeBagFromCounts" False
  , PrimInfo PrimMapToSet "mapToSet" True
  , PrimInfo PrimSetToMap "map" True
  , PrimInfo PrimSummary "summary" True
  , PrimInfo PrimVertex "vertex" True
  , PrimInfo PrimEmptyGraph "emptyGraph" True
  , PrimInfo PrimOverlay "overlay" True
  , PrimInfo PrimConnect "connect" True
  , PrimInfo PrimInsert "insert" True
  , PrimInfo PrimLookup "lookup" True
  , PrimInfo PrimEach "each" True
  , PrimInfo PrimReduce "reduce" True
  , PrimInfo PrimFilter "filter" True
  , PrimInfo PrimJoin "join" False
  , PrimInfo PrimMerge "merge" False
  , PrimInfo PrimIsPrime "isPrime" False
  , PrimInfo PrimFactor "factor" False
  , PrimInfo PrimFrac "frac" False
  , PrimInfo PrimCrash "crash" False
  , PrimInfo PrimUntil "until" False
  , PrimInfo PrimHolds "holds" True
  , PrimInfo PrimLookupSeq "lookupSequence" False
  , PrimInfo PrimExtendSeq "extendSequence" False
  ]

-- | Find any exposed prims with the given name.
toPrim :: String -> [Prim]
toPrim x = [p | PrimInfo p syn True <- primTable, syn == x]

-- | A convenient map from each 'Prim' to its info record.
primMap :: Map Prim PrimInfo
primMap =
  M.fromList $
    [(p, pinfo) | pinfo@(PrimInfo p _ _) <- primTable]