{-# LANGUAGE BangPatterns #-} module Interpreter(interpret) where import qualified Data.Vector.Mutable as MV import AST type Tape = MV.IOVector Byte interpret :: Program -> [Byte] -> IO [Byte] interpret (Program inss) inp = MV.replicate 60000 0 >>= \tape -> interInss 0 tape 30000 inss inp interInss :: Int -> Tape -> Int -> [Instruction] -> [Byte] -> IO [Byte] interInss _ _ _ [] _ = return [] -- interInss count _ _ _ _ | count > 2000000000 = return [] interInss !count !tape !memp allinss@(ins:rest) inp = case ins of IAdd value offset -> do MV.modify tape (+ value) (memp + offset) interInss (count + 1) tape memp rest inp ISet value offset -> do MV.write tape (memp + offset) value interInss (count + 1) tape memp rest inp ICopy from to mult -> do value <- MV.read tape (memp + from) MV.modify tape ((+) (mult * value)) (memp + to) interInss (count + 1) tape memp rest inp ISlide offset -> do interInss (count + 1) tape (memp + offset) rest inp ILoop iins offset -> do value <- MV.read tape (memp + offset) if value /= 0 then interInss (count + 1) tape memp (iins ++ allinss) inp else interInss (count + 1) tape memp rest inp IInput offset -> do let (c:cs) = inp MV.write tape (memp + offset) c interInss (count + 1) tape memp rest cs IOutput offset -> do value <- MV.read tape (memp + offset) (value :) <$> interInss (count + 1) tape memp rest inp IStart -> do interInss (count + 1) tape memp rest inp