diff --git a/CONTRIBUTORS b/CONTRIBUTORS
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -1,3 +1,5 @@
 The following people have contributed to Syntactic:
 
   * Anders Persson
+  * Daniel Schoepe
+  * Dmytro Lypai
diff --git a/examples/NanoFeldspar/Core.hs b/examples/NanoFeldspar/Core.hs
--- a/examples/NanoFeldspar/Core.hs
+++ b/examples/NanoFeldspar/Core.hs
@@ -2,6 +2,7 @@
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE UndecidableInstances #-}
@@ -69,10 +70,8 @@
         , semanticEval = \len ixf -> map ixf [0 .. len-1]
         }
 
-instance Equality Parallel where equal = equalDefault; exprHash = exprHashDefault
-instance Render   Parallel where renderArgs = renderArgsDefault
-instance Eval     Parallel where evaluate   = evaluateDefault
-instance ToTree   Parallel
+semanticInstances ''Parallel
+
 instance EvalBind Parallel where evalBindSym = evalBindSymDefault
 
 instance AlphaEq dom dom dom env => AlphaEq Parallel Parallel dom env
@@ -102,10 +101,8 @@
         , semanticEval = \len init body -> foldl (flip body) init [0 .. len-1]
         }
 
-instance Equality ForLoop where equal = equalDefault; exprHash = exprHashDefault
-instance Render   ForLoop where renderArgs = renderArgsDefault
-instance Eval     ForLoop where evaluate   = evaluateDefault
-instance ToTree   ForLoop
+semanticInstances ''ForLoop
+
 instance EvalBind ForLoop where evalBindSym = evalBindSymDefault
 
 instance AlphaEq dom dom dom env => AlphaEq ForLoop ForLoop dom env
@@ -152,8 +149,13 @@
 canShare (prj -> Just (Literal _)) = Nothing
 canShare _  = Just Dict
 
+canShareIn :: ASTF (FODomain FeldSyms Typeable Top) a -> Bool
+canShareIn (lam :$ _)
+    | Just _ <- prjP (P::P (CLambda Top)) lam = False
+canShareIn _ = True
+
 canShareDict :: MkInjDict (FODomain FeldSyms Typeable Top)
-canShareDict = mkInjDictFO canShare
+canShareDict = mkInjDictFO canShare canShareIn
 
 
 
diff --git a/examples/NanoFeldspar/Extra.hs b/examples/NanoFeldspar/Extra.hs
--- a/examples/NanoFeldspar/Extra.hs
+++ b/examples/NanoFeldspar/Extra.hs
@@ -8,6 +8,7 @@
 
 
 
+import Control.Monad.State
 import Data.Typeable
 
 import Language.Syntactic as Syntactic
@@ -16,6 +17,7 @@
 import Language.Syntactic.Constructs.Binding.Optimize
 import Language.Syntactic.Constructs.Construct
 import Language.Syntactic.Constructs.Literal
+import Language.Syntactic.Sharing.SimpleCodeMotion
 import Language.Syntactic.Sharing.Graph
 import Language.Syntactic.Sharing.ReifyHO
 
@@ -57,7 +59,7 @@
 
 
 --------------------------------------------------------------------------------
--- * Partial evaluation
+-- * Simplification/constant folding
 --------------------------------------------------------------------------------
 
 instance Optimize ForLoop
@@ -77,6 +79,15 @@
       _ -> expr
     ) expr
 
-drawPart :: (Syntactic a, Domain a ~ FeldDomainAll) => a -> IO ()
-drawPart = Syntactic.drawAST . optimize constFold . reify
+reifySimp :: (Syntactic a, Domain a ~ FeldDomainAll) =>
+    a -> ASTF ((FODomain (Let :+: (FeldDomain :|| Eq :| Show))) Typeable Top) (Internal a)
+reifySimp = flip evalState 0 .
+    (   codeMotion prjDictFO canShareDict
+    .   optimize constFold
+    <=< reifyM
+    .   desugar
+    )
+
+drawSimp :: (Syntactic a, Domain a ~ FeldDomainAll) => a -> IO ()
+drawSimp = Syntactic.drawAST . reifySimp
 
diff --git a/examples/NanoFeldspar/Test.hs b/examples/NanoFeldspar/Test.hs
--- a/examples/NanoFeldspar/Test.hs
+++ b/examples/NanoFeldspar/Test.hs
@@ -11,36 +11,49 @@
 
 
 --------------------------------------------------------------------------------
--- Basic operations
+-- Basic examples
 --------------------------------------------------------------------------------
 
--- Parallel arrays
-prog1 :: Data Int -> Data Int -> Data [Int]
-prog1 a b = parallel a (\i -> min (i+3) b)
+-- Scalar product
+scProd :: Vector (Data Float) -> Vector (Data Float) -> Data Float
+scProd a b = sum (zipWith (*) a b)
 
--- Evaluation
-test1_1 = eval prog1 10 20
+forEach = flip map
 
--- Print the expression
-test1_2 = printExpr prog1
+-- Matrix multiplication
+matMul :: Matrix Float -> Matrix Float -> Matrix Float
+matMul a b = forEach a $ \a' ->
+               forEach (transpose b) $ \b' ->
+                 scProd a' b'
 
--- Render the syntax tree
-test1_3 = drawAST prog1
+-- Note that
+--
+--   * `transpose` is fused with `scProd`
+--   * some invariant expressions have been hoisted out of `parallel` and `forLoop` (see the
+--     `Let` nodes)
+test_matMul = drawAST matMul
 
+-- Parallel array
+prog1 :: Data Int -> Data Int -> Data [Int]
+prog1 a b = parallel a (\i -> min (i+3) b)
+
 -- Common sub-expressions
 prog2 :: Data Int -> Data Int
 prog2 a = max (min a a) (min a a)
 
--- Basic vector operations
 prog3 :: Data Index -> Data Index -> Data Index
 prog3 a b = sum $ reverse (l ... u)
   where
     l = min a b
     u = max a b
 
+-- Invariant code hoisting
+prog4 :: Data Int -> Data [Int]
+prog4 a = parallel a (\i -> (a+a)*i)
+
 -- Explicit sharing
-prog4 :: Data Index -> Data Index
-prog4 a = share (a*2,a*3) $ \(b,c) -> (b-c)*(c-b)
+prog5 :: Data Index -> Data Index
+prog5 a = share (a*2,a*3) $ \(b,c) -> (b-c)*(c-b)
 
 
 
@@ -48,17 +61,17 @@
 -- Common sub-expression elimination and observable sharing
 --------------------------------------------------------------------------------
 
-prog5 = index as 1 + sum as + sum as
+prog6 = index as 1 + sum as + sum as
   where
     as = map (*2) $ force (1...20)
 
-test5_1 = drawAST prog5
+test6_1 = drawAST prog6
   -- Draws a tree with no duplication
 
-test5_2 = drawCSE prog5
+test6_2 = drawCSE prog6
   -- Draws a graph with no duplication
 
-test5_3 = drawObs prog5
+test6_3 = drawObs prog6
   -- Draws a graph with some duplication. The 'forLoop' introduced by 'sum' is
   -- not shared, because 'sum as' is repeated twice in source code. But the
   -- 'parallel' introduced by 'force' is shared, because 'force' only appears
@@ -70,16 +83,16 @@
 -- Optimizations
 --------------------------------------------------------------------------------
 
-prog6 :: Data Int -> Data Int
-prog6 a = (a==10) ? (max 5 (6+7), max 5 (6+7))
+prog7 :: Data Int -> Data Int
+prog7 a = (a==10) ? (max 5 (6+7), max 5 (6+7))
 
-test6 = drawPart prog6
+test7 = drawSimp prog7
   -- Reduced to the literal 13
 
-prog7 a = c ? (parallel 10 (+a), parallel 10 (+a))
+prog8 a = c ? (parallel 10 (+a), parallel 10 (+a))
   where
     c = (a*a*a*a) == 23
 
-test7 = drawPart prog7
+test8 = drawSimp prog8
   -- The condition gets pruned away
 
diff --git a/examples/NanoFeldspar/Vector.hs b/examples/NanoFeldspar/Vector.hs
--- a/examples/NanoFeldspar/Vector.hs
+++ b/examples/NanoFeldspar/Vector.hs
@@ -49,6 +49,11 @@
 index :: Vector a -> Data Index -> a
 index (Indexed _ ixf) = ixf
 
+(!) :: Vector a -> Data Index -> a
+Indexed _ ixf ! i = ixf i
+
+infixl 9 !
+
 freezeVector :: Type a => Vector (Data a) -> Data [a]
 freezeVector vec = parallel (length vec) (index vec)
 
@@ -83,6 +88,12 @@
 fold :: Syntax b => (a -> b -> b) -> b -> Vector a -> b
 fold f b (Indexed len ixf) = forLoop len b (\i st -> f (ixf i) st)
 
-sum :: (Type a, Num a) => Vector (Data a) -> Data a
+sum :: (Num a, Syntax a) => Vector a -> a
 sum = fold (+) 0
+
+type Matrix a = Vector (Vector (Data a))
+
+-- | Transpose of a matrix. Assumes that the number of rows is > 0.
+transpose :: Type a => Matrix a -> Matrix a
+transpose a = indexed (length (a!0)) $ \k -> indexed (length a) $ \l -> a ! l ! k
 
diff --git a/src/Language/Syntactic/Constructs/Binding/HigherOrder.hs b/src/Language/Syntactic/Constructs/Binding/HigherOrder.hs
--- a/src/Language/Syntactic/Constructs/Binding/HigherOrder.hs
+++ b/src/Language/Syntactic/Constructs/Binding/HigherOrder.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE TemplateHaskell #-}
 {-# LANGUAGE UndecidableInstances #-}
 
 -- | This module provides binding constructs using higher-order syntax and a
diff --git a/src/Language/Syntactic/Constructs/Condition.hs b/src/Language/Syntactic/Constructs/Condition.hs
--- a/src/Language/Syntactic/Constructs/Condition.hs
+++ b/src/Language/Syntactic/Constructs/Condition.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE TemplateHaskell #-}
+
 -- | Conditional expressions
 
 module Language.Syntactic.Constructs.Condition where
@@ -21,8 +23,5 @@
   where
     semantics Condition = Sem "condition" (\c t e -> if c then t else e)
 
-instance Equality Condition where equal = equalDefault; exprHash = exprHashDefault
-instance Render   Condition where renderArgs = renderArgsDefault
-instance Eval     Condition where evaluate   = evaluateDefault
-instance ToTree   Condition
+semanticInstances ''Condition
 
diff --git a/src/Language/Syntactic/Constructs/Construct.hs b/src/Language/Syntactic/Constructs/Construct.hs
--- a/src/Language/Syntactic/Constructs/Construct.hs
+++ b/src/Language/Syntactic/Constructs/Construct.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE TemplateHaskell #-}
+
 -- | Provides a simple way to make syntactic constructs for prototyping. Note
 -- that 'Construct' is quite unsafe as it only uses 'String' to distinguish
 -- between different constructs. Also, 'Construct' has a very free type that
@@ -24,8 +26,5 @@
   where
     semantics (Construct name den) = Sem name den
 
-instance Equality Construct where equal = equalDefault; exprHash = exprHashDefault
-instance Render   Construct where renderArgs = renderArgsDefault
-instance Eval     Construct where evaluate   = evaluateDefault
-instance ToTree   Construct
+semanticInstances ''Construct
 
diff --git a/src/Language/Syntactic/Constructs/Identity.hs b/src/Language/Syntactic/Constructs/Identity.hs
--- a/src/Language/Syntactic/Constructs/Identity.hs
+++ b/src/Language/Syntactic/Constructs/Identity.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE TemplateHaskell #-}
+
 -- | Identity function
 
 module Language.Syntactic.Constructs.Identity where
@@ -22,8 +24,5 @@
   where
     semantics Id = Sem "id" id
 
-instance Equality Identity where equal = equalDefault; exprHash = exprHashDefault
-instance Render   Identity where renderArgs = renderArgsDefault
-instance Eval     Identity where evaluate   = evaluateDefault
-instance ToTree   Identity
+semanticInstances ''Identity
 
diff --git a/src/Language/Syntactic/Constructs/Tuple.hs b/src/Language/Syntactic/Constructs/Tuple.hs
--- a/src/Language/Syntactic/Constructs/Tuple.hs
+++ b/src/Language/Syntactic/Constructs/Tuple.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE TemplateHaskell #-}
+
 -- | Construction and elimination of tuples in the object language
 
 module Language.Syntactic.Constructs.Tuple where
@@ -38,10 +40,7 @@
     semantics Tup6 = Sem "tup6" (,,,,,)
     semantics Tup7 = Sem "tup7" (,,,,,,)
 
-instance Equality Tuple where equal = equalDefault; exprHash = exprHashDefault
-instance Render   Tuple where renderArgs = renderArgsDefault
-instance Eval     Tuple where evaluate   = evaluateDefault
-instance ToTree   Tuple
+semanticInstances ''Tuple
 
 
 
@@ -120,10 +119,7 @@
     semantics Sel6 = Sem "sel6" sel6
     semantics Sel7 = Sem "sel7" sel7
 
-instance Equality Select where equal = equalDefault; exprHash = exprHashDefault
-instance Render   Select where renderArgs = renderArgsDefault
-instance Eval     Select where evaluate   = evaluateDefault
-instance ToTree   Select
+semanticInstances ''Select
 
 -- | Return the selected position, e.g.
 --
diff --git a/src/Language/Syntactic/Interpretation/Semantics.hs b/src/Language/Syntactic/Interpretation/Semantics.hs
--- a/src/Language/Syntactic/Interpretation/Semantics.hs
+++ b/src/Language/Syntactic/Interpretation/Semantics.hs
@@ -1,9 +1,14 @@
+{-# LANGUAGE TemplateHaskell #-}
+
 -- | Default implementations of some interpretation functions
 
 module Language.Syntactic.Interpretation.Semantics where
 
 
 
+import Language.Haskell.TH
+import Language.Haskell.TH.Quote
+
 import Data.Hash
 
 import Language.Syntactic.Syntax
@@ -74,3 +79,13 @@
 evaluateDefault :: Semantic expr => expr a -> Denotation a
 evaluateDefault = evaluate . semantics
 
+semanticInstances :: Name -> DecsQ
+semanticInstances n =
+    [d|
+        instance Equality $(typ) where equal = equalDefault ; exprHash = exprHashDefault
+        instance Render $(typ) where renderArgs = renderArgsDefault
+        instance ToTree $(typ)
+        instance Eval $(typ) where evaluate = evaluateDefault
+    |]
+  where
+    typ = conT n
diff --git a/src/Language/Syntactic/Sharing/SimpleCodeMotion.hs b/src/Language/Syntactic/Sharing/SimpleCodeMotion.hs
--- a/src/Language/Syntactic/Sharing/SimpleCodeMotion.hs
+++ b/src/Language/Syntactic/Sharing/SimpleCodeMotion.hs
@@ -211,11 +211,13 @@
 -- witness that the type of the expression satisfies the predicate @pVar@.
 mkInjDictFO :: forall dom pVar . (Let :<: dom)
     => (forall a . ASTF (FODomain dom Typeable pVar) a -> Maybe (Dict (pVar a)))
+    -> (forall b . ASTF (FODomain dom Typeable pVar) b -> Bool)
     -> MkInjDict (FODomain dom Typeable pVar)
-mkInjDictFO canShare a b
+mkInjDictFO canShare canShareIn a b
     | Dict <- exprDict a
     , Dict <- exprDict b
     , Just Dict <- canShare a
+    , canShareIn b
     = Just $ InjDict
         { injVariable = \v -> injC (symType pVar $ C' (Variable v))
         , injLambda   = \v -> injC (symType pLam $ SubConstr2 (Lambda v))
@@ -224,5 +226,5 @@
   where
     pVar = P::P (Variable :|| pVar)
     pLam = P::P (CLambda pVar)
-mkInjDictFO _ _ _ = Nothing
+mkInjDictFO _ _ _ _ = Nothing
 
diff --git a/syntactic.cabal b/syntactic.cabal
--- a/syntactic.cabal
+++ b/syntactic.cabal
@@ -1,5 +1,5 @@
 Name:           syntactic
-Version:        1.6.1
+Version:        1.7.1
 Synopsis:       Generic abstract syntax, and utilities for embedded languages
 Description:    This library provides:
                 .
@@ -99,12 +99,13 @@
 
   build-depends:
     array,
-    base >= 4 && < 4.7,
+    base >= 4 && < 4.8,
     containers,
     constraints,
     data-hash,
     ghc-prim,
     mtl >= 2 && < 3,
+    template-haskell,
     transformers >= 0.2,
     tuple >= 0.2
 
@@ -160,7 +161,8 @@
 
   build-depends:
     syntactic,
-    base >= 4 && < 4.7,
+    base,
+    mtl >= 2 && < 3,
     QuickCheck >= 2.4 && < 3,
     test-framework >= 0.6,
     test-framework-th >= 0.2,
@@ -193,8 +195,9 @@
 
   build-depends:
     syntactic,
-    base >= 4 && < 4.7,
+    base,
     bytestring,
+    mtl >= 2 && < 3,
     test-framework >= 0.6,
     test-framework-golden >= 1.1
 
diff --git a/tests/NanoFeldsparEval.hs b/tests/NanoFeldsparEval.hs
--- a/tests/NanoFeldsparEval.hs
+++ b/tests/NanoFeldsparEval.hs
@@ -9,10 +9,16 @@
 
 
 
+prop_scProd a b = eval scProd a' b' == ref a' b'
+  where
+    a' = take 20 a
+    b' = take 20 b
+    ref a b = sum (zipWith (*) a b)
+
 prop_1 a b = eval prog1 a' b == ref a' b
   where
     a' = a `mod` 20
-    ref a b = [min (i+3) b | i <- [0..a'-1]]
+    ref a b = [min (i+3) b | i <- [0..a-1]]
 
 prop_2 a = eval prog2 a == ref a
   where
@@ -26,17 +32,22 @@
         l = min a b
         u = max a b
 
-prop_4 a = eval prog4 a == ref a
+prop_4 a = eval prog4 a' == ref a'
   where
+    a' = a `mod` 20
+    ref a = [(a+a)*i | i <- [0..a-1]]
+
+prop_5 a = eval prog5 a == ref a
+  where
     ref a = let (b,c) = (a*2,a*3) in (b-c)*(c-b)
 
-prop_5 = eval prog5 == ref
+prop_6 = eval prog6 == ref
   where
     ref = as!!1 + sum as + sum as
       where
         as = map (*2) [1..20]
 
-prop_7 a = eval prog7 a == ref a
+prop_8 a = eval prog8 a == ref a
   where
     ref a = [a .. a+9]
 
diff --git a/tests/NanoFeldsparTree.hs b/tests/NanoFeldsparTree.hs
--- a/tests/NanoFeldsparTree.hs
+++ b/tests/NanoFeldsparTree.hs
@@ -8,22 +8,28 @@
 
 
 
-mkGold1 = B.writeFile "tests/gold/prog1.txt" $ B.pack $ showAST prog1
-mkGold2 = B.writeFile "tests/gold/prog2.txt" $ B.pack $ showAST prog2
-mkGold3 = B.writeFile "tests/gold/prog3.txt" $ B.pack $ showAST prog3
-mkGold4 = B.writeFile "tests/gold/prog4.txt" $ B.pack $ showAST prog4
-mkGold5 = B.writeFile "tests/gold/prog5.txt" $ B.pack $ showAST prog5
-mkGold6 = B.writeFile "tests/gold/prog6.txt" $ B.pack $ showAST prog6
-mkGold7 = B.writeFile "tests/gold/prog7.txt" $ B.pack $ showAST prog7
+mkGold_scProd = B.writeFile "tests/gold/scProd.txt" $ B.pack $ showAST scProd
+mkGold_matMul = B.writeFile "tests/gold/matMul.txt" $ B.pack $ showAST matMul
+mkGold_prog1  = B.writeFile "tests/gold/prog1.txt"  $ B.pack $ showAST prog1
+mkGold_prog2  = B.writeFile "tests/gold/prog2.txt"  $ B.pack $ showAST prog2
+mkGold_prog3  = B.writeFile "tests/gold/prog3.txt"  $ B.pack $ showAST prog3
+mkGold_prog4  = B.writeFile "tests/gold/prog4.txt"  $ B.pack $ showAST prog4
+mkGold_prog5  = B.writeFile "tests/gold/prog5.txt"  $ B.pack $ showAST prog5
+mkGold_prog6  = B.writeFile "tests/gold/prog6.txt"  $ B.pack $ showAST prog6
+mkGold_prog7  = B.writeFile "tests/gold/prog7.txt"  $ B.pack $ showAST prog7
+mkGold_prog8  = B.writeFile "tests/gold/prog8.txt"  $ B.pack $ showAST prog8
 
 tests = testGroup "TreeTests"
-    [ goldenVsString "prog1" "tests/gold/prog1.txt" $ return $ B.pack $ showAST prog1
-    , goldenVsString "prog2" "tests/gold/prog2.txt" $ return $ B.pack $ showAST prog2
-    , goldenVsString "prog3" "tests/gold/prog3.txt" $ return $ B.pack $ showAST prog3
-    , goldenVsString "prog4" "tests/gold/prog4.txt" $ return $ B.pack $ showAST prog4
-    , goldenVsString "prog5" "tests/gold/prog5.txt" $ return $ B.pack $ showAST prog5
-    , goldenVsString "prog6" "tests/gold/prog6.txt" $ return $ B.pack $ showAST prog6
-    , goldenVsString "prog7" "tests/gold/prog7.txt" $ return $ B.pack $ showAST prog7
+    [ goldenVsString "scProd" "tests/gold/scProd.txt" $ return $ B.pack $ showAST scProd
+    , goldenVsString "matMul" "tests/gold/matMul.txt" $ return $ B.pack $ showAST matMul
+    , goldenVsString "prog1"  "tests/gold/prog1.txt"  $ return $ B.pack $ showAST prog1
+    , goldenVsString "prog2"  "tests/gold/prog2.txt"  $ return $ B.pack $ showAST prog2
+    , goldenVsString "prog3"  "tests/gold/prog3.txt"  $ return $ B.pack $ showAST prog3
+    , goldenVsString "prog4"  "tests/gold/prog4.txt"  $ return $ B.pack $ showAST prog4
+    , goldenVsString "prog5"  "tests/gold/prog5.txt"  $ return $ B.pack $ showAST prog5
+    , goldenVsString "prog6"  "tests/gold/prog6.txt"  $ return $ B.pack $ showAST prog6
+    , goldenVsString "prog7"  "tests/gold/prog7.txt"  $ return $ B.pack $ showAST prog7
+    , goldenVsString "prog8"  "tests/gold/prog8.txt"  $ return $ B.pack $ showAST prog8
     ]
 
 main = defaultMain [tests]
diff --git a/tests/gold/matMul.txt b/tests/gold/matMul.txt
new file mode 100644
--- /dev/null
+++ b/tests/gold/matMul.txt
@@ -0,0 +1,87 @@
+Lambda 0
+|
+`- Lambda 1
+   |
+   `- Let 6
+      |
+      +- arrLength
+      |  |
+      |  `- getIx
+      |     |
+      |     +- var:1
+      |     |
+      |     `- 0
+      |
+      `- Let 7
+         |
+         +- arrLength
+         |  |
+         |  `- var:1
+         |
+         `- parallel
+            |
+            +- arrLength
+            |  |
+            |  `- var:0
+            |
+            `- Lambda 2
+               |
+               `- Let 8
+                  |
+                  +- min
+                  |  |
+                  |  +- arrLength
+                  |  |  |
+                  |  |  `- getIx
+                  |  |     |
+                  |  |     +- var:0
+                  |  |     |
+                  |  |     `- var:2
+                  |  |
+                  |  `- var:7
+                  |
+                  `- Let 9
+                     |
+                     +- getIx
+                     |  |
+                     |  +- var:0
+                     |  |
+                     |  `- var:2
+                     |
+                     `- parallel
+                        |
+                        +- var:6
+                        |
+                        `- Lambda 3
+                           |
+                           `- forLoop
+                              |
+                              +- var:8
+                              |
+                              +- 0.0
+                              |
+                              `- Lambda 4
+                                 |
+                                 `- Lambda 5
+                                    |
+                                    `- (+)
+                                       |
+                                       +- (*)
+                                       |  |
+                                       |  +- getIx
+                                       |  |  |
+                                       |  |  +- var:9
+                                       |  |  |
+                                       |  |  `- var:4
+                                       |  |
+                                       |  `- getIx
+                                       |     |
+                                       |     +- getIx
+                                       |     |  |
+                                       |     |  +- var:1
+                                       |     |  |
+                                       |     |  `- var:4
+                                       |     |
+                                       |     `- var:3
+                                       |
+                                       `- var:5
diff --git a/tests/gold/prog3.txt b/tests/gold/prog3.txt
--- a/tests/gold/prog3.txt
+++ b/tests/gold/prog3.txt
@@ -38,26 +38,22 @@
             |
             `- Lambda 2
                |
-               `- Let 6
-                  |
-                  +- (+)
-                  |  |
-                  |  +- (-)
-                  |  |  |
-                  |  |  +- (-)
-                  |  |  |  |
-                  |  |  |  +- var:4
-                  |  |  |  |
-                  |  |  |  `- var:2
-                  |  |  |
-                  |  |  `- 1
-                  |  |
-                  |  `- var:5
+               `- Lambda 3
                   |
-                  `- Lambda 3
+                  `- (+)
                      |
-                     `- (+)
-                        |
-                        +- var:6
-                        |
-                        `- var:3
+                     +- (+)
+                     |  |
+                     |  +- (-)
+                     |  |  |
+                     |  |  +- (-)
+                     |  |  |  |
+                     |  |  |  +- var:4
+                     |  |  |  |
+                     |  |  |  `- var:2
+                     |  |  |
+                     |  |  `- 1
+                     |  |
+                     |  `- var:5
+                     |
+                     `- var:3
diff --git a/tests/gold/prog4.txt b/tests/gold/prog4.txt
--- a/tests/gold/prog4.txt
+++ b/tests/gold/prog4.txt
@@ -1,43 +1,21 @@
 Lambda 0
 |
-`- Let 1
+`- Let 2
    |
-   +- tup2
+   +- (+)
    |  |
-   |  +- (*)
-   |  |  |
-   |  |  +- var:0
-   |  |  |
-   |  |  `- 2
+   |  +- var:0
    |  |
-   |  `- (*)
-   |     |
-   |     +- var:0
-   |     |
-   |     `- 3
+   |  `- var:0
    |
-   `- Let 2
+   `- parallel
       |
-      +- sel1
-      |  |
-      |  `- var:1
+      +- var:0
       |
-      `- Let 3
-         |
-         +- sel2
-         |  |
-         |  `- var:1
+      `- Lambda 1
          |
          `- (*)
             |
-            +- (-)
-            |  |
-            |  +- var:2
-            |  |
-            |  `- var:3
+            +- var:2
             |
-            `- (-)
-               |
-               +- var:3
-               |
-               `- var:2
+            `- var:1
diff --git a/tests/gold/prog5.txt b/tests/gold/prog5.txt
--- a/tests/gold/prog5.txt
+++ b/tests/gold/prog5.txt
@@ -1,71 +1,43 @@
-Let 9
-|
-+- parallel
-|  |
-|  +- (+)
-|  |  |
-|  |  +- (-)
-|  |  |  |
-|  |  |  +- 20
-|  |  |  |
-|  |  |  `- 1
-|  |  |
-|  |  `- 1
-|  |
-|  `- Lambda 0
-|     |
-|     `- (+)
-|        |
-|        +- var:0
-|        |
-|        `- 1
+Lambda 0
 |
-`- Let 11
+`- Let 1
    |
-   +- forLoop
+   +- tup2
    |  |
-   |  +- arrLength
+   |  +- (*)
    |  |  |
-   |  |  `- var:9
-   |  |
-   |  +- 0
+   |  |  +- var:0
+   |  |  |
+   |  |  `- 2
    |  |
-   |  `- Lambda 2
+   |  `- (*)
    |     |
-   |     `- Let 10
-   |        |
-   |        +- (*)
-   |        |  |
-   |        |  +- getIx
-   |        |  |  |
-   |        |  |  +- var:9
-   |        |  |  |
-   |        |  |  `- var:2
-   |        |  |
-   |        |  `- 2
-   |        |
-   |        `- Lambda 3
-   |           |
-   |           `- (+)
-   |              |
-   |              +- var:10
-   |              |
-   |              `- var:3
+   |     +- var:0
+   |     |
+   |     `- 3
    |
-   `- (+)
+   `- Let 2
       |
-      +- (+)
-      |  |
-      |  +- (*)
-      |  |  |
-      |  |  +- getIx
-      |  |  |  |
-      |  |  |  +- var:9
-      |  |  |  |
-      |  |  |  `- 1
-      |  |  |
-      |  |  `- 2
+      +- sel1
       |  |
-      |  `- var:11
+      |  `- var:1
       |
-      `- var:11
+      `- Let 3
+         |
+         +- sel2
+         |  |
+         |  `- var:1
+         |
+         `- (*)
+            |
+            +- (-)
+            |  |
+            |  +- var:2
+            |  |
+            |  `- var:3
+            |
+            `- (-)
+               |
+               +- var:3
+               |
+               `- var:2
diff --git a/tests/gold/prog6.txt b/tests/gold/prog6.txt
--- a/tests/gold/prog6.txt
+++ b/tests/gold/prog6.txt
@@ -1,25 +1,67 @@
-Let 1
+Let 9
 |
-+- max
++- parallel
 |  |
-|  +- 5
+|  +- (+)
+|  |  |
+|  |  +- (-)
+|  |  |  |
+|  |  |  +- 20
+|  |  |  |
+|  |  |  `- 1
+|  |  |
+|  |  `- 1
 |  |
-|  `- (+)
-|     |
-|     +- 6
+|  `- Lambda 0
 |     |
-|     `- 7
+|     `- (+)
+|        |
+|        +- var:0
+|        |
+|        `- 1
 |
-`- Lambda 0
+`- Let 10
    |
-   `- condition
+   +- forLoop
+   |  |
+   |  +- arrLength
+   |  |  |
+   |  |  `- var:9
+   |  |
+   |  +- 0
+   |  |
+   |  `- Lambda 2
+   |     |
+   |     `- Lambda 3
+   |        |
+   |        `- (+)
+   |           |
+   |           +- (*)
+   |           |  |
+   |           |  +- getIx
+   |           |  |  |
+   |           |  |  +- var:9
+   |           |  |  |
+   |           |  |  `- var:2
+   |           |  |
+   |           |  `- 2
+   |           |
+   |           `- var:3
+   |
+   `- (+)
       |
-      +- (==)
+      +- (+)
       |  |
-      |  +- var:0
+      |  +- (*)
+      |  |  |
+      |  |  +- getIx
+      |  |  |  |
+      |  |  |  +- var:9
+      |  |  |  |
+      |  |  |  `- 1
+      |  |  |
+      |  |  `- 2
       |  |
-      |  `- 10
-      |
-      +- var:1
+      |  `- var:10
       |
-      `- var:1
+      `- var:10
diff --git a/tests/gold/prog7.txt b/tests/gold/prog7.txt
--- a/tests/gold/prog7.txt
+++ b/tests/gold/prog7.txt
@@ -1,39 +1,25 @@
 Lambda 0
 |
-`- Let 3
+`- Let 1
    |
-   +- parallel
+   +- max
    |  |
-   |  +- 10
+   |  +- 5
    |  |
-   |  `- Lambda 1
+   |  `- (+)
    |     |
-   |     `- (+)
-   |        |
-   |        +- var:1
-   |        |
-   |        `- var:0
+   |     +- 6
+   |     |
+   |     `- 7
    |
    `- condition
       |
       +- (==)
       |  |
-      |  +- (*)
-      |  |  |
-      |  |  +- (*)
-      |  |  |  |
-      |  |  |  +- (*)
-      |  |  |  |  |
-      |  |  |  |  +- var:0
-      |  |  |  |  |
-      |  |  |  |  `- var:0
-      |  |  |  |
-      |  |  |  `- var:0
-      |  |  |
-      |  |  `- var:0
+      |  +- var:0
       |  |
-      |  `- 23
+      |  `- 10
       |
-      +- var:3
+      +- var:1
       |
-      `- var:3
+      `- var:1
diff --git a/tests/gold/prog8.txt b/tests/gold/prog8.txt
new file mode 100644
--- /dev/null
+++ b/tests/gold/prog8.txt
@@ -0,0 +1,39 @@
+Lambda 0
+|
+`- Let 3
+   |
+   +- parallel
+   |  |
+   |  +- 10
+   |  |
+   |  `- Lambda 1
+   |     |
+   |     `- (+)
+   |        |
+   |        +- var:1
+   |        |
+   |        `- var:0
+   |
+   `- condition
+      |
+      +- (==)
+      |  |
+      |  +- (*)
+      |  |  |
+      |  |  +- (*)
+      |  |  |  |
+      |  |  |  +- (*)
+      |  |  |  |  |
+      |  |  |  |  +- var:0
+      |  |  |  |  |
+      |  |  |  |  `- var:0
+      |  |  |  |
+      |  |  |  `- var:0
+      |  |  |
+      |  |  `- var:0
+      |  |
+      |  `- 23
+      |
+      +- var:3
+      |
+      `- var:3
diff --git a/tests/gold/scProd.txt b/tests/gold/scProd.txt
new file mode 100644
--- /dev/null
+++ b/tests/gold/scProd.txt
@@ -0,0 +1,39 @@
+Lambda 0
+|
+`- Lambda 1
+   |
+   `- forLoop
+      |
+      +- min
+      |  |
+      |  +- arrLength
+      |  |  |
+      |  |  `- var:0
+      |  |
+      |  `- arrLength
+      |     |
+      |     `- var:1
+      |
+      +- 0.0
+      |
+      `- Lambda 2
+         |
+         `- Lambda 3
+            |
+            `- (+)
+               |
+               +- (*)
+               |  |
+               |  +- getIx
+               |  |  |
+               |  |  +- var:0
+               |  |  |
+               |  |  `- var:2
+               |  |
+               |  `- getIx
+               |     |
+               |     +- var:1
+               |     |
+               |     `- var:2
+               |
+               `- var:3
