diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2022-01-30 18:48:29 +0200 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2022-01-30 18:48:29 +0200 |
| commit | 542b0d035444416cae8994f89d1ae11c4e4c5df9 (patch) | |
| tree | 3c930e750a679b834fe5373ae8249ae1e7676f67 /src/main.hs | |
| parent | 3fbe17312a7b1474b290c129ebeca9ee7c773c6e (diff) | |
Move interpreter stuff under interpreter.hs
Diffstat (limited to 'src/main.hs')
| -rw-r--r-- | src/main.hs | 238 |
1 files changed, 1 insertions, 237 deletions
diff --git a/src/main.hs b/src/main.hs index c67cea0..6582b38 100644 --- a/src/main.hs +++ b/src/main.hs @@ -4,17 +4,12 @@ import Data.Char import Data.Map (Map, (!)) import qualified Data.Map as M import Debug.Trace (trace, traceShow) +import Interpreter import LTypes import Parser import System.Environment (getArgs) -import System.IO (BufferMode (NoBuffering), hSetBuffering, stdin) import Utils -data Config = Config - { configFileNameM :: Maybe String, - configDebugMode :: Bool - } - getConfig config [] = config getConfig config ("--debug" : rest) = let newConfig = config {configDebugMode = True} @@ -23,237 +18,6 @@ getConfig config (fileName : rest) = let newConfig = config {configFileNameM = Just fileName} in getConfig newConfig rest -debugPrint Config {configDebugMode = mode} message = - if mode - then putStrLn $ "[debug] " ++ message - else pure () - -data LState = LState - { lDict :: Map String LWord, - lStack :: [LWord], - lPhraseDepth :: Int, - lDefs :: Map String [LWord], - lSource :: [LWord], - lStrLitRefMap :: Map String [LWord] - } - deriving (Show) - -evalMode state = lPhraseDepth state == 0 - -debugState Config {configDebugMode = mode} state = - if mode - then do - putStrLn $ "stack: " ++ unwords (map reprWord (lStack state)) - putStrLn $ "source: " ++ unwords (map reprWord (lSource state)) - putStrLn $ "defs: " ++ unwords (M.keys (lDefs state)) - putStrLn $ "dict: " ++ unwords (M.keys (lDict state)) - putStrLn $ "lPhraseDepth: " ++ show (lPhraseDepth state) - putStrLn "" - else pure () - -data ExecStep = ExecContinue | ExecExit - -debugWaitForChar Config {configDebugMode = mode} = - if mode - then do - hSetBuffering stdin NoBuffering - c <- getChar - pure $ case c of - 'q' -> ExecExit - _ -> ExecContinue - else pure ExecContinue - -interpretSource :: Config -> LState -> IO () -interpretSource config LState {lSource = []} = pure () -interpretSource config state@LState {lSource = (word : rest)} = do - newState <- interpretWord state {lSource = rest} word - debugPrint config $ "processed " ++ show word ++ ", newState =" - debugState config newState - step <- debugWaitForChar config - case step of - ExecContinue -> interpretSource config newState - ExecExit -> pure () - -interpretWord :: LState -> LWord -> IO LState --- non-nestable structures -interpretWord state@LState {lStack = stack, lPhraseDepth = phraseDepth} word@(LSymbol "define") = - pure $ - state - { lPhraseDepth = phraseDepth + 1, - lStack = word : stack - } -interpretWord state@LState {lDefs = defs, lStack = stack, lPhraseDepth = phraseDepth} word@(LSymbol ";") = - let defineSpan = takeWhile (\word -> word /= LSymbol "define") stack - newStack = dropWhile (\word -> word /= LSymbol "define") stack $> tail - ((LSymbol identifier) : body) = reverse defineSpan - newDefs = M.insert identifier body defs - in pure $ - state - { lPhraseDepth = phraseDepth - 1, - lDefs = newDefs, - lStack = newStack - } --- words that simply move from source to stack -interpretWord state@LState {lStack = stack} word@(LInteger _) = pure $ state {lStack = word : stack} -interpretWord state@LState {lStack = stack} word@(LFloat _) = pure $ state {lStack = word : stack} -interpretWord state@LState {lStack = stack} word@(LBool _) = pure $ state {lStack = word : stack} -interpretWord state@LState {lStack = stack} word@(LChar _) = pure $ state {lStack = word : stack} -interpretWord state@LState {lStack = stack} word@(LLabel _) = pure $ state {lStack = word : stack} -interpretWord state@LState {lStack = stack} word@(LPhrase _) = pure $ state {lStack = word : stack} --- string literals -interpretWord state@LState {lSource = source, lStrLitRefMap = strLitRefMap} (LStringLitRef ref) = - let strLitP = strLitRefMap ! ref - in pure $ state {lSource = strLitP ++ source} --- phrase markers are always evaled -interpretWord state@LState {lStack = stack, lPhraseDepth = phraseDepth} word@(LSymbol "[") = - pure $ state {lPhraseDepth = phraseDepth + 1, lStack = word : stack} -interpretWord state@LState {lStack = stack, lPhraseDepth = phraseDepth} word@(LSymbol "]") = - let (phrase, stack') = break (== LSymbol "[") stack - newStack = LPhrase (reverse phrase) : tail stack' - in pure $ state {lPhraseDepth = phraseDepth - 1, lStack = newStack} --- definition lookup -interpretWord state@LState {lDefs = defs, lDict = dict, lSource = source, lPhraseDepth = phraseDepth, lStack = stack} word@(LSymbol symbol) - | phraseDepth == 0 = - case M.lookup symbol defs of - Just body -> pure $ state {lSource = body ++ source} - Nothing -> - case symbol of - "dup" -> pure $ state {lStack = head stack : stack} - "drop" -> pure $ state {lStack = tail stack} - "clear" -> pure $ state {lStack = []} - "noop" -> pure state - "true" -> pure $ state {lStack = LBool True : stack} - "false" -> pure $ state {lStack = LBool False : stack} - "not" -> - let (LBool a : stack') = stack - in pure $ state {lStack = LBool (not a) : stack'} - "float" -> - let (LInteger a : stack') = stack - in pure $ state {lStack = LFloat (fromIntegral a) : stack'} - "round" -> - let (LFloat a : stack') = stack - in pure $ state {lStack = LInteger (round a) : stack'} - "!" -> - let (LLabel a : b : stack') = stack - newDict = M.insert a b dict - in pure $ state {lDict = newDict, lStack = stack'} - "@" -> - let (LLabel a : stack') = stack - lookupWord = dict ! a - in pure $ state {lStack = lookupWord : stack'} - "forget" -> - let (LLabel a : stack') = stack - newDict = M.delete a dict - in pure $ state {lStack = stack', lDict = newDict} - "." -> do - let (a : stack') = stack - putStrLn $ reprWord a - pure $ state {lStack = stack'} - "s." -> do - let (word@(LPhrase ws) : stack') = stack - let isLChar w = case w of LChar _ -> True; _ -> False - if not (all isLChar ws) - then error $ "[error] cannot string-print heterogenous phrase: " ++ reprWord word - else pure () - let stringRepr = ws $> map (\(LChar c) -> c) - putStrLn stringRepr - pure $ state {lStack = stack'} - "?" -> do - let (LLabel a : stack') = stack - let lookupWord = dict ! a - putStrLn $ reprWord lookupWord - pure $ state {lStack = stack'} - "+" -> - let (a : b : stack') = stack - result = lAddNumbers b a - in pure $ state {lStack = result : stack'} - "-" -> - let (a : b : stack') = stack - result = lSubNumbers b a - in pure $ state {lStack = result : stack'} - "*" -> - let (a : b : stack') = stack - result = lMultiplyNumbers b a - in pure $ state {lStack = result : stack'} - "/" -> - let (a : b : stack') = stack - result = lDivideNumbers b a - in pure $ state {lStack = result : stack'} - "mod" -> - let (a : b : stack') = stack - result = lModNumbers b a - in pure $ state {lStack = result : stack'} - "eq?" -> - let (a : b : stack') = stack - in pure $ state {lStack = LBool (a == b) : stack'} - "gt?" -> - let (a : b : stack') = stack - in pure $ state {lStack = lGreaterThan b a : stack'} - "lt?" -> - let (a : b : stack') = stack - in pure $ state {lStack = lLesserThan b a : stack'} - "unphrase" -> - let (LPhrase phrase : stack') = stack - in pure $ state {lSource = phrase ++ source, lStack = stack'} - "phrase" -> - let (LSymbol "]" : stack') = stack - (body, _ : newStack) = break (== LSymbol "[") stack' - in pure $ state {lStack = LPhrase (reverse body) : newStack} - "repr" -> - let (word : stack') = stack - reprStr = reprWord word $> map LChar .> LPhrase - in pure $ state {lStack = reprStr : stack'} - "pop" -> - let (LPhrase phrase : stack') = stack - (first : rest) = phrase - in pure $ state {lStack = first : LPhrase rest : stack'} - "stack-size" -> - let size = LInteger $ fromIntegral (length stack) - in pure $ state {lStack = size : stack} - "']" -> - pure $ state {lStack = LSymbol "]" : stack} - "'[" -> - pure $ state {lStack = LSymbol "[" : stack} - "cond" -> - let (fb : tb : (LBool cond) : stack') = stack - LPhrase branch = if cond then tb else fb - newSource = branch ++ source - in pure $ state {lStack = stack', lSource = newSource} - "loop" -> - let (bodyP@(LPhrase body) : condP@(LPhrase cond) : stack') = stack - ifWords = cond ++ [LPhrase (body ++ [condP, bodyP, LSymbol "loop"])] ++ [LPhrase [], LSymbol "cond"] - newSource = ifWords ++ source - in pure $ state {lStack = stack', lSource = newSource} - _ -> error $ "[error] not defined: " ++ symbol - | otherwise = pure $ state {lStack = word : stack} - -lAddNumbers (LInteger a) (LInteger b) = LInteger (a + b) -lAddNumbers (LFloat a) (LFloat b) = LFloat (a + b) -lAddNumbers a b = error $ "[error] sum is not defined for " ++ show a ++ ", " ++ show b - -lSubNumbers (LInteger a) (LInteger b) = LInteger (a - b) -lSubNumbers (LFloat a) (LFloat b) = LFloat (a - b) -lSubNumbers a b = error $ "[error] difference is not defined for " ++ show a ++ ", " ++ show b - -lMultiplyNumbers (LInteger a) (LInteger b) = LInteger (a * b) -lMultiplyNumbers (LFloat a) (LFloat b) = LFloat (a * b) -lMultiplyNumbers a b = error $ "[error] product is not defined for " ++ show a ++ ", " ++ show b - -lDivideNumbers (LInteger a) (LInteger b) = LInteger (a `div` b) -lDivideNumbers (LFloat a) (LFloat b) = LFloat (a / b) -lDivideNumbers a b = error $ "[error] product is not defined for " ++ show a ++ ", " ++ show b - -lGreaterThan (LInteger a) (LInteger b) = LBool (a > b) -lGreaterThan (LFloat a) (LFloat b) = LBool (a > b) -lGreaterThan a b = error $ "[error] greater-than is not defined for " ++ show a ++ ", " ++ show b - -lLesserThan (LInteger a) (LInteger b) = LBool (a < b) -lLesserThan (LFloat a) (LFloat b) = LBool (a < b) -lLesserThan a b = error $ "[error] lesser-than is not defined for " ++ show a ++ ", " ++ show b - -lModNumbers (LInteger a) (LInteger b) = LInteger (a `mod` b) -lModNumbers a b = error $ "[error] modulo is not defined for " ++ show a ++ ", " ++ show b - main :: IO () main = do args <- getArgs |
