diff --git a/csound-expression.cabal b/csound-expression.cabal
--- a/csound-expression.cabal
+++ b/csound-expression.cabal
@@ -1,5 +1,5 @@
 Name:          csound-expression
-Version:       1.0.1
+Version:       1.0.2
 Cabal-Version: >= 1.6
 License:       BSD3
 License-file:  LICENSE
@@ -88,7 +88,6 @@
         Csound.Exp.Numeric       
         
         Csound.Tfm.RateGraph
-        Csound.Tfm.TfmTree
         
         Csound.Render
         Csound.Render.Pretty
diff --git a/src/Csound/Exp.hs b/src/Csound/Exp.hs
--- a/src/Csound/Exp.hs
+++ b/src/Csound/Exp.hs
@@ -1,8 +1,8 @@
 module Csound.Exp(
-    E, RatedExp(..), RatedVar(..), onExp, Exp(..), Name,
+    E, RatedExp(..), RatedVar(..), onExp, Exp, toPrimOr, PrimOr(..), MainExp(..), Name,
     VarType(..), Var(..), Info(..), OpcType(..), Rate(..), 
     Signature(..), isProcedure, isInfix, isPrefix,    
-    Prim(..), Tab(..),
+    Prim(..), Tab(..), TabMap,
     Inline(..), InlineExp(..), PreInline(..),
     BoolExp, CondInfo, CondOp(..), isTrue, isFalse,    
     NumExp, NumOp(..)    
@@ -15,6 +15,7 @@
 
 import Data.Map(Map)
 import qualified Data.IntMap as IM
+import qualified Data.Map    as M
 import Data.Fix
 
 -- | The inner representation of csound expressions.
@@ -39,7 +40,18 @@
 data VarType = LocalVar | GlobalVar
     deriving (Show, Eq, Ord)
 
-data Exp a 
+type Exp a = MainExp (PrimOr a)
+
+toPrimOr :: E -> PrimOr E
+toPrimOr a = PrimOr $ case ratedExpExp $ unFix a of
+    ExpPrim (PString _) -> Right a
+    ExpPrim p -> Left p
+    _         -> Right a
+
+newtype PrimOr a = PrimOr { unPrimOr :: Either Prim a }
+    deriving (Show, Eq, Ord)
+
+data MainExp a 
     = ExpPrim Prim
     | Tfm Info [a]
     | ConvertRate Rate Rate a
@@ -97,7 +109,9 @@
     | PrimTab Tab 
     | PrimString String 
     deriving (Show, Eq, Ord)
-    
+   
+type TabMap = M.Map Tab Int
+ 
 -- | Csound f-tables. You can make a value of 'Tab' with the function 'gen'.
 data Tab = Tab 
     { tabSize    :: Int
@@ -160,15 +174,28 @@
 -- instances for cse
 
 instance Functor RatedExp where
-    fmap f (RatedExp r d a) = RatedExp r (fmap f d) (fmap f a)
+    fmap f (RatedExp r d a) = RatedExp r (fmap f d) (fmap (fmap f) a)
 
 instance Foldable RatedExp where
-    foldMap f (RatedExp _ d a) = foldMap f d <> foldMap f a
+    foldMap f (RatedExp _ d a) = foldMap f d <> foldMap (foldMap f) a
     
 instance Traversable RatedExp where
-    traverse f (RatedExp r d a) = RatedExp r <$> traverse f d <*> traverse f a
+    traverse f (RatedExp r d a) = RatedExp r <$> traverse f d <*> traverse (traverse f) a
 
-instance Functor Exp where
+instance Functor PrimOr where
+    fmap f (PrimOr a) = PrimOr (fmap f a)
+
+instance Foldable PrimOr where
+    foldMap f x = case unPrimOr x of
+        Left _  -> mempty
+        Right a -> f a
+
+instance Traversable PrimOr where
+    traverse f x = case unPrimOr x of
+        Left  p -> pure $ PrimOr $ Left p
+        Right a -> PrimOr . Right <$> f a
+
+instance Functor MainExp where
     fmap f x = case x of
         ExpPrim p -> ExpPrim p
         Tfm t xs -> Tfm t $ map f xs
@@ -181,7 +208,7 @@
         WriteVar v a -> WriteVar v (f a)        
 
 
-instance Foldable Exp where
+instance Foldable MainExp where
     foldMap f x = case x of
         ExpPrim p -> mempty
         Tfm t xs -> foldMap f xs
@@ -193,7 +220,7 @@
         ReadVar v -> mempty
         WriteVar v a -> f a
         
-instance Traversable Exp where
+instance Traversable MainExp where
     traverse f x = case x of
         ExpPrim p -> pure $ ExpPrim p
         Tfm t xs -> Tfm t <$> traverse f xs
@@ -204,7 +231,6 @@
         ExpNum  a -> ExpNum  <$> traverse f a
         ReadVar v -> pure $ ReadVar v
         WriteVar v a -> WriteVar v <$> f a
-
 
 instance Functor (Inline a) where
     fmap f a = a{ inlineEnv = fmap f $ inlineEnv a }
diff --git a/src/Csound/Exp/Cons.hs b/src/Csound/Exp/Cons.hs
--- a/src/Csound/Exp/Cons.hs
+++ b/src/Csound/Exp/Cons.hs
@@ -32,7 +32,7 @@
 withInits :: (Val a, CsdTuple inits) => a -> inits -> Sig
 withInits a b = wrap $ onExp phi $ unwrap a
     where phi x = case x of
-            Tfm t xs -> Tfm t (xs ++ fromCsdTuple b)
+            Tfm t xs -> Tfm t (xs ++ (fmap toPrimOr $ fromCsdTuple b))
             x        -> x
 
 ------------------------------------------------
diff --git a/src/Csound/Exp/Logic.hs b/src/Csound/Exp/Logic.hs
--- a/src/Csound/Exp/Logic.hs
+++ b/src/Csound/Exp/Logic.hs
@@ -39,29 +39,29 @@
 boolExp = PreInline
 
 cond' :: BoolSig -> Sig -> Sig -> Sig
-cond' p t e = wrap $ mkCond (condInfo $ Fix $ unwrap p) (unwrap t) (unwrap e)
-    where mkCond :: CondInfo E -> RatedExp E -> RatedExp E -> RatedExp E
+cond' p t e = wrap $ mkCond (condInfo $ toPrimOr $ Fix $ unwrap p) (unwrap t) (unwrap e)
+    where mkCond :: CondInfo (PrimOr E) -> RatedExp E -> RatedExp E -> RatedExp E
           mkCond p t e 
             | isTrue p = t
             | isFalse p = e
-            | otherwise = noRate $ If p (Fix t) (Fix e)            
+            | otherwise = noRate $ If p (toPrimOr $ Fix t) (toPrimOr $ Fix e)            
 
-condInfo :: E -> CondInfo E
+condInfo :: PrimOr E -> CondInfo (PrimOr E)
 condInfo exp = (\(a, b) -> Inline a (IM.fromList b)) $ evalState (condInfo' exp) 0
-    where condInfo' :: E -> State Int (InlineExp CondOp, [(Int, E)])
+    where condInfo' :: PrimOr E -> State Int (InlineExp CondOp, [(Int, PrimOr E)])
           condInfo' e = maybe (onLeaf e) (onExp e) $ parseNode e
           onLeaf e = state $ \n -> ((InlinePrim n, [(n, e)]), n+1)  
           onExp  e (op, args) = mkNode <$> mapM condInfo' args
               where mkNode as = (InlineExp op (map fst as), concat $ map snd as) 
 
-          parseNode :: E -> Maybe (CondOp, [E])
-          parseNode x = case ratedExpExp $ unFix x of
-              ExpBool (PreInline op args) -> Just (op, args)
+          parseNode :: PrimOr E -> Maybe (CondOp, [PrimOr E])
+          parseNode x = case unPrimOr $ fmap (ratedExpExp . unFix) x of
+              Right (ExpBool (PreInline op args)) -> Just (op, args)
               _ -> Nothing    
 
 
 boolOps :: (Val a) => CondOp -> [E] -> a
-boolOps op as = noRate $ ExpBool $ boolExp op as
+boolOps op as = noRate $ ExpBool $ boolExp op $ fmap toPrimOr as
 
 boolOp0 :: Val a => CondOp -> a
 boolOp0 op = boolOps op []
@@ -78,13 +78,14 @@
     where phi (ExpBool (PreInline op args)) = ExpBool $ case op of
             TrueOp            -> boolExp FalseOp        []
             FalseOp           -> boolExp TrueOp         []
-            And               -> boolExp Or             $ map notE args
-            Or                -> boolExp And            $ map notE args
+            And               -> boolExp Or             $ fmap (fmap notE) args
+            Or                -> boolExp And            $ fmap (fmap notE) args
             Equals            -> boolExp NotEquals      args
             NotEquals         -> boolExp Equals         args
             Less              -> boolExp GreaterEquals  args
             Greater           -> boolExp LessEquals     args
             LessEquals        -> boolExp Greater        args
             GreaterEquals     -> boolExp Less           args     
+
    
 
diff --git a/src/Csound/Exp/Numeric.hs b/src/Csound/Exp/Numeric.hs
--- a/src/Csound/Exp/Numeric.hs
+++ b/src/Csound/Exp/Numeric.hs
@@ -12,6 +12,13 @@
 -------------------------------------------------------
 -- instances for numerical expressions
 
+class NumOpt a where
+    maybeInt    :: a -> Maybe Int
+    maybeDouble :: a -> Maybe Double
+    fromInt     :: Int -> a
+    fromDouble  :: Double -> a
+    fromNum     :: NumExp a -> a
+
 instance NumOpt E where
     maybeInt x = case ratedExpExp $ unFix x of
         ExpPrim (PrimInt n) -> Just n
@@ -23,7 +30,7 @@
     
     fromInt = prim . PrimInt
     fromDouble = prim . PrimDouble
-    fromNum = noRate . ExpNum        
+    fromNum = noRate . ExpNum . fmap toPrimOr   
 
 --------------------------------------------
 -- numeric instances
@@ -196,13 +203,6 @@
 
 ------------------------------------------------------------
 
-class NumOpt a where
-    maybeInt    :: a -> Maybe Int
-    maybeDouble :: a -> Maybe Double
-    fromInt     :: Int -> a
-    fromDouble  :: Double -> a
-    fromNum     :: NumExp a -> a
-    
 isZero :: NumOpt a => a -> Bool
 isZero a = maybe False id $ liftA2 (||) ((== 0) <$> maybeInt a) ((==0) <$> maybeDouble a)
 
diff --git a/src/Csound/Exp/Wrapper.hs b/src/Csound/Exp/Wrapper.hs
--- a/src/Csound/Exp/Wrapper.hs
+++ b/src/Csound/Exp/Wrapper.hs
@@ -10,7 +10,8 @@
     str, double, int, ir,
     tfm, pref, prim, p,
     isMultiOutSignature,
-    noRate, setRate, getRates,
+    noRate, setRate, 
+    getRates, tabMap,
     readVar, writeVar, gOutVar,
     Channel
 ) where
@@ -19,9 +20,12 @@
 import Control.Monad(ap)
 import Control.Monad.Trans.State
 
+import Data.List(nub)
 import Data.String
 import Data.Fix
 import Control.Monad.Trans.State
+import qualified Data.Map as M
+import Data.Foldable(foldMap)
 
 import Csound.Exp
 
@@ -30,7 +34,6 @@
 -- | Output of the instrument.
 type Out = SE [Sig]
 
-
 -- | Audio or control rate signals. 
 newtype Sig = Sig { unSig :: E }
 
@@ -99,7 +102,7 @@
 inf name signature = Info name signature Infix Nothing
   
 tfm :: Val a => Info -> [RatedExp E] -> a
-tfm info args = wrap $ noRate $ Tfm info $ map Fix args
+tfm info args = wrap $ noRate $ Tfm info $ map (toPrimOr . Fix) args
 
 gvar, var :: Val a => Rate -> Name -> a
 
@@ -125,7 +128,7 @@
 str = prim . PrimString
 
 writeVar :: (Val a) => Var -> a -> SE ()
-writeVar v x = se_ $ noRate $ WriteVar v $ Fix $ unwrap x 
+writeVar v x = se_ $ noRate $ WriteVar v $ toPrimOr $ Fix $ unwrap x 
 
 readVar :: (Val a) => Var -> a
 readVar v = noRate $ ReadVar v
@@ -146,12 +149,32 @@
 se_ = fmap (const ()) . (se :: E -> SE E)
 
 ------------------------------------------------
--- basic destructors
+-- basic extractors
 
 getPrimUnsafe :: Val a => a -> Prim
 getPrimUnsafe a = case ratedExpExp $ unwrap a of
     ExpPrim p -> p
 
+tabMap :: [E] -> TabMap
+tabMap es = M.fromList $ zip (nub $ getFtables =<< es) [1 ..]
+    where 
+        getFtables :: E -> [Tab]
+        getFtables = cata $ \re -> case fmap fromPrimOr $ ratedExpExp re of    
+            ExpPrim p -> fromPrim p
+            Tfm _ as -> concat as
+            ConvertRate _ _ a -> a
+            ExpNum a -> foldMap id a
+            Select _ _ a -> a
+            If info a b -> foldMap id info ++ a ++ b
+            ReadVar _ -> []
+            WriteVar _ a -> a
+            where fromPrim x = case x of
+                    PrimTab t -> [t]
+                    _ -> []
+                  fromPrimOr x = case unPrimOr x of
+                    Left  p -> fromPrim p
+                    Right a -> a
+
 --------------------------------------------
 -- signals from primitive types
 
@@ -436,11 +459,11 @@
           e' = Fix $ onExp (setMultiRate rates) $ unFix e
           
           setMultiRate rates (Tfm info xs) = Tfm (info{ infoSignature = MultiRate rates ins }) xs 
-            where MultiRate _ ins = infoSignature info
+              where MultiRate _ ins = infoSignature info
             
-          select n r e = withRate r $ Select r n e
+          select n r e = withRate r $ Select r n (PrimOr $ Right e)
 
-getRates :: Exp a -> [Rate]
+getRates :: MainExp a -> [Rate]
 getRates (Tfm info _) = case infoSignature info of
     MultiRate outs _ -> outs
     
diff --git a/src/Csound/Opcode/Data.hs b/src/Csound/Opcode/Data.hs
--- a/src/Csound/Opcode/Data.hs
+++ b/src/Csound/Opcode/Data.hs
@@ -425,7 +425,7 @@
 instance Nums D
 
 conv :: Nums a => NumOp -> a -> a
-conv op a = noRate $ ExpNum $ PreInline op [toE a]
+conv op a = noRate $ ExpNum $ PreInline op [toPrimOr $ toE a]
 
 
 -- | Returns the amplitude equivalent of the decibel value x. Thus:
diff --git a/src/Csound/Render.hs b/src/Csound/Render.hs
--- a/src/Csound/Render.hs
+++ b/src/Csound/Render.hs
@@ -12,11 +12,9 @@
 
 import Csound.Exp
 import Csound.Exp.Wrapper hiding (double, int)
-import Csound.Tfm.TfmTree(tabMap)
 import Csound.Render.Sco
 import Csound.Render.Instr
 import Csound.Render.Options
-import Csound.Tfm.TfmTree(TabMap)
 import Csound.Exp.Numeric
 
 import Csound.Render.Pretty
diff --git a/src/Csound/Render/Instr.hs b/src/Csound/Render/Instr.hs
--- a/src/Csound/Render/Instr.hs
+++ b/src/Csound/Render/Instr.hs
@@ -17,7 +17,6 @@
 import Csound.Exp.Wrapper hiding (double, int)
 
 import Csound.Tfm.RateGraph
-import Csound.Tfm.TfmTree
 import Csound.Render.Pretty
 
 type InstrId = Int
@@ -29,7 +28,7 @@
 renderInstrBody :: KrateSet -> TabMap -> E -> [Doc]
 renderInstrBody krateSet ft sig = map (stmt . clearEmptyResults) $ collectRates krateSet st g
     where stmt :: ([RatedVar], Exp RatedVar) -> Doc
-          stmt (res, exp) = renderExp (ppOuts res) exp
+          stmt (res, exp) = renderExp ft (ppOuts res) exp
           
           st = getRenderState g
           g  = toDag ft sig
@@ -53,7 +52,7 @@
           selectInfo = filter (isSelect . ratedExpExp . snd) a    
             
           extract (n, x) = case ratedExpExp x of
-                Select rate order parent -> (parent, [MultiOutPort n order])
+                Select rate order (PrimOr (Right parent)) -> (parent, [MultiOutPort n order])
 
 filterMultiOutHelpers :: [(RatedVar, Exp RatedVar)] -> [(RatedVar, Exp RatedVar)]
 filterMultiOutHelpers = filter (not . isSelect . snd) 
@@ -64,7 +63,7 @@
 
 
 toDag :: TabMap -> E -> Dag RatedExp 
-toDag ft exp = fromDag $ cse $ substTabs ft exp
+toDag ft exp = fromDag $ cse exp
 
 
 clearEmptyResults :: ([RatedVar], Exp RatedVar) -> ([RatedVar], Exp RatedVar)
@@ -79,23 +78,21 @@
 tfmMultiRates :: RenderState -> [(RatedVar, Exp RatedVar)] -> State Int [([RatedVar], Exp RatedVar)]
 tfmMultiRates st as = mapM substRate as
     where substRate (n, exp) 
-            | isMultiOutExp exp = fmap (,exp) $ getMultiOutVars (multiOutsLinks st IM.! ratedVarId n) exp
+            | isMultiOutExp exp = fmap (,exp) $ getMultiOutVars (multiOutsLinks st IM.! ratedVarId n) (getRates exp)
             | otherwise = return ([n], exp)
 
           isMultiOutExp x = case x of
               Tfm i _ -> isMultiOutSignature (infoSignature i)
               _ -> False
   
-getMultiOutVars :: [MultiOutPort] -> Exp RatedVar -> State Int [RatedVar]
-getMultiOutVars ports exp = fmap (zipWith RatedVar (getRates exp)) (getPorts ports)
+getMultiOutVars :: [MultiOutPort] -> [Rate] -> State Int [RatedVar]
+getMultiOutVars ports rates = fmap (zipWith RatedVar rates) (getPorts ports)
     where getPorts ps = state $ \lastFreshId -> 
             let ps' = sortBy (comparing orderMultiOutPort) ps
                 (ids, lastPortOrder) = runState (mapM (fillMissingPorts lastFreshId) ps') 0
-                ids' = ids ++ [map (+ lastFreshId) [lastPortOrder + 1 .. portsSize - 1]]                
-            in  (concat ids', lastFreshId + portsSize - inUsePortsSize)             
-                  
-                  
-          rates = getRates exp
+                ids' = ids ++ [map (+ lastFreshId) [0 .. portsSize - 1 - lastPortOrder]]                
+            in  (concat ids', lastFreshId + portsSize - inUsePortsSize)                             
+
           portsSize = length rates    
           inUsePortsSize = length ports  
                     
@@ -113,10 +110,10 @@
 getRate :: RatedExp a -> Rate
 getRate = fromJust . ratedExpRate
 
-renderExp :: Doc -> Exp RatedVar -> Doc
-renderExp res exp = case fmap ppRatedVar exp of
+renderExp :: TabMap -> Doc -> Exp RatedVar -> Doc
+renderExp m res exp = case fmap (ppPrimOrVar m) exp of
     ExpPrim (PString n) -> ppStrget res n
-    ExpPrim p -> res $= ppPrim p
+    ExpPrim p -> res $= ppPrim m p
     Tfm info [a, b] | isInfix  info -> res $= binary (infoName info) a b
     Tfm info xs -> ppOpc res (infoName info) xs
     ConvertRate to from x -> ppConvertRate res to from x
diff --git a/src/Csound/Render/Pretty.hs b/src/Csound/Render/Pretty.hs
--- a/src/Csound/Render/Pretty.hs
+++ b/src/Csound/Render/Pretty.hs
@@ -4,7 +4,7 @@
     binaries, unaries, funcs,
     binary, unary, func,
     ppMapTable,
-    ($=), ppRatedVar, ppOuts, ppOpc, ppProc, ppVar,
+    ($=), ppPrimOrVar, ppRatedVar, ppOuts, ppOpc, ppProc, ppVar,
     ppPrim, ppTab, ppStrget, ppStrset, ppTabDef, ppConvertRate, ppIf,
     ppCsdFile, ppInstr, ppInstr0, ppScore, ppNote, ppTotalDur, ppOrc, ppSco, 
     ppInline, ppCondOp, ppNumOp
@@ -44,6 +44,8 @@
     _  -> phi x
     where phi = text . map toLower . show 
 
+ppPrimOrVar :: TabMap -> PrimOr RatedVar -> Doc
+ppPrimOrVar m x = either (ppPrim m) ppRatedVar $ unPrimOr x
 
 ppRatedVar :: RatedVar -> Doc
 ppRatedVar (RatedVar r x) = ppRate r <> int x
@@ -70,13 +72,13 @@
     LocalVar -> empty
     GlobalVar -> char 'g'
 
-ppPrim :: Prim -> Doc
-ppPrim x = case x of
+ppPrim :: TabMap -> Prim -> Doc
+ppPrim m x = case x of
     P n -> char 'p' <> int n
     PrimInt n -> int n
     PrimDouble d -> double d
-    PrimString s -> text s
-    PrimTab f -> ppTab f
+    PrimString s -> dquotes $ text s
+    PrimTab f -> int $ m M.! f
     
 ppTab :: Tab -> Doc
 ppTab (Tab size n xs) = text "gen" <> int n <+> int size <+> (hsep $ map double xs)
diff --git a/src/Csound/Render/Sco.hs b/src/Csound/Render/Sco.hs
--- a/src/Csound/Render/Sco.hs
+++ b/src/Csound/Render/Sco.hs
@@ -15,7 +15,6 @@
 
 import Csound.Exp
 import Csound.Exp.Wrapper hiding (int, double)
-import Csound.Tfm.TfmTree(TabMap)
 import Csound.Exp.Cons(opcs)
 import Csound.Exp.Numeric
 
@@ -89,7 +88,7 @@
 expReader instr instrId = swap $ runSE $ do             
     as <- instr
     let vars = instrPorts instrId as    
-    zipWithM writeVar vars as
+    zipWithM (\v a -> writeVar v $ readVar v + a) vars as
     return vars
             
 
diff --git a/src/Csound/Tfm/RateGraph.hs b/src/Csound/Tfm/RateGraph.hs
--- a/src/Csound/Tfm/RateGraph.hs
+++ b/src/Csound/Tfm/RateGraph.hs
@@ -7,7 +7,8 @@
 import qualified Data.IntMap as IM
 import qualified Data.Set as S
 import Data.Ord(comparing)
-import Data.Maybe(fromJust)
+import Data.Maybe(fromJust, catMaybes)
+import Data.Either
 
 import Data.Default
 
@@ -22,6 +23,7 @@
 
 import Debug.Trace
 
+
 echo :: Show a => String -> a -> a
 echo msg a = trace (msg ++ ": " ++ show a) a
 
@@ -120,7 +122,7 @@
    
 
 notifyChildren :: AgentId -> Rate -> Exp Int -> MsgBox s -> ST s ()
-notifyChildren pid curRate exp box = mapM_ (\(to, query) -> sendQuery to query box) $ case exp of
+notifyChildren pid curRate exp box = mapM_ (\(to, query) -> sendQuery to query box) $ catMaybes $ fmap wrapFromEither $ case exp of
     Tfm info xs -> notifyTfm curRate (infoSignature info) xs
     WriteVar v a -> [(a, mkQuery 0 $ varRate v)]
     If info a b -> (a, mkQuery (-2) curRate) : (b, mkQuery (-1) curRate) : encodeIfEnv (max Kr curRate) (inlineEnv info)
@@ -136,6 +138,9 @@
 
           encodeIfEnv rate info = map (\(port, arg) -> (arg, mkQuery port rate)) $ IM.toList info 
 
+          wrapFromEither (to, query) = either (const Nothing) (Just . \x -> (x, query)) (unPrimOr to)
+
+
 notifyParents :: MsgBox s -> M.Map Rate RatedVar -> [Query] -> ST s ()
 notifyParents box convTab qs = mapM_ (notifyParent box convTab) qs
 
@@ -166,7 +171,7 @@
 getConversions pid curRate convTable = uncurry phi =<< M.toList convTable
     where phi rate var@(RatedVar r n)
             | n == pid  = []
-            | otherwise = [(var, ConvertRate r curRate $ RatedVar curRate pid)] 
+            | otherwise = [(var, ConvertRate r curRate $ PrimOr $ Right $ RatedVar curRate pid)] 
 
 
 processLine :: MsgBox s -> (Int, RatedExp Int) -> ST s [(RatedVar, Exp RatedVar)]
@@ -179,16 +184,28 @@
 rateExp curRate rs exp = case exp of
     ExpPrim (P n) | curRate == Sr -> ExpPrim (PString n)
     ExpPrim p -> ExpPrim p
-    Tfm i _ -> Tfm i vs   
-    Select rate pid a -> Select rate pid (RatedVar Xr a)    
-    If condInfo _ _ -> case vs of
+    Tfm i vsOld -> Tfm i $ mergeWithPrimOr vsOld vs
+    Select rate pid a -> Select rate pid (fmap (RatedVar Xr) a)    
+    If condInfo a' b' -> case mergeWithPrimOr (encodeIfEnv condInfo a' b') vs of
         a:b:rest -> If (decodeIfEnv condInfo rest) a b
-    ExpNum (PreInline op _) -> ExpNum (PreInline op vs)
+    ExpNum (PreInline op vsOld) -> ExpNum (PreInline op $ mergeWithPrimOr vsOld vs)
     ReadVar v -> ReadVar v
-    WriteVar v _ -> WriteVar v (head vs)
+    WriteVar v vsOld -> WriteVar v (substPrimOr vsOld $ head vs)
     where vs = map responseRatedVar $ sortBy (comparing $ addrArg . responseAddr) rs
-          decodeIfEnv info xs = info{ inlineEnv = IM.fromList $ zip [0..] xs }
+          decodeIfEnv info xs = info{ inlineEnv = IM.fromList $ zip [0..] xs }      
+          encodeIfEnv info a b = a:b:(IM.elems $ inlineEnv info)  
 
+
+substPrimOr :: PrimOr a -> b -> PrimOr b
+substPrimOr p val = PrimOr $ case unPrimOr p of
+    Left  a -> Left a
+    Right _ -> Right val
+
+mergeWithPrimOr :: [PrimOr a] -> [b] -> [PrimOr b]
+mergeWithPrimOr xs ys = case (xs, ys) of
+    ([], _) -> []
+    (PrimOr (Left a):as, bs) -> PrimOr (Left a) : mergeWithPrimOr as bs
+    (PrimOr (Right _):as, b:bs) -> PrimOr (Right b) : mergeWithPrimOr as bs
 
 findRate :: [Rate] -> Rate
 findRate [x] = x
diff --git a/src/Csound/Tfm/TfmTree.hs b/src/Csound/Tfm/TfmTree.hs
deleted file mode 100644
--- a/src/Csound/Tfm/TfmTree.hs
+++ /dev/null
@@ -1,35 +0,0 @@
-module Csound.Tfm.TfmTree(
-    TabMap, tabMap, substTabs
-) where
-
-import Data.List(nub)
-import Data.Fix
-import qualified Data.Map as M
-import Data.Foldable(foldMap)
-
-import Csound.Exp
-
-type TabMap = M.Map Tab Int
-
--- substitute ftables for ids 
-
-substTabs :: TabMap -> E -> E
-substTabs m = cata $ \(RatedExp r d x) -> Fix $ RatedExp r d $ case x of
-    ExpPrim (PrimTab t) -> ExpPrim (PrimInt $ m M.! t)
-    _ -> x
-
-
-tabMap :: [E] -> TabMap
-tabMap es = M.fromList $ zip (nub $ getFtables =<< es) [1 ..]
-
-getFtables :: E -> [Tab]
-getFtables = cata $ \(RatedExp _ _ x) -> case x of
-    ExpPrim (PrimTab t) -> [t]
-    ExpPrim _ -> []
-    Tfm _ as -> concat as
-    ConvertRate _ _ a -> a
-    ExpNum a -> foldMap id a
-    Select _ _ a -> a
-    If info a b -> foldMap id info ++ a ++ b
-    ReadVar _ -> []
-    WriteVar _ a -> a
