module CsoundExpr.Translator.InstrOrder
(instrOrderInfo,
setInstrIds,
instrIds)
where
import Data.List
import Data.Function
import qualified Data.Map as Map
import Control.Monad.State
import CsoundExpr.Translator.Cs.CsTree
import CsoundExpr.Translator.Cs.Utils
import CsoundExpr.Translator.Types
import Debug.Trace
debug x = trace (show x) x
setInstrIds :: [Id] -> [(Instr, [Note])] ->
([(Id, Instr)], [(Id, [Note])])
setInstrIds ids qs = unzip [((id, q1), (id, q2)) | (id, (q1, q2)) <- xs]
where xs = sortBy (compare `on` fst) $ zip ids qs
instrOrderInfo :: InstrOrder -> [Instr] -> InstrOrderInfo
instrOrderInfo xs qs = Map.fromList $ zip (map fst ps') ids
where ids = resolveCollisions $ map snd ps'
ps' = sortBy (compare `on` snd) $
fst $ runState (mapM (f xs) qs) (startId + length xs)
f :: InstrOrder -> Instr -> State Id (Instr, Id)
f xs q = state $ \s -> case findIndex ((liftPredicateToList equalStructureByParams) q) xs of
(Just i) -> ((q, startId + i), s)
Nothing -> ((q, s), s + 1)
resolveCollisions :: [Int] -> [Int]
resolveCollisions xs = fst $ runState (mapM f xs) (head xs 1, 0)
where f x = state $ \(prev, shift) ->
if x + shift == prev
then (x + shift + 1, (x + shift + 1, shift + 1))
else (x + shift, (x + shift , shift))
startId :: Id
startId = 33
instrIds :: InstrOrderInfo -> [Instr] -> [Id]
instrIds f = map (f Map.!)