diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2022-12-06 13:43:46 +0200 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2022-12-06 14:23:39 +0200 |
| commit | 21ee11d3df3000a77d5b36d3c7e0a18d9a07d599 (patch) | |
| tree | 5c0be32fdecf596175c5f4504db1cda1ac0a6b21 /src | |
| parent | 64f2dbed84da98c4517cf725b088d870f4aadd98 (diff) | |
Add stdlib stuff, aoc22_1 example
Diffstat (limited to 'src')
| -rw-r--r-- | src/Builtins.hs | 48 | ||||
| -rw-r--r-- | src/Utils.hs | 19 |
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 |
