#Issue: 758
#Issue: 1044

// TODO(perf): reduce number of conjunctions and disjunctions.
-- stats.txt --
Leaks:  0
Freed:  24096
Reused: 24051
Allocs: 45
Retain: 1

Unifications: 18724
Conjuncts:    100730
Disjuncts:    24097

-- in.cue --
A: #Task
B: #steps: #Script & {mount: [A]}
C: #steps: #Script & {mount: [B]}

#Script: {mount: [...#Task]}

#Task: {
	// Without the proper constructs, repeating the below results
	// in exponential runtime.
	#ref
	#ref
	_ | {}
	_ | {}
	#steps: #Script
	...
}

#ref: {a: 1} | {b: 2}
-- out/evalalpha/stats --
Leaks:  96
Freed:  0
Reused: 0
Allocs: 96
Retain: 0

Unifications: 40
Conjuncts:    98
Disjuncts:    24

CloseIDElems: 290
NumCloseIDs: 22
-- out/evalalpha --
(struct){
  A: (#struct){ |((#struct){
      #steps: ~(#Script)
      a: (int){ 1 }
    }, (#struct){
      #steps: ~(#Script)
      b: (int){ 2 }
    }) }
  B: (struct){
    #steps: (#struct){
      mount: (#list){
        0: (#struct){ |((#struct){
            #steps: ~(#Script)
            a: (int){ 1 }
          }, (#struct){
            #steps: ~(#Script)
            b: (int){ 2 }
          }) }
      }
    }
  }
  C: (struct){
    #steps: (#struct){
      mount: (#list){
        0: (#struct){ |((#struct){
            #steps: (#struct){
              mount: (#list){
                0: (#struct){ |((#struct){
                    #steps: ~(#Script)
                    a: (int){ 1 }
                  }, (#struct){
                    #steps: ~(#Script)
                    b: (int){ 2 }
                  }) }
              }
            }
            a: (int){ 1 }
          }, (#struct){
            #steps: (#struct){
              mount: (#list){
                0: (#struct){ |((#struct){
                    #steps: ~(#Script)
                    a: (int){ 1 }
                  }, (#struct){
                    #steps: ~(#Script)
                    b: (int){ 2 }
                  }) }
              }
            }
            b: (int){ 2 }
          }) }
      }
    }
  }
  #Script: (#struct){
    mount: (list){
    }
  }
  #Task: (#struct){ |((#struct){
      #steps: ~(#Script)
      a: (int){ 1 }
    }, (#struct){
      #steps: ~(#Script)
      b: (int){ 2 }
    }) }
  #ref: (#struct){ |((#struct){
      a: (int){ 1 }
    }, (#struct){
      b: (int){ 2 }
    }) }
}
-- diff/-out/evalalpha<==>+out/eval --
diff old new
--- old
+++ new
@@ -1,22 +1,9 @@
 (struct){
   A: (#struct){ |((#struct){
-      #steps: (#struct){
-        mount: (list){
-        }
-      }
-      a: (int){ 1 }
-    }, (#struct){
-      #steps: (#struct){
-        mount: (list){
-        }
-      }
-      a: (int){ 1 }
-      b: (int){ 2 }
-    }, (#struct){
-      #steps: (#struct){
-        mount: (list){
-        }
-      }
+      #steps: ~(#Script)
+      a: (int){ 1 }
+    }, (#struct){
+      #steps: ~(#Script)
       b: (int){ 2 }
     }) }
   B: (struct){
@@ -23,23 +10,10 @@
     #steps: (#struct){
       mount: (#list){
         0: (#struct){ |((#struct){
-            #steps: (#struct){
-              mount: (list){
-              }
-            }
-            a: (int){ 1 }
-          }, (#struct){
-            #steps: (#struct){
-              mount: (list){
-              }
-            }
-            a: (int){ 1 }
-            b: (int){ 2 }
-          }, (#struct){
-            #steps: (#struct){
-              mount: (list){
-              }
-            }
+            #steps: ~(#Script)
+            a: (int){ 1 }
+          }, (#struct){
+            #steps: ~(#Script)
             b: (int){ 2 }
           }) }
       }
@@ -52,76 +26,23 @@
             #steps: (#struct){
               mount: (#list){
                 0: (#struct){ |((#struct){
-                    #steps: (#struct){
-                      mount: (list){
-                      }
-                    }
-                    a: (int){ 1 }
-                  }, (#struct){
-                    #steps: (#struct){
-                      mount: (list){
-                      }
-                    }
-                    a: (int){ 1 }
-                    b: (int){ 2 }
-                  }, (#struct){
-                    #steps: (#struct){
-                      mount: (list){
-                      }
-                    }
-                    b: (int){ 2 }
-                  }) }
-              }
-            }
-            a: (int){ 1 }
-          }, (#struct){
-            #steps: (#struct){
-              mount: (#list){
-                0: (#struct){ |((#struct){
-                    #steps: (#struct){
-                      mount: (list){
-                      }
-                    }
-                    a: (int){ 1 }
-                  }, (#struct){
-                    #steps: (#struct){
-                      mount: (list){
-                      }
-                    }
-                    a: (int){ 1 }
-                    b: (int){ 2 }
-                  }, (#struct){
-                    #steps: (#struct){
-                      mount: (list){
-                      }
-                    }
-                    b: (int){ 2 }
-                  }) }
-              }
-            }
-            a: (int){ 1 }
-            b: (int){ 2 }
-          }, (#struct){
-            #steps: (#struct){
-              mount: (#list){
-                0: (#struct){ |((#struct){
-                    #steps: (#struct){
-                      mount: (list){
-                      }
-                    }
-                    a: (int){ 1 }
-                  }, (#struct){
-                    #steps: (#struct){
-                      mount: (list){
-                      }
-                    }
-                    a: (int){ 1 }
-                    b: (int){ 2 }
-                  }, (#struct){
-                    #steps: (#struct){
-                      mount: (list){
-                      }
-                    }
+                    #steps: ~(#Script)
+                    a: (int){ 1 }
+                  }, (#struct){
+                    #steps: ~(#Script)
+                    b: (int){ 2 }
+                  }) }
+              }
+            }
+            a: (int){ 1 }
+          }, (#struct){
+            #steps: (#struct){
+              mount: (#list){
+                0: (#struct){ |((#struct){
+                    #steps: ~(#Script)
+                    a: (int){ 1 }
+                  }, (#struct){
+                    #steps: ~(#Script)
                     b: (int){ 2 }
                   }) }
               }
@@ -136,23 +57,10 @@
     }
   }
   #Task: (#struct){ |((#struct){
-      #steps: (#struct){
-        mount: (list){
-        }
-      }
-      a: (int){ 1 }
-    }, (#struct){
-      #steps: (#struct){
-        mount: (list){
-        }
-      }
-      a: (int){ 1 }
-      b: (int){ 2 }
-    }, (#struct){
-      #steps: (#struct){
-        mount: (list){
-        }
-      }
+      #steps: ~(#Script)
+      a: (int){ 1 }
+    }, (#struct){
+      #steps: ~(#Script)
       b: (int){ 2 }
     }) }
   #ref: (#struct){ |((#struct){
-- out/eval --
(struct){
  A: (#struct){ |((#struct){
      #steps: (#struct){
        mount: (list){
        }
      }
      a: (int){ 1 }
    }, (#struct){
      #steps: (#struct){
        mount: (list){
        }
      }
      a: (int){ 1 }
      b: (int){ 2 }
    }, (#struct){
      #steps: (#struct){
        mount: (list){
        }
      }
      b: (int){ 2 }
    }) }
  B: (struct){
    #steps: (#struct){
      mount: (#list){
        0: (#struct){ |((#struct){
            #steps: (#struct){
              mount: (list){
              }
            }
            a: (int){ 1 }
          }, (#struct){
            #steps: (#struct){
              mount: (list){
              }
            }
            a: (int){ 1 }
            b: (int){ 2 }
          }, (#struct){
            #steps: (#struct){
              mount: (list){
              }
            }
            b: (int){ 2 }
          }) }
      }
    }
  }
  C: (struct){
    #steps: (#struct){
      mount: (#list){
        0: (#struct){ |((#struct){
            #steps: (#struct){
              mount: (#list){
                0: (#struct){ |((#struct){
                    #steps: (#struct){
                      mount: (list){
                      }
                    }
                    a: (int){ 1 }
                  }, (#struct){
                    #steps: (#struct){
                      mount: (list){
                      }
                    }
                    a: (int){ 1 }
                    b: (int){ 2 }
                  }, (#struct){
                    #steps: (#struct){
                      mount: (list){
                      }
                    }
                    b: (int){ 2 }
                  }) }
              }
            }
            a: (int){ 1 }
          }, (#struct){
            #steps: (#struct){
              mount: (#list){
                0: (#struct){ |((#struct){
                    #steps: (#struct){
                      mount: (list){
                      }
                    }
                    a: (int){ 1 }
                  }, (#struct){
                    #steps: (#struct){
                      mount: (list){
                      }
                    }
                    a: (int){ 1 }
                    b: (int){ 2 }
                  }, (#struct){
                    #steps: (#struct){
                      mount: (list){
                      }
                    }
                    b: (int){ 2 }
                  }) }
              }
            }
            a: (int){ 1 }
            b: (int){ 2 }
          }, (#struct){
            #steps: (#struct){
              mount: (#list){
                0: (#struct){ |((#struct){
                    #steps: (#struct){
                      mount: (list){
                      }
                    }
                    a: (int){ 1 }
                  }, (#struct){
                    #steps: (#struct){
                      mount: (list){
                      }
                    }
                    a: (int){ 1 }
                    b: (int){ 2 }
                  }, (#struct){
                    #steps: (#struct){
                      mount: (list){
                      }
                    }
                    b: (int){ 2 }
                  }) }
              }
            }
            b: (int){ 2 }
          }) }
      }
    }
  }
  #Script: (#struct){
    mount: (list){
    }
  }
  #Task: (#struct){ |((#struct){
      #steps: (#struct){
        mount: (list){
        }
      }
      a: (int){ 1 }
    }, (#struct){
      #steps: (#struct){
        mount: (list){
        }
      }
      a: (int){ 1 }
      b: (int){ 2 }
    }, (#struct){
      #steps: (#struct){
        mount: (list){
        }
      }
      b: (int){ 2 }
    }) }
  #ref: (#struct){ |((#struct){
      a: (int){ 1 }
    }, (#struct){
      b: (int){ 2 }
    }) }
}
-- diff/-out/evalalpha/stats<==>+out/eval/stats --
diff old new
--- old
+++ new
@@ -1,9 +1,12 @@
-Leaks:  0
-Freed:  24096
-Reused: 24051
-Allocs: 45
-Retain: 1
-
-Unifications: 18724
-Conjuncts:    100730
-Disjuncts:    24097
+Leaks:  96
+Freed:  0
+Reused: 0
+Allocs: 96
+Retain: 0
+
+Unifications: 40
+Conjuncts:    98
+Disjuncts:    24
+
+CloseIDElems: 290
+NumCloseIDs: 22
-- out/eval/stats --
Leaks:  0
Freed:  24096
Reused: 24051
Allocs: 45
Retain: 1

Unifications: 18724
Conjuncts:    100730
Disjuncts:    24097
-- out/compile --
--- in.cue
{
  A: 〈0;#Task〉
  B: {
    #steps: (〈1;#Script〉 & {
      mount: [
        〈3;A〉,
      ]
    })
  }
  C: {
    #steps: (〈1;#Script〉 & {
      mount: [
        〈3;B〉,
      ]
    })
  }
  #Script: {
    mount: [
      ...〈2;#Task〉,
    ]
  }
  #Task: {
    〈1;#ref〉
    〈1;#ref〉
    (_|{})
    (_|{})
    #steps: 〈1;#Script〉
    ...
  }
  #ref: ({
    a: 1
  }|{
    b: 2
  })
}
