Carriage/Carriage.hs
Jump to navigation
Jump to search
Quick and dirty implementation of Carriage in Haskell. Program might not explode under every condition it is supposed to explode (but please do consider every error to be an explosion, not just BOOM). Runs the two examples given in the article.
explode = error "BOOM"
data Elem = Int Integer
| Fn ([Elem] -> [Elem])
| Sym Char
instance Show Elem where
show (Int i) = show i
show (Fn _) = "<fn>"
show (Sym c) = show c
pop (e:s) = (e, s)
push s e = (e:s)
pick 0 ((Sym _):_) = explode
pick 0 (e:_) = e
pick n (_:s) = pick (n-1) s
slice _ 0 _ = []
slice p k s = slice' p (reverse s)
where
slice' 0 s = take (fromIntegral k) s
slice' n (_:s) = slice' (n-1) s
ci " " = id
ci "1" = \s -> push s $ Int 1
ci "$" = snd . pop
ci "#" = \s -> push s $ Int $ fromIntegral $ length s
ci "~" = (\s ->
let
(Int a, s') = pop(s)
in
push s' $ pick a s')
ci "\\" = (\s ->
let
(a, s') = pop(s)
(b, s'') = pop(s')
in
push (push s'' a) b)
ci "+" = (\s ->
let
(Int a, s') = pop(s)
(Int b, s'') = pop(s')
in
push s'' $ Int (a + b))
ci "-" = (\s ->
let
(Int a, s') = pop(s)
(Int b, s'') = pop(s')
in
push s'' $ Int (b - a))
ci "@" = (\s ->
let
(Int k, s') = pop(s)
(Int p, s'') = pop(s')
fn = ci $ map (\(Sym c) -> c) $ slice p k s''
in
push s'' (Fn fn))
ci "!" = \s -> let (Fn f, s') = pop(s) in f s'
ci [] = id
ci [_] = explode
ci (sym:rest) = \x -> (ci rest) ((ci [sym]) x)
di = reverse . map (\x -> Sym x) . filter (\x -> x /= ' ')
run prog = (ci prog) (di prog)