packages feed

runGhcBWrap-core-0.1.0.0: src/RunGhc/LocatedModule.hs

{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}

module RunGhc.LocatedModule where

import RunGhc.SystemModule
import RunGhc.Locate
import System.FilePath
import Data.Aeson
import GHC.Generics
import qualified Data.List.Split as List
import qualified Data.List as List
import qualified Data.Text as T
import qualified Data.Text.IO as T

localImport :: LocatedModule -> Import
localImport mod = Import Nothing (getPathSegments mod)

localQualifiedImport :: T.Text -> LocatedModule -> Import
localQualifiedImport qname mod = Import (Just qname) (getPathSegments mod)

-- This is an interesting case
-- because the result can absolutely be wrong
-- But we want to be careful where we allow that failure
-- sometimes we even want that failure!
--
-- One case we never want this failure is with a TestModule we make.
-- User modules however can be designed to fail this way if user
-- has been allowed to make a mistake and has
class Locatable a where
  locate :: [PathSegment] -> a -> LocatedModule
-- | These instances describe the
--   boring logistical differences between
-- 
--  1) A full script given
--  2) Only a function given
--  3) A module we create fully
--
--  While broad, this is the last script of including 
--  some Haskell symbols in our end executable
--
-- The utility of this is that often, linking/locating is the last step we
-- want to think of

instance Locatable Script where
  locate pathSeg script =
    FromLocatedScript $ LocatedScript pathSeg script
instance Locatable SystemModule where
  locate pathSeg sysMod =
    FromSystemModule pathSeg sysMod
instance Locatable Expressions where
  locate pathSeg expressions =
    FromSystemModule pathSeg $ ExpressionsOnly expressions

instance SemigroupModule LocatedModule where
  addImports imports = \case
    loc@(FromLocatedScript _) -> loc
    sys@(FromSystemModule _ _) -> addImports imports sys
  addExtensions extensions = \case
    loc@(FromLocatedScript _) -> loc
    sys@(FromSystemModule _ _) -> addExtensions extensions sys
  addFuncsDataDecls script = \case
    loc@(FromLocatedScript _) -> loc
    sys@(FromSystemModule _ _) -> addFuncsDataDecls script sys
  

getPathSegments :: LocatedModule -> [PathSegment]
getPathSegments = \case
  FromLocatedScript (LocatedScript pathSegs _) -> pathSegs
  FromSystemModule pathSegs _ -> pathSegs

-- Is there value in this construct?
data DependentLocatedModule = DependentLocatedModule
  { _locatedModule :: LocatedModule
  , _deps :: [[PathSegment]]
  }

data LocatedModule
  = FromLocatedScript LocatedScript
  -- ^ Nothing to process to create+write Module
  --   but we probably still need to make it as a lib and link it
  --   with expected targets if it is a user Module
  | FromSystemModule [PathSegment] SystemModule
  deriving Generic
  -- ^ Builder descriptions to create+write Module
instance ToJSON LocatedModule
instance FromJSON LocatedModule


-- | Witness that this script has module written in
data LocatedScript = LocatedScript [PathSegment] Script deriving Generic
instance ToJSON LocatedScript
instance FromJSON LocatedScript

newtype LocatedUserModule = LocatedUserModule
  { getLocatedUserModule :: LocatedModule }
newtype LocatedMainModule = LocatedMainModule
  { getLocatedMainModule :: LocatedModule }
newtype LocatedTestModule = LocatedTestModule
  { getLocatedTestModule :: LocatedModule }
  

newtype Script = Script { getScript :: T.Text } deriving (Show, Generic)
instance ToJSON Script
instance FromJSON Script
instance Semigroup Script where
  Script a <> Script b = Script $ a <> b
instance Monoid Script where
  mempty = Script mempty

newtype Symbol = Symbol { getSymbol :: T.Text } -- should never get a show instance