summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Tuomi <jans.tuomi@gmail.com>2022-01-27 21:49:56 +0200
committerJan Tuomi <jans.tuomi@gmail.com>2022-01-27 21:49:56 +0200
commit7dbb6e631346cbb790300d823dff6efdf84288d7 (patch)
treeb1607a7be9339e362b59a9db13f39f13b2b45849
Initial commit
-rw-r--r--.gitignore4
-rwxr-xr-xrun.sh5
-rw-r--r--samples/foo.sample1
-rw-r--r--src/main.hs48
-rw-r--r--src/utils.hs7
5 files changed, 65 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1561641
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+*.hi
+*.o
+interpreter
+.git/
diff --git a/run.sh b/run.sh
new file mode 100755
index 0000000..93f0954
--- /dev/null
+++ b/run.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+set -uxo pipefail
+ghc -o interpreter src/*.hs
+./interpreter $@
diff --git a/samples/foo.sample b/samples/foo.sample
new file mode 100644
index 0000000..a64a29c
--- /dev/null
+++ b/samples/foo.sample
@@ -0,0 +1 @@
+1 1 + . \ No newline at end of file
diff --git a/src/main.hs b/src/main.hs
new file mode 100644
index 0000000..90de59e
--- /dev/null
+++ b/src/main.hs
@@ -0,0 +1,48 @@
+module Main where
+
+import Data.Char
+import System.Environment (getArgs)
+import Utils
+
+getFilename [] = error "empty argument list"
+getFilename (f : fs) = f
+
+data LWord
+ = LSymbol String
+ | LInteger Integer
+ deriving (Show)
+
+reprWord (LSymbol a) = a
+reprWord (LInteger a) = show a
+
+parseWord rawStr
+ | all isDigit rawStr = LInteger (read rawStr)
+ | otherwise = LSymbol rawStr
+
+parseSource source = source $> words .> map parseWord
+
+interpretSource :: [LWord] -> [LWord] -> IO ()
+interpretSource _ [] = putStrLn "done"
+interpretSource stack (word : rest) = do
+ newStack <- interpretWord stack word
+ interpretSource newStack rest
+
+interpretWord :: [LWord] -> LWord -> IO [LWord]
+interpretWord stack word@(LInteger value) = pure $ word : stack
+interpretWord (a : stack) word@(LSymbol ".") = do
+ putStrLn $ reprWord a
+ pure stack
+interpretWord ((LInteger a) : (LInteger b) : stack) word@(LSymbol "+") = pure $ LInteger (a + b) : stack
+interpretWord _ other = error $ "[error] runtime error at " ++ show other
+
+main :: IO ()
+main = do
+ args <- getArgs
+ let filename = getFilename args
+ putStrLn $ "[info] executing file " ++ filename
+ source <- readFile filename
+ putStrLn source
+ let parsed = parseSource source
+ putStrLn $ "[info] parsed words:\n" ++ show parsed
+ putStrLn "[info] interpreter output:"
+ interpretSource [] parsed
diff --git a/src/utils.hs b/src/utils.hs
new file mode 100644
index 0000000..33f3f6e
--- /dev/null
+++ b/src/utils.hs
@@ -0,0 +1,7 @@
+module Utils where
+
+(.>) = flip (.)
+
+($>) = flip ($)
+
+infixr 6 $>