From 2abeab9c04c5ed28c909c0812984924cdab62711 Mon Sep 17 00:00:00 2001 From: James Eversole Date: Sun, 29 Dec 2024 21:49:57 -0600 Subject: [PATCH] Adds "compiler" and CLI argument handling --- src/Compiler.hs | 23 +++++++++++++++++++++++ src/Library.hs | 2 +- src/Main.hs | 39 ++++++++++++++++++++++++++++++++------- src/REPL.hs | 8 ++++---- src/Research.hs | 2 ++ test.tri | 2 ++ tricu.cabal | 5 +++++ 7 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 src/Compiler.hs create mode 100644 test.tri diff --git a/src/Compiler.hs b/src/Compiler.hs new file mode 100644 index 0000000..87c5a5a --- /dev/null +++ b/src/Compiler.hs @@ -0,0 +1,23 @@ +module Compiler where + +import Eval +import Parser +import Research + +import System.IO + +import qualified Data.Map as Map + +evaluateFile :: FilePath -> IO T +evaluateFile filePath = do + contents <- readFile filePath + let linesOfFile = lines contents + let env = foldl evaluateLine Map.empty linesOfFile + case Map.lookup "__result" env of + Just finalResult -> return finalResult + Nothing -> error "No result found in final environment" + +evaluateLine :: Env -> String -> Env +evaluateLine env line = + let ast = parseSingle line + in evalSingle env ast diff --git a/src/Library.hs b/src/Library.hs index 09c9df2..c4c9ddc 100644 --- a/src/Library.hs +++ b/src/Library.hs @@ -6,7 +6,7 @@ import Research import qualified Data.Map as Map -library :: Map.Map String T +library :: Env library = evalTricu Map.empty $ parseTricu $ unlines [ "false = t" , "true = t t" diff --git a/src/Main.hs b/src/Main.hs index 80c2959..54eecf7 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -1,5 +1,6 @@ module Main where +import Compiler import Eval (evalTricu, result) import Library (library) import Parser (parseTricu) @@ -7,16 +8,40 @@ import REPL (repl) import Research (T) import Text.Megaparsec (runParser) +import System.Console.CmdArgs import qualified Data.Map as Map +data TricuArgs + = Repl + | Compile { file :: FilePath } + deriving (Show, Data, Typeable) + +replMode :: TricuArgs +replMode = Repl + &= help "Start interactive REPL" + &= auto + &= name "repl" + +compileMode :: TricuArgs +compileMode = Compile { file = def &= typ "FILE" &= help "Relative or absolute path to compile" } + &= help "Compile a file and return the result of the expression in the final line" + &= explicit + &= name "compile" + main :: IO () main = do - putStrLn "Welcome to the tricu Interpreter" - putStrLn "You can exit at any time by typing and entering: " - putStrLn ":_exit" - repl library + args <- cmdArgs $ modes [replMode, compileMode] + &= help "tricu: Exploring Tree Calculus" + &= program "tricu" + &= summary "tricu - compiler and repl" + + case args of + Repl -> do + putStrLn "Welcome to the tricu REPL" + putStrLn "You can exit with `CTRL+D` or the `:_exit` command.`" + repl Map.empty + Compile filePath -> do + result <- evaluateFile filePath + print result -runTricu :: String -> T -runTricu s = result (evalTricu Map.empty $ parseTricu s) -runTricuEnv env s = result (evalTricu env $ parseTricu s) diff --git a/src/REPL.hs b/src/REPL.hs index d283956..76edcd6 100644 --- a/src/REPL.hs +++ b/src/REPL.hs @@ -12,10 +12,10 @@ import System.Console.Haskeline import qualified Data.Map as Map -repl :: Map.Map String T -> IO () +repl :: Env -> IO () repl env = runInputT defaultSettings (loop env) where - loop :: Map.Map String T -> InputT IO () + loop :: Env -> InputT IO () loop env = do minput <- getInputLine "tricu < " case minput of @@ -28,7 +28,7 @@ repl env = runInputT defaultSettings (loop env) newEnv <- liftIO $ (processInput env input `catch` errorHandler env) loop newEnv - processInput :: Map.Map String T -> String -> IO (Map.Map String T) + processInput :: Env -> String -> IO (Env) processInput env input = do let clearEnv = Map.delete "__result" env newEnv = evalSingle clearEnv (parseSingle input) @@ -39,7 +39,7 @@ repl env = runInputT defaultSettings (loop env) Nothing -> return () return newEnv - errorHandler :: Map.Map String T -> SomeException -> IO (Map.Map String T) + errorHandler :: Env -> SomeException -> IO (Env) errorHandler env e = do putStrLn $ "Error: " ++ show e return env diff --git a/src/Research.hs b/src/Research.hs index e12981e..0b59f1d 100644 --- a/src/Research.hs +++ b/src/Research.hs @@ -89,6 +89,8 @@ toList (Fork x rest) = case toList rest of toList _ = Left "Invalid Tree Calculus list" -- Utility +type Env = Map.Map String T + toAscii :: T -> String toAscii tree = go tree "" True where diff --git a/test.tri b/test.tri new file mode 100644 index 0000000..7ec7d67 --- /dev/null +++ b/test.tri @@ -0,0 +1,2 @@ +x = t t t +x diff --git a/tricu.cabal b/tricu.cabal index 5f92536..48a7270 100644 --- a/tricu.cabal +++ b/tricu.cabal @@ -19,6 +19,7 @@ executable tricu default-extensions: ConstraintKinds DataKinds + DeriveDataTypeable DeriveGeneric FlexibleContexts FlexibleInstances @@ -28,11 +29,13 @@ executable tricu ghc-options: -threaded -rtsopts -with-rtsopts=-N -optl-pthread -fPIC build-depends: base >=4.7 + , cmdargs , containers , haskeline , megaparsec , mtl other-modules: + Compiler Eval Lexer Library @@ -47,6 +50,7 @@ test-suite tricu-tests hs-source-dirs: test, src build-depends: base + , cmdargs , containers , haskeline , megaparsec @@ -56,6 +60,7 @@ test-suite tricu-tests , tasty-quickcheck default-language: Haskell2010 other-modules: + Compiler Eval Lexer Library