never executed always true always false
    1 module HelVM.HelMA.Automata.ETA.Optimizer (
    2   optimize,
    3 )
    4 where
    5 
    6 import           HelVM.HelMA.Automata.ETA.OperandParsers
    7 import           HelVM.HelMA.Automata.ETA.Token
    8 
    9 import           HelVM.HelMA.Automaton.Instruction
   10 import           HelVM.HelMA.Automaton.Instruction.Extras.Constructors
   11 
   12 import           HelVM.HelIO.Control.Safe
   13 
   14 import           Control.Applicative.Tools
   15 
   16 import           Data.List.Extra
   17 import qualified Data.List.Index                                       as List
   18 
   19 import qualified Data.ListLike                                         as LL
   20 
   21 optimize :: MonadSafe m => TokenList -> m InstructionList
   22 optimize = appendEnd <.> join <.> optimizeLines
   23 
   24 appendEnd :: InstructionList -> InstructionList
   25 appendEnd l = l <> [markNI 0 , End]
   26 
   27 optimizeLines :: MonadSafe m => TokenList -> m [InstructionList]
   28 optimizeLines = sequence . optimizeLineInit <.> lineFromTuple2 <.> splitOnRAndIndex2
   29 
   30 splitOnRAndIndex2 :: TokenList -> [(Natural, [TokenList])]
   31 splitOnRAndIndex2 = indexedByNaturalWithOffset 1 <.> List.indexed . filterNull . tails . splitOn [R]
   32 
   33 indexedByNaturalWithOffset :: Int -> (Int , a) -> (Natural , a)
   34 indexedByNaturalWithOffset offset (i , a) = (fromIntegral (i + offset) , a)
   35 
   36 optimizeLineInit :: MonadSafe m => Line -> m InstructionList
   37 optimizeLineInit line = (markNI (currentAddress line) : ) <$> optimizeLineTail line
   38 
   39 optimizeLineTail:: MonadSafe m => Line -> m InstructionList
   40 optimizeLineTail line = check (currentTL line) where
   41   check (t : tl) = optimizeLineForToken t $ line { currentTL = tl }
   42   check []       = pure []
   43 
   44 optimizeLineForToken :: MonadSafe m => Token -> Line -> m InstructionList
   45 optimizeLineForToken O = (sOutputI  : ) <.> optimizeLineTail
   46 optimizeLineForToken I = (sInputI   : ) <.> optimizeLineTail
   47 
   48 optimizeLineForToken S = (subI      : ) <.> optimizeLineTail
   49 optimizeLineForToken E = prependDivMod
   50 
   51 optimizeLineForToken H = (halibutI  : ) <.> optimizeLineTail
   52 optimizeLineForToken T = (bNeTI     : ) <.> optimizeLineTail
   53 
   54 optimizeLineForToken A = prependAddress
   55 optimizeLineForToken N = prependNumber
   56 
   57 optimizeLineForToken R = optimizeLineTail
   58 
   59 prependDivMod :: MonadSafe m => Line -> m InstructionList
   60 prependDivMod line = check $ numberFlag line where
   61   check False = prependDivModSimple line
   62   check True  = prependStaticMakr line <.> optimizeLineTail $ line {numberFlag = False}
   63 
   64 prependStaticMakr :: Line -> InstructionList -> InstructionList
   65 prependStaticMakr line il = divModI : markSI (show $ currentAddress line) : il
   66 
   67 prependDivModSimple :: MonadSafe m => Line -> m InstructionList
   68 prependDivModSimple = (divModI : ) <.> optimizeLineTail
   69 
   70 prependAddress :: MonadSafe m => Line -> m InstructionList
   71 prependAddress line = ((consI $ fromIntegral $ nextAddress line) : ) <$> optimizeLineTail line
   72 
   73 prependNumber :: MonadSafe m => Line -> m InstructionList
   74 prependNumber line = flip buildNumber line =<< parseNumberFromTLL (currentTL line , nextTLL line)
   75 
   76 buildNumber :: MonadSafe m => (Integer , (TokenList , [TokenList])) -> Line -> m InstructionList
   77 buildNumber (n , (tl , ttl) ) line = build (LL.length (nextTLL line) - LL.length ttl) where
   78   build 0      = (consI n :) <$> optimizeLineTail (line {currentTL = tl})
   79   build offset = pure [consI n , jumpSI $ show $ currentAddress line + fromIntegral offset]
   80 
   81 -- | Accessors
   82 
   83 nextAddress :: Line -> Natural
   84 nextAddress line = currentAddress line + 1
   85 
   86 -- | Constructors
   87 
   88 lineFromTuple2 :: (Natural, [TokenList]) -> Line
   89 lineFromTuple2 (a, []) = Line
   90   { currentAddress = a
   91   , currentTL = []
   92   , nextTLL = []
   93   , numberFlag = True
   94   }
   95 lineFromTuple2 (a, l : ls) = Line
   96   { currentAddress = a
   97   , currentTL = l
   98   , nextTLL = ls
   99   , numberFlag = True
  100   }
  101 
  102 data Line = Line
  103   { currentTL      :: TokenList
  104   , currentAddress :: Natural
  105   , numberFlag     :: Bool
  106   , nextTLL        :: [TokenList]
  107   }
  108 
  109 --consM :: Functor f => a -> f [a] -> f [a]
  110 --consM a l = (a : ) <$> l
  111 
  112 filterNull :: [[a]] -> [[a]]
  113 filterNull = filter notNull