// These tests are related to issue 2351.

-- in.cue --

conjunct: t1: {
	#early: *"X" | string
	#early
} & {
	#early: *"X" | string
	string
}

conjunct: t2: {
	#early: *"X" | string
	#early
}
conjunct: t2: {
	#early: *"X" | string
	string
}

// TODO: fix this test
conjunct: t3: conjunct.t1 & conjunct.t2

handleComprehensions: {
	if false {
		subs: #sub2 & 2
	}
	#sub2: 2
}

-- issue2351.cue --
issue2351: let: {
	let _param = "foo"
	({
		param: _param & [{}]
		gen: [for p in param {p}]
	}).gen
}

issue2351: hidden: {
	_in1: ["foo"]
	{
		in2: _in1
		out: [for x in in2 {x}]
	}.out
}

-- issue2355.cue --
issue2355: {
	#GetF1: {
		in:  _
		out: in.f1
	}

	#PutOut1: {
		in: _
		out: out1: "\(in)"
	}

	export: {
		let data = {f1: "foo"}
		(#PutOut1 & {
			in: (#GetF1 & {
				in: data
			}).out
		}).out
	}
}

-- out/evalalpha/stats --
Leaks:  244
Freed:  0
Reused: 0
Allocs: 244
Retain: 0

Unifications: 40
Conjuncts:    254
Disjuncts:    152

CloseIDElems: 160
NumCloseIDs: 48
-- out/evalalpha --
Errors:
param: conflicting values [{}] and "foo" (mismatched types list and string):
    ./issue2351.cue:2:15
    ./issue2351.cue:4:19

Result:
(_|_){
  // [eval]
  conjunct: (struct){
    t1: (string){ |(*(string){
        "X"
        #early: (string){ |(*(string){ "X" }, (string){ string }) }
      }, (string){
        string
        #early: (string){ |(*(string){ "X" }, (string){ string }) }
      }) }
    t2: (string){ |(*(string){
        "X"
        #early: (string){ |(*(string){ "X" }, (string){ string }) }
      }, (string){
        string
        #early: (string){ |(*(string){ "X" }, (string){ string }) }
      }) }
    t3: (string){ |(*(string){
        "X"
        #early: (string){ |(*(string){ "X" }, (string){ string }) }
      }, (string){
        string
        #early: (string){ |(*(string){ "X" }, (string){ string }) }
      }) }
  }
  handleComprehensions: (struct){
    #sub2: (int){ 2 }
  }
  issue2351: (_|_){
    // [eval]
    let: (_|_){
      // [eval] param: conflicting values [{}] and "foo" (mismatched types list and string):
      //     ./issue2351.cue:2:15
      //     ./issue2351.cue:4:19
      let _param#1 = (string){ "foo" }
    }
    hidden: (#list){
      _in1: (#list){
        0: (string){ "foo" }
      }
      0: (string){ "foo" }
    }
  }
  issue2355: (struct){
    #GetF1: (#struct){
      in: (_){ _ }
      out: (_|_){
        // [incomplete] issue2355.#GetF1.out: in.f1 undefined as in is incomplete (type _):
        //     ./issue2355.cue:4:8
      }
    }
    #PutOut1: (#struct){
      in: (_){ _ }
      out: (#struct){
        out1: (_|_){
          // [incomplete] issue2355.#PutOut1.out.out1: invalid interpolation: non-concrete value _ (type _):
          //     ./issue2355.cue:9:14
        }
      }
    }
    export: (#struct){
      let data#2 = (struct){
        f1: (string){ "foo" }
      }
      out1: (string){ "foo" }
    }
  }
}
-- diff/-out/evalalpha/stats<==>+out/eval/stats --
diff old new
--- old
+++ new
@@ -1,9 +1,12 @@
-Leaks:  9
-Freed:  68
-Reused: 59
-Allocs: 18
-Retain: 22
-
-Unifications: 45
-Conjuncts:    135
-Disjuncts:    86
+Leaks:  244
+Freed:  0
+Reused: 0
+Allocs: 244
+Retain: 0
+
+Unifications: 40
+Conjuncts:    254
+Disjuncts:    152
+
+CloseIDElems: 160
+NumCloseIDs: 48
-- diff/-out/evalalpha<==>+out/eval --
diff old new
--- old
+++ new
@@ -1,7 +1,6 @@
 Errors:
-issue2351.let.param: conflicting values "foo" and [{}] (mismatched types string and list):
+param: conflicting values [{}] and "foo" (mismatched types list and string):
     ./issue2351.cue:2:15
-    ./issue2351.cue:3:2
     ./issue2351.cue:4:19
 
 Result:
@@ -22,14 +21,13 @@
         string
         #early: (string){ |(*(string){ "X" }, (string){ string }) }
       }) }
-    t3: (_|_){
-      // [incomplete] conjunct.t3: 2 errors in empty disjunction:
-      // conjunct.t3: cannot add field #early: was already used:
-      //     ./in.cue:6:2
-      // conjunct.t3: cannot add field #early: was already used:
-      //     ./in.cue:15:2
-      #early: (string){ |(*(string){ "X" }, (string){ string }) }
-    }
+    t3: (string){ |(*(string){
+        "X"
+        #early: (string){ |(*(string){ "X" }, (string){ string }) }
+      }, (string){
+        string
+        #early: (string){ |(*(string){ "X" }, (string){ string }) }
+      }) }
   }
   handleComprehensions: (struct){
     #sub2: (int){ 2 }
@@ -37,9 +35,8 @@
   issue2351: (_|_){
     // [eval]
     let: (_|_){
-      // [eval] issue2351.let.param: conflicting values "foo" and [{}] (mismatched types string and list):
+      // [eval] param: conflicting values [{}] and "foo" (mismatched types list and string):
       //     ./issue2351.cue:2:15
-      //     ./issue2351.cue:3:2
       //     ./issue2351.cue:4:19
       let _param#1 = (string){ "foo" }
     }
@@ -67,7 +64,7 @@
         }
       }
     }
-    export: (struct){
+    export: (#struct){
       let data#2 = (struct){
         f1: (string){ "foo" }
       }
-- out/eval/stats --
Leaks:  9
Freed:  68
Reused: 59
Allocs: 18
Retain: 22

Unifications: 45
Conjuncts:    135
Disjuncts:    86
-- diff/todo/p3 --
Missing error position.
-- diff/explanation --
conjunct.t3: this used to be broken, but is now fixed.
issue2355.export: correctly closing in new evaluator.
-- out/eval --
Errors:
issue2351.let.param: conflicting values "foo" and [{}] (mismatched types string and list):
    ./issue2351.cue:2:15
    ./issue2351.cue:3:2
    ./issue2351.cue:4:19

Result:
(_|_){
  // [eval]
  conjunct: (struct){
    t1: (string){ |(*(string){
        "X"
        #early: (string){ |(*(string){ "X" }, (string){ string }) }
      }, (string){
        string
        #early: (string){ |(*(string){ "X" }, (string){ string }) }
      }) }
    t2: (string){ |(*(string){
        "X"
        #early: (string){ |(*(string){ "X" }, (string){ string }) }
      }, (string){
        string
        #early: (string){ |(*(string){ "X" }, (string){ string }) }
      }) }
    t3: (_|_){
      // [incomplete] conjunct.t3: 2 errors in empty disjunction:
      // conjunct.t3: cannot add field #early: was already used:
      //     ./in.cue:6:2
      // conjunct.t3: cannot add field #early: was already used:
      //     ./in.cue:15:2
      #early: (string){ |(*(string){ "X" }, (string){ string }) }
    }
  }
  handleComprehensions: (struct){
    #sub2: (int){ 2 }
  }
  issue2351: (_|_){
    // [eval]
    let: (_|_){
      // [eval] issue2351.let.param: conflicting values "foo" and [{}] (mismatched types string and list):
      //     ./issue2351.cue:2:15
      //     ./issue2351.cue:3:2
      //     ./issue2351.cue:4:19
      let _param#1 = (string){ "foo" }
    }
    hidden: (#list){
      _in1: (#list){
        0: (string){ "foo" }
      }
      0: (string){ "foo" }
    }
  }
  issue2355: (struct){
    #GetF1: (#struct){
      in: (_){ _ }
      out: (_|_){
        // [incomplete] issue2355.#GetF1.out: in.f1 undefined as in is incomplete (type _):
        //     ./issue2355.cue:4:8
      }
    }
    #PutOut1: (#struct){
      in: (_){ _ }
      out: (#struct){
        out1: (_|_){
          // [incomplete] issue2355.#PutOut1.out.out1: invalid interpolation: non-concrete value _ (type _):
          //     ./issue2355.cue:9:14
        }
      }
    }
    export: (struct){
      let data#2 = (struct){
        f1: (string){ "foo" }
      }
      out1: (string){ "foo" }
    }
  }
}
-- out/compile --
--- in.cue
{
  conjunct: {
    t1: ({
      #early: (*"X"|string)
      〈0;#early〉
    } & {
      #early: (*"X"|string)
      string
    })
  }
  conjunct: {
    t2: {
      #early: (*"X"|string)
      〈0;#early〉
    }
  }
  conjunct: {
    t2: {
      #early: (*"X"|string)
      string
    }
  }
  conjunct: {
    t3: (〈1;conjunct〉.t1 & 〈1;conjunct〉.t2)
  }
  handleComprehensions: {
    if false {
      subs: (〈1;#sub2〉 & 2)
    }
    #sub2: 2
  }
}
--- issue2351.cue
{
  issue2351: {
    let: {
      let _param#1 = "foo"
      {
        param: (〈1;let _param#1〉 & [
          {},
        ])
        gen: [
          for _, p in 〈1;param〉 {
            〈1;p〉
          },
        ]
      }.gen
    }
  }
  issue2351: {
    hidden: {
      _in1: [
        "foo",
      ]
      {
        in2: 〈1;_in1〉
        out: [
          for _, x in 〈1;in2〉 {
            〈1;x〉
          },
        ]
      }.out
    }
  }
}
--- issue2355.cue
{
  issue2355: {
    #GetF1: {
      in: _
      out: 〈0;in〉.f1
    }
    #PutOut1: {
      in: _
      out: {
        out1: "\(〈1;in〉)"
      }
    }
    export: {
      let data#2 = {
        f1: "foo"
      }
      (〈1;#PutOut1〉 & {
        in: (〈2;#GetF1〉 & {
          in: 〈2;let data#2〉
        }).out
      }).out
    }
  }
}
