aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJan Tuomi <jans.tuomi@gmail.com>2022-12-06 13:43:46 +0200
committerJan Tuomi <jans.tuomi@gmail.com>2022-12-06 14:23:39 +0200
commit21ee11d3df3000a77d5b36d3c7e0a18d9a07d599 (patch)
tree5c0be32fdecf596175c5f4504db1cda1ac0a6b21 /src
parent64f2dbed84da98c4517cf725b088d870f4aadd98 (diff)
Add stdlib stuff, aoc22_1 example
Diffstat (limited to 'src')
-rw-r--r--src/Builtins.hs48
-rw-r--r--src/Utils.hs19
2 files changed, 67 insertions, 0 deletions
diff --git a/src/Builtins.hs b/src/Builtins.hs
index ec14c2f..b731e66 100644
--- a/src/Builtins.hs
+++ b/src/Builtins.hs
@@ -29,8 +29,13 @@ builtinEnv = M.fromList [
-- string operations
builtinSubstr,
builtinStrToVec,
+ builtinLen,
-- vector & string operations
builtinConcat,
+ -- filesystem operations
+ builtinReadFile,
+ builtinWriteFile,
+ builtinAppendFile,
-- special
builtinPrint,
("unit", makeNonsenseAST ASTUnit),
@@ -246,6 +251,13 @@ builtinConcat = (name, makeNonsenseAST $ ASTFunction True fn1) where
fn2 ast2 = throwL (astPos ast2) $ argError2 name ast1 ast2
fn1 ast1 = throwL (astPos ast1) $ argError1 name ast1
+builtinLen :: (String, AST)
+builtinLen = (name, makeNonsenseAST $ ASTFunction True fn1) where
+ name = "len"
+ fn1 AST { astNode = ASTString str } =
+ return $ makeNonsenseAST $ ASTInteger $ length str
+ fn1 ast1 = throwL (astPos ast1) $ argError1 name ast1
+
builtinFatal :: (String, AST)
builtinFatal = (name, makeNonsenseAST $ ASTFunction False fn1) where
name = "fatal!"
@@ -260,3 +272,39 @@ builtinKind = (name, makeNonsenseAST $ ASTFunction True fn1) where
fn1 AST { astNode = ASTRecord identifier _} =
return $ makeNonsenseAST $ ASTString identifier
fn1 ast1 = throwL (astPos ast1) $ argError1 name ast1
+
+builtinReadFile :: (String, AST)
+builtinReadFile = (name, makeNonsenseAST $ ASTFunction False fn1) where
+ name = "read-file!"
+ fn1 ast1@AST { astNode = ASTString filePath } = do
+ contentsM <- liftIO $ safeReadFile filePath
+ case contentsM of
+ Just contents -> return $ makeNonsenseAST $ ASTString contents
+ Nothing -> throwL (astPos ast1) $ "failed to read file: " ++ filePath
+ fn1 ast1 = throwL (astPos ast1) $ argError1 name ast1
+
+builtinWriteFile :: (String, AST)
+builtinWriteFile = (name, makeNonsenseAST $ ASTFunction False fn1) where
+ name = "write-file!"
+ fn1 ast1@AST { astNode = ASTString filePath } =
+ return $ makeNonsenseAST $ ASTFunction True $ fn2 where
+ fn2 AST { astNode = ASTString content } = do
+ resultM <- liftIO $ safeWriteFile filePath content
+ case resultM of
+ Just () -> return $ makeNonsenseAST $ ASTUnit
+ Nothing -> throwL (astPos ast1) $ "failed to write file: " ++ filePath
+ fn2 ast2 = throwL (astPos ast2) $ argError2 name ast1 ast2
+ fn1 ast1 = throwL (astPos ast1) $ argError1 name ast1
+
+builtinAppendFile :: (String, AST)
+builtinAppendFile = (name, makeNonsenseAST $ ASTFunction False fn1) where
+ name = "append-file!"
+ fn1 ast1@AST { astNode = ASTString filePath } =
+ return $ makeNonsenseAST $ ASTFunction True $ fn2 where
+ fn2 AST { astNode = ASTString content } = do
+ resultM <- liftIO $ safeAppendFile filePath content
+ case resultM of
+ Just () -> return $ makeNonsenseAST $ ASTUnit
+ Nothing -> throwL (astPos ast1) $ "failed to append to file: " ++ filePath
+ fn2 ast2 = throwL (astPos ast2) $ argError2 name ast1 ast2
+ fn1 ast1 = throwL (astPos ast1) $ argError1 name ast1
diff --git a/src/Utils.hs b/src/Utils.hs
index bcac58e..2f9e3c0 100644
--- a/src/Utils.hs
+++ b/src/Utils.hs
@@ -2,6 +2,7 @@
module Utils where
import Control.Monad.Except
+import Control.Exception (IOException, catch)
import Control.Monad.State
import qualified Data.Map as M
import qualified Data.List as L
@@ -301,3 +302,21 @@ separateNsIdPart identifier =
nsPartText = T.concat $ L.init parts
idPartText = L.last parts
in (T.unpack nsPartText, T.unpack idPartText)
+
+safeReadFile :: FilePath -> IO (Maybe String)
+safeReadFile p = (Just <$> readFile p) `catch` handler
+ where
+ handler :: IOException -> IO (Maybe String)
+ handler _ = pure Nothing
+
+safeWriteFile :: FilePath -> String -> IO (Maybe ())
+safeWriteFile p content = (Just <$> writeFile p content) `catch` handler
+ where
+ handler :: IOException -> IO (Maybe ())
+ handler _ = pure Nothing
+
+safeAppendFile :: FilePath -> String -> IO (Maybe ())
+safeAppendFile p content = (Just <$> appendFile p content) `catch` handler
+ where
+ handler :: IOException -> IO (Maybe ())
+ handler _ = pure Nothing