Change Value type to just be Dynamic

Restructure into more modules.
This commit is contained in:
2024-10-10 23:53:54 +02:00
parent 41fc74eb98
commit f348bd1e82
19 changed files with 378 additions and 467 deletions

View File

@@ -0,0 +1,18 @@
{-# LANGUAGE GADTs #-}
module Functions.General
( elemOf
) where
import Types (Valuable, IsFunction(..), Token)
import DependencyGenerator (DepGenM, TokenableTo(..), toTupleToken, runFunction)
import Type.Reflection (Typeable, TypeRep, typeRep)
data ElemOf a where ElemOf :: TypeRep a -> ElemOf a
deriving instance Show (ElemOf a)
instance (Show a, Valuable a, Eq a) => IsFunction (ElemOf a) (a, [a]) Bool where
evalFunction (ElemOf _) (y, ys) = y `elem` ys
elemOf :: forall t a b. (Show t, Valuable t, Eq t, TokenableTo t a, TokenableTo [t] b, Typeable t) => a -> b -> DepGenM (Token Bool)
elemOf a b = runFunction (ElemOf (typeRep :: TypeRep t)) =<< toTupleToken a b

View File

@@ -0,0 +1,58 @@
module Functions.Image
( Image(..)
, ImageConversionSettings(..)
, openImage
, saveImage
, convertImage
) where
import Types (IsFunction(..), IsFunctionIO(..), Token)
import DependencyGenerator (DepGenM, TokenableTo(..), toTupleToken,
runFunction, runFunctionIO, runFunctionIO_)
import qualified Codec.Picture as CP
import qualified Codec.Picture.STBIR as CPS
newtype Image = ImageWrapper (CP.Image CP.PixelRGB8)
deriving (Eq)
instance Show Image where
show = const "<image>"
data ImageConversionSettings = ResizeToWidth Int
deriving (Eq, Show)
data OpenImage = OpenImage deriving Show
instance IsFunctionIO OpenImage FilePath Image where
evalFunctionIO OpenImage s = do
imageOrig <- CP.readImage s
case imageOrig of
Left e -> error ("unexpected error: " ++ e)
Right image -> pure $ ImageWrapper $ CP.convertRGB8 image
functionIOTouchesFilesystem OpenImage = False
openImage :: TokenableTo FilePath a => a -> DepGenM (Token Image)
openImage a = runFunctionIO OpenImage =<< toToken a
data SaveImage = SaveImage deriving Show
instance IsFunctionIO SaveImage (Image, FilePath) () where
evalFunctionIO SaveImage (ImageWrapper image, s) =
CP.saveJpgImage 90 s $ CP.ImageRGB8 image
functionIOTouchesFilesystem SaveImage = True
saveImage :: (TokenableTo Image a, TokenableTo FilePath b) => a -> b -> DepGenM ()
saveImage a b = runFunctionIO_ SaveImage =<< toTupleToken a b
data ConvertImage = ConvertImage deriving Show
instance IsFunction ConvertImage (Image, ImageConversionSettings) Image where
evalFunction ConvertImage (ImageWrapper image, ResizeToWidth widthResized) =
let sizeFactor :: Double
sizeFactor = fromIntegral (CP.imageWidth image) / fromIntegral widthResized
heightResized = round (fromIntegral (CP.imageHeight image) / sizeFactor)
in ImageWrapper $ CPS.resize CPS.defaultOptions widthResized heightResized image
convertImage :: (TokenableTo Image a, TokenableTo ImageConversionSettings b) => a -> b -> DepGenM (Token Image)
convertImage a b = runFunction ConvertImage =<< toTupleToken a b

View File

@@ -0,0 +1,24 @@
module Functions.Pandoc
( runPandoc
) where
import Types (IsFunction(..), Token)
import DependencyGenerator (DepGenM, TokenableTo(..), runFunction)
import Data.Text (Text)
import qualified Data.Text.Lazy as TL
import qualified Text.Pandoc as P
import qualified Text.Blaze.Html.Renderer.Text as B
data RunPandoc = RunPandoc deriving Show
instance IsFunction RunPandoc Text Text where
evalFunction RunPandoc contents =
let settings = P.def { P.readerExtensions = P.extensionsFromList [ P.Ext_raw_html ] }
m = P.writeHtml5 P.def =<< P.readMarkdown settings contents
in case P.runPure m of
Left e -> error ("unexpected pandoc error: " ++ show e)
Right html -> TL.toStrict $ B.renderHtml html
runPandoc :: TokenableTo Text a => a -> DepGenM (Token Text)
runPandoc a = runFunction RunPandoc =<< toToken a

View File

@@ -0,0 +1,90 @@
module Functions.Paths
( joinPaths
, fileComponents
, hasExtension
, listDirectory
, isDirectory
, makeDir
, copyFile
, copyTo
) where
import Functions.Text (lowerString)
import Functions.General (elemOf)
import Types (IsFunction(..), IsFunctionIO(..), Token(..))
import DependencyGenerator (DepGenM, TokenableTo(..), toTupleToken, runFunction,
runFunctionIO, runFunctionIO_, untupleSndDepGenM)
import qualified System.Directory as SD
data JoinPaths = JoinPaths deriving Show
instance IsFunction JoinPaths (FilePath, FilePath) FilePath where
evalFunction JoinPaths (s0, s1) = s0 ++ "/" ++ s1
joinPaths :: (TokenableTo FilePath a, TokenableTo FilePath b) => a -> b -> DepGenM (Token FilePath)
joinPaths a b = runFunction JoinPaths =<< TupleToken <$> toToken a <*> toToken b
data FileComponents = FileComponents deriving Show
instance IsFunction FileComponents FilePath (String, String) where
evalFunction FileComponents s =
let (lastRev, firstRev) = span (/= '.') $ reverse s
(base, ext) = case firstRev of
_ : firstRev' -> (reverse firstRev', reverse lastRev)
[] -> (reverse lastRev, "")
in (base, ext)
fileComponents :: TokenableTo FilePath a => a -> DepGenM (Token (String, String))
fileComponents a = runFunction FileComponents =<< toToken a
hasExtension :: (TokenableTo [String] a, TokenableTo FilePath b) => a -> b -> DepGenM (Token Bool)
hasExtension exts filename = do
ext <- lowerString =<< untupleSndDepGenM =<< fileComponents filename
ext `elemOf` exts
data ListDirectory = ListDirectory deriving Show
instance IsFunctionIO ListDirectory FilePath [FilePath] where
evalFunctionIO ListDirectory s =
SD.listDirectory s
functionIOTouchesFilesystem ListDirectory = False
listDirectory :: TokenableTo FilePath a => a -> DepGenM (Token [FilePath])
listDirectory a = runFunctionIO ListDirectory =<< toToken a
data IsDirectory = IsDirectory deriving Show
instance IsFunctionIO IsDirectory FilePath Bool where
evalFunctionIO IsDirectory s =
SD.doesDirectoryExist s
functionIOTouchesFilesystem IsDirectory = False
isDirectory :: TokenableTo FilePath a => a -> DepGenM (Token Bool)
isDirectory a = runFunctionIO IsDirectory =<< toToken a
data MakeDir = MakeDir deriving Show
instance IsFunctionIO MakeDir FilePath () where
evalFunctionIO MakeDir s =
SD.createDirectory s
functionIOTouchesFilesystem MakeDir = True
makeDir :: TokenableTo FilePath a => a -> DepGenM ()
makeDir a = runFunctionIO_ MakeDir =<< toToken a
data CopyFile = CopyFile deriving Show
instance IsFunctionIO CopyFile (FilePath, FilePath) () where
evalFunctionIO CopyFile (source, target) =
SD.copyFile source target
functionIOTouchesFilesystem CopyFile = True
copyFile :: (TokenableTo FilePath a, TokenableTo FilePath b) => a -> b -> DepGenM ()
copyFile a b = runFunctionIO_ CopyFile =<< toTupleToken a b
copyTo :: (TokenableTo FilePath a, TokenableTo FilePath b) => a -> b -> DepGenM ()
copyTo path targetDir = do
pathToken <- toToken path
copyFile pathToken =<< joinPaths targetDir pathToken

View File

@@ -0,0 +1,33 @@
module Functions.Template
( Template(..)
, makeTemplate
, applyTemplate
) where
import Types (IsFunction(..), Token)
import DependencyGenerator (DepGenM, TokenableTo(..), toTupleToken, runFunction)
import Data.Text (Text)
import qualified Data.Text as T
data Template = TemplateParts Text Text
deriving (Eq, Show)
data MakeTemplate = MakeTemplate deriving Show
instance IsFunction MakeTemplate (Text, Text) Template where
evalFunction MakeTemplate (t, c) =
let (beforeContent, after) = T.breakOn c t
afterContent = T.drop (T.length c) after
in TemplateParts beforeContent afterContent
makeTemplate :: (TokenableTo Text a, TokenableTo Text b) => a -> b -> DepGenM (Token Template)
makeTemplate a b = runFunction MakeTemplate =<< toTupleToken a b
data ApplyTemplate = ApplyTemplate deriving Show
instance IsFunction ApplyTemplate (Template, Text) Text where
evalFunction ApplyTemplate (TemplateParts beforeContent afterContent, t) =
T.concat [beforeContent, t, afterContent]
applyTemplate :: (TokenableTo Template a, TokenableTo Text b) => a -> b -> DepGenM (Token Text)
applyTemplate a b = runFunction ApplyTemplate =<< toTupleToken a b

69
byg/src/Functions/Text.hs Normal file
View File

@@ -0,0 +1,69 @@
module Functions.Text
( concatStrings
, concatTexts
, lowerString
, toText
, readTextFile
, saveTextFile
) where
import Types (IsFunction(..), IsFunctionIO(..), Token)
import DependencyGenerator (DepGenM, TokenableTo(..), toTupleToken,
runFunction, runFunctionIO, runFunctionIO_)
import Data.Char (toLower)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.IO as T
data ConcatStrings = ConcatStrings deriving Show
instance IsFunction ConcatStrings [String] String where
evalFunction ConcatStrings = concat
concatStrings :: TokenableTo [String] a => a -> DepGenM (Token String)
concatStrings a = runFunction ConcatStrings =<< toToken a
data ConcatTexts = ConcatTexts deriving Show
instance IsFunction ConcatTexts [Text] Text where
evalFunction ConcatTexts = T.concat
concatTexts :: TokenableTo [Text] a => a -> DepGenM (Token Text)
concatTexts a = runFunction ConcatTexts =<< toToken a
data LowerString = LowerString deriving Show
instance IsFunction LowerString String String where
evalFunction LowerString s = map toLower s
lowerString :: TokenableTo String a => a -> DepGenM (Token String)
lowerString a = runFunction LowerString =<< toToken a
data ToText = ToText deriving Show
instance IsFunction ToText String Text where
evalFunction ToText s = T.pack s
toText :: TokenableTo String a => a -> DepGenM (Token Text)
toText a = runFunction ToText =<< toToken a
data ReadTextFile = ReadTextFile deriving Show
instance IsFunctionIO ReadTextFile FilePath Text where
evalFunctionIO ReadTextFile s =
T.readFile s
functionIOTouchesFilesystem ReadTextFile = False
readTextFile :: TokenableTo FilePath a => a -> DepGenM (Token Text)
readTextFile a = runFunctionIO ReadTextFile =<< toToken a
data SaveTextFile = SaveTextFile deriving Show
instance IsFunctionIO SaveTextFile (Text, FilePath) () where
evalFunctionIO SaveTextFile (t, s) =
T.writeFile s t
functionIOTouchesFilesystem SaveTextFile = True
saveTextFile :: (TokenableTo Text a, TokenableTo FilePath b) => a -> b -> DepGenM ()
saveTextFile a b = runFunctionIO_ SaveTextFile =<< toTupleToken a b