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