quox/lib/Quox/Parser/LoadFile.idr

101 lines
2.4 KiB
Idris
Raw Normal View History

2023-08-25 12:09:06 -04:00
module Quox.Parser.LoadFile
2023-10-19 23:23:56 -04:00
import public Quox.Parser.Syntax
import Quox.Parser.Parser
2023-08-25 12:09:06 -04:00
import Quox.Loc
import Quox.EffExtra
import Data.IORef
import Data.SortedSet
import System.File
import System.Path
%default total
public export
FilePath : Type
FilePath = String
public export
data LoadFileL : (lbl : k) -> Type -> Type where
[search lbl]
Seen : FilePath -> LoadFileL lbl Bool
SetSeen : FilePath -> LoadFileL lbl ()
2023-10-19 23:23:56 -04:00
DoLoad : Loc -> FilePath -> LoadFileL lbl PFile
2023-08-25 12:09:06 -04:00
public export
LoadFile : Type -> Type
LoadFile = LoadFileL ()
export
seenAt : (0 lbl : k) -> Has (LoadFileL lbl) fs => FilePath -> Eff fs Bool
seenAt lbl file = send $ Seen {lbl} file
export %inline
seen : Has LoadFile fs => FilePath -> Eff fs Bool
seen = seenAt ()
export
setSeenAt : (0 lbl : k) -> Has (LoadFileL lbl) fs => FilePath -> Eff fs ()
setSeenAt lbl file = send $ SetSeen {lbl} file
export %inline
setSeen : Has LoadFile fs => FilePath -> Eff fs ()
setSeen = setSeenAt ()
export
doLoadAt : (0 lbl : k) -> Has (LoadFileL lbl) fs =>
2023-10-19 23:23:56 -04:00
Loc -> FilePath -> Eff fs PFile
2023-08-25 12:09:06 -04:00
doLoadAt lbl loc file = send $ DoLoad {lbl} loc file
export %inline
2023-10-19 23:23:56 -04:00
doLoad : Has LoadFile fs => Loc -> FilePath -> Eff fs PFile
2023-08-25 12:09:06 -04:00
doLoad = doLoadAt ()
public export
SeenSet : Type
SeenSet = SortedSet FilePath
public export
IncludePath : Type
IncludePath = List String
export covering
readFileFrom : HasIO io => IncludePath -> FilePath ->
io (Either FileError String)
readFileFrom inc f =
case !(firstExists $ map (</> f) inc) of
Just path => readFile path
Nothing => pure $ Left $ FileNotFound
export covering
2023-10-19 23:23:56 -04:00
handleLoadFileIOE : (Loc -> FilePath -> FileError -> e) ->
(FilePath -> Parser.Error -> e) ->
2023-08-25 12:09:06 -04:00
IORef SeenSet -> IncludePath ->
LoadFileL lbl a -> IOErr e a
2023-10-19 23:23:56 -04:00
handleLoadFileIOE injf injp seen inc = \case
2023-08-25 12:09:06 -04:00
Seen f => contains f <$> readIORef seen
SetSeen f => modifyIORef seen $ insert f
2023-10-19 23:23:56 -04:00
DoLoad l f =>
case !(readFileFrom inc f) of
Left err => ioLeft $ injf l f err
Right str => either (ioLeft . injp f) pure $ lexParseInput f str
2023-08-25 12:09:06 -04:00
export
loadFileAt : (0 lbl : k) -> Has (LoadFileL lbl) fs =>
2023-10-19 23:23:56 -04:00
Loc -> FilePath -> Eff fs (Maybe PFile)
2023-08-25 12:09:06 -04:00
loadFileAt lbl loc file =
if !(seenAt lbl file)
then pure Nothing
else Just <$> doLoadAt lbl loc file <* setSeenAt lbl file
export
2023-10-19 23:23:56 -04:00
loadFile : Has LoadFile fs => Loc -> FilePath -> Eff fs (Maybe PFile)
2023-08-25 12:09:06 -04:00
loadFile = loadFileAt ()