aboutsummaryrefslogtreecommitdiff
path: root/Smurf.icl
diff options
context:
space:
mode:
authorCamil Staps2016-04-12 22:01:25 +0200
committerCamil Staps2016-04-12 22:01:25 +0200
commitb605f30516cc1fef04a706137dc9bc202aadc991 (patch)
tree7c1ea3670052489d455c9262c3a04267afc87503 /Smurf.icl
Initial commit
Diffstat (limited to 'Smurf.icl')
-rw-r--r--Smurf.icl118
1 files changed, 118 insertions, 0 deletions
diff --git a/Smurf.icl b/Smurf.icl
new file mode 100644
index 0000000..f00ef65
--- /dev/null
+++ b/Smurf.icl
@@ -0,0 +1,118 @@
+implementation module Smurf
+
+from StdFunc import o, flip
+import StdArray
+import StdList
+import StdString
+import StdTuple
+import StdFile
+
+from Data.Func import $
+import Control.Applicative
+import Control.Monad
+import Data.Maybe
+
+import SmurfParse
+
+instance zero [a] where zero = []
+
+instance toString Stm
+where
+ toString (Push s) = "\"" +++ s +++ "\""
+ toString Input = "i"
+ toString Output = "o"
+ toString Cat = "+"
+ toString Head = "h"
+ toString Tail = "t"
+ toString Quotify = "q"
+ toString Put = "p"
+ toString Get = "g"
+ toString Exec = "x"
+
+instance zero State where zero = { stack = zero, store = zero }
+
+instance toString State
+where
+ toString {stack, store}
+ = "Stack:\n"
+ +++ foldl (+++) "" [" " +++ val +++ "\n" \\ val <- stack]
+ +++ "Store:\n"
+ +++ foldl (+++) "" [" " +++ var +++ " : " +++ val +++ "\n"
+ \\ (var, val) <- store]
+
+run :: !Program State *File -> *(Maybe State, *File)
+run prog st io
+ # (mbProgSt, io) = step prog st io
+ | isNothing mbProgSt = (Nothing, io)
+ # (prog, st) = fromJust mbProgSt
+ = if (isEmpty prog) (Just st, io) (run prog st io)
+
+step :: !Program State !*File -> *(Maybe (!Program, State), *File)
+step [] st io
+ = (pure ([], st), io)
+step [Push s:p] st io
+ = (pure (p, { st & stack = push s st.stack }), io)
+step [Input:p] st io
+ # (ip, io) = freadline io
+ # ip = ip % (0, size ip - 2)
+ = (pure (p, { st & stack = push ip st.stack }), io)
+step [Output:p] st io
+ # mbSStk = pop st.stack
+ | isNothing mbSStk = (empty, io)
+ # (s, stk) = fromJust mbSStk
+ = (pure (p, { st & stack = stk }), io <<< s)
+step [Cat:p] st io
+ = (pop st.stack >>= \(x,stk) -> pop stk >>= \(y,stk`) ->
+ pure (p, { st & stack = push (y +++ x) stk` }), io)
+step [Head:p] st io
+ = (pop st.stack >>= \(x,stk) -> head x >>= \x` ->
+ pure (p, { st & stack = push x` stk }), io)
+step [Tail:p] st io
+ = (pop st.stack >>= \(x,stk) -> tail x >>= \x` ->
+ pure (p, { st & stack = push x` stk }), io)
+step [Quotify:p] st io
+ = (pop st.stack >>= \(x,stk) ->
+ pure (p, { st & stack = push (quotify x) stk }), io)
+step [Put:p] st io
+ = (pop st.stack >>= \(var,stk) -> pop stk >>= \(val,stk`) ->
+ pure (p, { st & stack = stk`, store = put var val st.store }), io)
+step [Get:p] st io
+ = (pop st.stack >>= \(var,stk) ->
+ pure (p, { st & stack = push (get var st.store) stk }), io)
+step [Exec:p] st io
+ = (pop st.stack >>= parse o fromString o fst >>= \p ->
+ pure (p, zero), io)
+
+push :: String Stack -> Stack
+push s st = [s:st]
+
+pop :: Stack -> Maybe (String, Stack)
+pop [] = empty
+pop [s:ss] = pure (s, ss)
+
+head :: String -> Maybe String
+head "" = empty
+head s = pure $ s % (0,0)
+
+tail :: String -> Maybe String
+tail "" = empty
+tail s = pure $ s % (1, size s - 1)
+
+put :: String String Store -> Store
+put var val store = [(var,val) : filter ((<>)var o fst) store]
+
+get :: String Store -> String
+get var store = case filter ((==)var o fst) store of [] = ""; [(_,val):_] = val
+
+quotify :: (String -> String)
+quotify = (flip (+++) "\"") o ((+++)"\"") o toString o quot o fromString
+where
+ quot :: [Char] -> [Char]
+ quot [] = []
+ quot ['\\':cs] = ['\\':'\\':quot cs]
+ quot ['\n':cs] = ['\\':'n':quot cs]
+ quot ['\r':cs] = ['\\':'r':quot cs]
+ quot ['\t':cs] = ['\\':'t':quot cs]
+ quot ['"':cs] = ['\\':'"':quot cs]
+ quot [c:cs] = [c:quot cs]
+