# File eval mode now relies on main function
To encourage organizing code in a way that helps in understanding, I have implemented the common idiom of requiring a `main` function. In tricu and other functional languages, it is usually placed near the top of the module. The evaluator gracefully handles the situation of passing multiple files where the intermediary "library" files do not have main functions.
This commit is contained in:
@ -179,3 +179,8 @@ result :: Env -> T
|
||||
result r = case Map.lookup "__result" r of
|
||||
Just a -> a
|
||||
Nothing -> errorWithoutStackTrace "No __result field found in provided env"
|
||||
|
||||
mainResult :: Env -> T
|
||||
mainResult r = case Map.lookup "main" r of
|
||||
Just a -> a
|
||||
Nothing -> errorWithoutStackTrace "No valid definition for `main` found."
|
||||
|
@ -13,9 +13,9 @@ evaluateFileResult filePath = do
|
||||
contents <- readFile filePath
|
||||
let asts = parseTricu contents
|
||||
let finalEnv = evalTricu Map.empty asts
|
||||
case Map.lookup "__result" finalEnv of
|
||||
case Map.lookup "main" finalEnv of
|
||||
Just finalResult -> return finalResult
|
||||
Nothing -> errorWithoutStackTrace "No expressions to evaluate found"
|
||||
Nothing -> errorWithoutStackTrace "No `main` function detected"
|
||||
|
||||
evaluateFile :: FilePath -> IO Env
|
||||
evaluateFile filePath = do
|
||||
|
12
src/Main.hs
12
src/Main.hs
@ -1,6 +1,6 @@
|
||||
module Main where
|
||||
|
||||
import Eval (evalTricu, result)
|
||||
import Eval (evalTricu, mainResult, result)
|
||||
import FileEval
|
||||
import Parser (parseTricu)
|
||||
import REPL
|
||||
@ -16,7 +16,7 @@ import qualified Data.Map as Map
|
||||
data TricuArgs
|
||||
= Repl
|
||||
| Evaluate { file :: [FilePath], form :: EvaluatedForm }
|
||||
| Decode { file :: [FilePath] }
|
||||
| TDecode { file :: [FilePath] }
|
||||
deriving (Show, Data, Typeable)
|
||||
|
||||
replMode :: TricuArgs
|
||||
@ -31,7 +31,7 @@ evaluateMode = Evaluate
|
||||
\ Defaults to stdin."
|
||||
&= name "f" &= typ "FILE"
|
||||
, form = TreeCalculus &= typ "FORM"
|
||||
&= help "Optional output form: (tree|fsl|ast|ternary|ascii).\n \
|
||||
&= help "Optional output form: (tree|fsl|ast|ternary|ascii|decode).\n \
|
||||
\ Defaults to tricu-compatible `t` tree form."
|
||||
&= name "t"
|
||||
}
|
||||
@ -40,7 +40,7 @@ evaluateMode = Evaluate
|
||||
&= name "eval"
|
||||
|
||||
decodeMode :: TricuArgs
|
||||
decodeMode = Decode
|
||||
decodeMode = TDecode
|
||||
{ file = def
|
||||
&= help "Optional input file path to attempt decoding.\n \
|
||||
\ Defaults to stdin."
|
||||
@ -70,10 +70,10 @@ main = do
|
||||
(filePath:restFilePaths) -> do
|
||||
initialEnv <- evaluateFile filePath
|
||||
finalEnv <- foldM evaluateFileWithContext initialEnv restFilePaths
|
||||
pure $ result finalEnv
|
||||
pure $ mainResult finalEnv
|
||||
let fRes = formatResult form result
|
||||
putStr fRes
|
||||
Decode { file = filePaths } -> do
|
||||
TDecode { file = filePaths } -> do
|
||||
value <- case filePaths of
|
||||
[] -> getContents
|
||||
(filePath:_) -> readFile filePath
|
||||
|
@ -59,10 +59,3 @@ repl env = runInputT defaultSettings (loop env)
|
||||
|
||||
strip :: String -> String
|
||||
strip = dropWhileEnd isSpace . dropWhile isSpace
|
||||
|
||||
decodeResult :: T -> String
|
||||
decodeResult tc
|
||||
| Right num <- toNumber tc = show num
|
||||
| Right str <- toString tc = "\"" ++ str ++ "\""
|
||||
| Right list <- toList tc = "[" ++ intercalate ", " (map decodeResult list) ++ "]"
|
||||
| otherwise = formatResult TreeCalculus tc
|
||||
|
@ -45,7 +45,7 @@ data LToken
|
||||
deriving (Show, Eq, Ord)
|
||||
|
||||
-- Output formats
|
||||
data EvaluatedForm = TreeCalculus | FSL | AST | Ternary | Ascii
|
||||
data EvaluatedForm = TreeCalculus | FSL | AST | Ternary | Ascii | Decode
|
||||
deriving (Show, Data, Typeable)
|
||||
|
||||
-- Environment containing previously evaluated TC terms
|
||||
@ -115,6 +115,7 @@ formatResult FSL = show
|
||||
formatResult AST = show . toAST
|
||||
formatResult Ternary = toTernaryString
|
||||
formatResult Ascii = toAscii
|
||||
formatResult Decode = decodeResult
|
||||
|
||||
toSimpleT :: String -> String
|
||||
toSimpleT s = T.unpack
|
||||
@ -147,4 +148,9 @@ toAscii tree = go tree "" True
|
||||
++ go left (prefix ++ (if isLast then " " else "| ")) False
|
||||
++ go right (prefix ++ (if isLast then " " else "| ")) True
|
||||
|
||||
-- Utility
|
||||
decodeResult :: T -> String
|
||||
decodeResult tc
|
||||
| Right num <- toNumber tc = show num
|
||||
| Right str <- toString tc = "\"" ++ str ++ "\""
|
||||
| Right list <- toList tc = "[" ++ intercalate ", " (map decodeResult list) ++ "]"
|
||||
| otherwise = formatResult TreeCalculus tc
|
||||
|
Reference in New Issue
Block a user