diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2022-10-06 12:28:24 +0300 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2022-12-05 14:21:53 +0200 |
| commit | 77117fa515c5853b5f756d899db0ec9b502298e7 (patch) | |
| tree | 43e6ad438b315debae335b0d9e74b8f7f21bb1d8 | |
| parent | d69313ce44a9415555033926c6a64b4120455502 (diff) | |
Add line info to REPL
| -rw-r--r-- | app/Main.hs | 17 | ||||
| -rw-r--r-- | src/Interpreter.hs | 26 | ||||
| -rw-r--r-- | src/Tokenizer.hs | 11 | ||||
| -rw-r--r-- | src/Utils.hs | 6 | ||||
| -rw-r--r-- | todo.md | 3 |
5 files changed, 43 insertions, 20 deletions
diff --git a/app/Main.hs b/app/Main.hs index a422a5b..1ee5bd8 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -24,20 +24,23 @@ parseArgs config args = _ -> config repl :: LState -> InputT IO () -repl ls = do - minput <- getInputLine "> " +repl = repl' 1 + +repl' :: LineNo -> LState -> InputT IO () +repl' lineNo ls = do + minput <- getInputLine $ show lineNo ++ ":> " case minput of Nothing -> return () Just input -> do - result <- lift $ runL ls (runInlineScript "<repl>" input) + result <- lift $ runL ls $ runInlineScript' lineNo "<repl>" input case result of Left (LException mp ex) -> do outputStrLn $ case mp of Just p -> p ++ " error: " ++ ex Nothing -> "error: " ++ ex - repl ls + repl' (lineNo + 1) ls Right (_, LState { stateEnv = newEnv }) -> do - repl ls { stateEnv = newEnv } + repl' (lineNo + 1) ls { stateEnv = newEnv } main :: IO () main = do @@ -81,8 +84,8 @@ main = do Nothing -> putStrLn $ "error: " ++ ex Right (_, LState { stateEnv = evaledEnv }) -> do when (configUseREPL config) $ - runInputT defaultSettings (repl ls { stateEnv = evaledEnv }) + runInputT defaultSettings $ repl ls { stateEnv = evaledEnv } Nothing -> do putStrLn $ "Lang REPL" putStrLn $ "Use CTRL+D to exit" - runInputT defaultSettings (repl ls) + runInputT defaultSettings $ repl ls diff --git a/src/Interpreter.hs b/src/Interpreter.hs index abe8b85..1f9153c 100644 --- a/src/Interpreter.hs +++ b/src/Interpreter.hs @@ -1,6 +1,7 @@ {-# LANGUAGE LambdaCase #-} module Interpreter ( runInlineScript, + runInlineScript', runScriptFile, evaluate ) where @@ -13,7 +14,7 @@ import Control.Monad.Except import Control.Exception ( try ) import Utils import Builtins -import Tokenizer ( tokenize ) +import Tokenizer ( tokenize' ) import Parser ( parse ) _curryCall :: [AST] -> LFunction -> LContext AST @@ -172,7 +173,7 @@ evaluateLet asts = do args = tail asts d <- getDepth - when (d > 1) $ throwL (astPos letAst) $ "let! can only be called on the top level or in a function definition" + when (d > 1) $ throwL (astPos letAst) $ "let! can only be called on the top level or in a function definition, current depth: " ++ show d (symbol, value) <- letArgsToSymValPairs args env <- getEnv @@ -185,7 +186,7 @@ evaluateEnv asts = do let envAst = head asts d <- getDepth - when (d > 1) $ throwL (astPos envAst) $ "env! can only be called on the top level" + when (d > 1) $ throwL (astPos envAst) $ "env! can only be called on the top level, current depth: " ++ show d env <- getEnv let pairs = M.assocs env @@ -201,7 +202,7 @@ evaluateImport asts = do args = tail asts d <- getDepth - when (d > 1) $ throwL (astPos importAst) $ "import! can only be called on the top level" + when (d > 1) $ throwL (astPos importAst) $ "import! can only be called on the top level, current depth: " ++ show d config <- getConfig let initialState = LState { @@ -274,7 +275,7 @@ evaluate ast@AST { astNode = fnc@(ASTFunctionCall args@(x:_)) } = do config <- getConfig when (configPrintCallStack config) $ liftIO $ putStrLn $ "fn call: " ++ show fnc incrementDepth - let ret = case astNode x of + let task = case astNode x of -- remember to add these as reseved keywords in Builtins! ASTSymbol "\\" -> evaluateFunctionDef args @@ -289,14 +290,17 @@ evaluate ast@AST { astNode = fnc@(ASTFunctionCall args@(x:_)) } = _ -> evaluateUserFunction args - ret `catchError` + ret <- task `catchError` appendError ("when calling function " ++ show x ++ " at " ++ astPos ast) + decrementDepth + return ret evaluate ast@AST { astNode = (ASTSymbol _) } = evaluateSymbol ast evaluate ast@AST { astNode = (ASTVector vec) } = do incrementDepth rets <- mapM evaluate vec `catchError` appendError ("when evaluating elements of vector " ++ show vec ++ " at " ++ astPos ast) + decrementDepth return $ ast { astNode = ASTVector rets } evaluate other = return other @@ -315,8 +319,12 @@ runScriptFile fileName = do runInlineScript fileName src runInlineScript :: String -> String -> LContext [AST] -runInlineScript fileName src = do - tokenized <- tokenize fileName src +runInlineScript fileName src = + runInlineScript' 0 fileName src + +runInlineScript' :: LineNo -> String -> String -> LContext [AST] +runInlineScript' lineNo fileName src = do + tokenized <- tokenize' (lineNo, 1) fileName src LState { stateConfig = config } <- get when (configVerboseMode config) $ liftIO $ putStrLn $ "tokenized:\t\t" ++ show tokenized parsed <- parse tokenized @@ -336,4 +344,4 @@ runInlineScript fileName src = do foldEvaluate (ast:rest) = do newAst <- evaluate ast restEvaled <- foldEvaluate rest - return $ newAst : restEvaled + return $ newAst : restEvaled
\ No newline at end of file diff --git a/src/Tokenizer.hs b/src/Tokenizer.hs index 6a5cc5c..777bedb 100644 --- a/src/Tokenizer.hs +++ b/src/Tokenizer.hs @@ -1,5 +1,6 @@ module Tokenizer ( tokenize, + tokenize' ) where import qualified Data.Bifunctor as B @@ -81,9 +82,15 @@ _tokenize fileName acc current (x:xs) in _tokenize fileName (token1 : token2 : acc) [] xs | otherwise = _tokenize fileName acc (x : current) xs +type RowN = Int +type ColN = Int + tokenize :: String -> String -> LContext [Token] -tokenize fileName src = do - let tChars = augment 1 1 src +tokenize = tokenize' (1, 1) + +tokenize' :: (RowN, ColN) -> String -> String -> LContext [Token] +tokenize' (row, col) fileName src = do + let tChars = augment row col src tokens <- _tokenize fileName [] [] tChars return $ tokens $> reverse diff --git a/src/Utils.hs b/src/Utils.hs index ec8cfc8..4421f8a 100644 --- a/src/Utils.hs +++ b/src/Utils.hs @@ -30,6 +30,8 @@ data LState = LState { stateDepth :: Int } +type LineNo = Int + type LContext a = StateT LState (ExceptT LException IO) a runL :: LState -> LContext a -> IO (Either LException (a, LState)) @@ -58,6 +60,10 @@ incrementDepth :: LContext () incrementDepth = modify (\s -> s { stateDepth = stateDepth s + 1 }) +decrementDepth :: LContext () +decrementDepth = + modify (\s -> s { stateDepth = stateDepth s - 1 }) + getDepth :: LContext Int getDepth = do s <- get @@ -2,10 +2,9 @@ In order of priority -- Add row index to "<repl>" filename in AST +- Write function let expressions properly using lookups - Add proper module system - Make exports a return value of runXXX functions -- Write function let expressions properly using lookups - Write tests! - Come up with a name for the language - Add auto import for standard library (std) and a flag to disable auto import |
