#name: builtins
#evalPartial
-- in.cue --
import (
	"list"
	"strings"
)

a1: {
	a: and([b, c])
	b: =~"oo"
	c: =~"fo"
}
a2: a1 & {a: "foo"}
a3: a1 & {a: "bar"}

o1: {
	a: or([b, c])
	b: string
	c: "bar"
}
o2: o1 & {a: "foo"}
o3: o1 & {a: "foo", b: "baz"}

// Issue #585
stringListErrors: {
	a: {
		x: [string, ...string]
		result: strings.Join(x, " ")
	}

	b: {
		x: [int, ...string]
		result: strings.Join(x, " ")
	}

	c: {
		x: []
		result: strings.Join(x, int)
	}
}

decimalListErrors: {
	a: {
		x: [string]
		result: list.Avg(x)
	}

	b: {
		x: [int, ...string]
		result: list.Avg(x)
	}
}
-- issue3648.cue --
// Fully finalize values before passing them to builtins.

import "list"

issue3648: reduced: {
	[string]: {
		a: list.Concat([b])
		b: [{}]
	}
	foo: {}
}
issue3648: full: {
	#Redirect: path?: string

	[string]: {
		// Note that this bug disappears if the order of the fields below is swapped.
		allRedirects: list.Concat([redirects])
		redirects:    [...#Redirect]
	}
	foo: {}
}
-- out/def --
a1: {
	a: =~"oo" & =~"fo"
	b: =~"oo"
	c: =~"fo"
}
a2: a1 & {
	a: "foo"
}
a3: a1 & {
	a: "bar"
}
o1: {
	a: string
	b: string
	c: "bar"
}
o2: o1 & {
	a: "foo"
}
o3: o1 & {
	a: "foo"
	b: "baz"
}
-- out/legacy-debug --
<0>{a1: <1>{a: (=~"oo" & =~"fo"), b: =~"oo", c: =~"fo"}, a2: <2>{a: "foo", b: =~"oo", c: =~"fo"}, a3: <3>{a: _|_((=~"oo" & "bar"):invalid value "bar" (does not match =~"oo")), b: =~"oo", c: =~"fo"}, o1: <4>{a: string, b: string, c: "bar"}, o2: <5>{a: "foo", b: string, c: "bar"}, o3: <6>{a: _|_(("baz" & "foo"):empty disjunction: conflicting values "baz" and "foo";("bar" & "foo"):empty disjunction: conflicting values "bar" and "foo"), b: "baz", c: "bar"}}
-- out/eval/stats --
Leaks:  6
Freed:  79
Reused: 70
Allocs: 15
Retain: 26

Unifications: 73
Conjuncts:    152
Disjuncts:    97
-- out/evalalpha --
Errors:
o3.a: 2 errors in empty disjunction:
o3.a: conflicting values "bar" and "foo":
    ./in.cue:17:5
    ./in.cue:20:14
o3.a: conflicting values "baz" and "foo":
    ./in.cue:20:14
    ./in.cue:20:24
a3.a: invalid value "bar" (out of bound =~"oo"):
    ./in.cue:8:5
    ./in.cue:7:5
    ./in.cue:12:14
a3.a: invalid value "bar" (out of bound =~"fo"):
    ./in.cue:9:5
    ./in.cue:7:5
    ./in.cue:12:14
stringListErrors.b.result: invalid list element 0 in argument 0 to call: cannot use value int (int) as string:
    ./in.cue:31:11
    ./in.cue:30:7
stringListErrors.c.result: cannot use int (type int) as string in argument 2 to strings.Join:
    ./in.cue:36:27
decimalListErrors.a.result: invalid list element 0 in argument 0 to call: cannot use value string (string) as number:
    ./in.cue:43:11
    ./in.cue:42:7

Result:
(_|_){
  // [eval]
  a1: (struct){
    a: (string){ &(=~"oo", =~"fo") }
    b: (string){ =~"oo" }
    c: (string){ =~"fo" }
  }
  a2: (struct){
    a: (string){ "foo" }
    b: (string){ =~"oo" }
    c: (string){ =~"fo" }
  }
  a3: (_|_){
    // [eval]
    a: (_|_){
      // [eval] a3.a: invalid value "bar" (out of bound =~"oo"):
      //     ./in.cue:8:5
      //     ./in.cue:7:5
      //     ./in.cue:12:14
      // a3.a: invalid value "bar" (out of bound =~"fo"):
      //     ./in.cue:9:5
      //     ./in.cue:7:5
      //     ./in.cue:12:14
    }
    b: (string){ =~"oo" }
    c: (string){ =~"fo" }
  }
  o1: (struct){
    a: (string){ |((string){ string }, (string){ "bar" }) }
    b: (string){ string }
    c: (string){ "bar" }
  }
  o2: (struct){
    a: (string){ "foo" }
    b: (string){ string }
    c: (string){ "bar" }
  }
  o3: (_|_){
    // [eval]
    a: (_|_){
      // [eval] o3.a: 2 errors in empty disjunction:
      // o3.a: conflicting values "bar" and "foo":
      //     ./in.cue:17:5
      //     ./in.cue:20:14
      // o3.a: conflicting values "baz" and "foo":
      //     ./in.cue:20:14
      //     ./in.cue:20:24
    }
    b: (string){ "baz" }
    c: (string){ "bar" }
  }
  stringListErrors: (_|_){
    // [eval]
    a: (struct){
      x: (list){
        0: (string){ string }
      }
      result: (_|_){
        // [incomplete] stringListErrors.a.result: non-concrete value string for element 0 of string list argument 0:
        //     ./in.cue:26:11
        //     ./in.cue:25:7
      }
    }
    b: (_|_){
      // [eval]
      x: (list){
        0: (int){ int }
      }
      result: (_|_){
        // [eval] stringListErrors.b.result: invalid list element 0 in argument 0 to call: cannot use value int (int) as string:
        //     ./in.cue:31:11
        //     ./in.cue:30:7
      }
    }
    c: (_|_){
      // [eval]
      x: (#list){
      }
      result: (_|_){
        // [eval] stringListErrors.c.result: cannot use int (type int) as string in argument 2 to strings.Join:
        //     ./in.cue:36:27
      }
    }
  }
  decimalListErrors: (_|_){
    // [eval]
    a: (_|_){
      // [eval]
      x: (#list){
        0: (string){ string }
      }
      result: (_|_){
        // [eval] decimalListErrors.a.result: invalid list element 0 in argument 0 to call: cannot use value string (string) as number:
        //     ./in.cue:43:11
        //     ./in.cue:42:7
      }
    }
    b: (struct){
      x: (list){
        0: (int){ int }
      }
      result: (_|_){
        // [incomplete] decimalListErrors.b.result: non-concrete value int for element 0 of number list argument 0:
        //     ./in.cue:48:11
        //     ./in.cue:47:7
      }
    }
  }
  issue3648: (struct){
    reduced: (struct){
      foo: (struct){
        a: (#list){
          0: (struct){
          }
        }
        b: (#list){
          0: (struct){
          }
        }
      }
    }
    full: (struct){
      #Redirect: (#struct){
        path?: (string){ string }
      }
      foo: (struct){
        allRedirects: (#list){
        }
        redirects: (list){
        }
      }
    }
  }
}
-- diff/-out/evalalpha<==>+out/eval --
diff old new
--- old
+++ new
@@ -1,13 +1,9 @@
 Errors:
 o3.a: 2 errors in empty disjunction:
 o3.a: conflicting values "bar" and "foo":
-    ./in.cue:15:12
     ./in.cue:17:5
-    ./in.cue:20:5
     ./in.cue:20:14
 o3.a: conflicting values "baz" and "foo":
-    ./in.cue:15:9
-    ./in.cue:20:5
     ./in.cue:20:14
     ./in.cue:20:24
 a3.a: invalid value "bar" (out of bound =~"oo"):
@@ -70,13 +66,9 @@
     a: (_|_){
       // [eval] o3.a: 2 errors in empty disjunction:
       // o3.a: conflicting values "bar" and "foo":
-      //     ./in.cue:15:12
       //     ./in.cue:17:5
-      //     ./in.cue:20:5
       //     ./in.cue:20:14
       // o3.a: conflicting values "baz" and "foo":
-      //     ./in.cue:15:9
-      //     ./in.cue:20:5
       //     ./in.cue:20:14
       //     ./in.cue:20:24
     }
-- diff/todo/p2 --
Missing error positions.
-- out/eval --
Errors:
o3.a: 2 errors in empty disjunction:
o3.a: conflicting values "bar" and "foo":
    ./in.cue:15:12
    ./in.cue:17:5
    ./in.cue:20:5
    ./in.cue:20:14
o3.a: conflicting values "baz" and "foo":
    ./in.cue:15:9
    ./in.cue:20:5
    ./in.cue:20:14
    ./in.cue:20:24
a3.a: invalid value "bar" (out of bound =~"oo"):
    ./in.cue:8:5
    ./in.cue:7:5
    ./in.cue:12:14
a3.a: invalid value "bar" (out of bound =~"fo"):
    ./in.cue:9:5
    ./in.cue:7:5
    ./in.cue:12:14
stringListErrors.b.result: invalid list element 0 in argument 0 to call: cannot use value int (int) as string:
    ./in.cue:31:11
    ./in.cue:30:7
stringListErrors.c.result: cannot use int (type int) as string in argument 2 to strings.Join:
    ./in.cue:36:27
decimalListErrors.a.result: invalid list element 0 in argument 0 to call: cannot use value string (string) as number:
    ./in.cue:43:11
    ./in.cue:42:7

Result:
(_|_){
  // [eval]
  a1: (struct){
    a: (string){ &(=~"oo", =~"fo") }
    b: (string){ =~"oo" }
    c: (string){ =~"fo" }
  }
  a2: (struct){
    a: (string){ "foo" }
    b: (string){ =~"oo" }
    c: (string){ =~"fo" }
  }
  a3: (_|_){
    // [eval]
    a: (_|_){
      // [eval] a3.a: invalid value "bar" (out of bound =~"oo"):
      //     ./in.cue:8:5
      //     ./in.cue:7:5
      //     ./in.cue:12:14
      // a3.a: invalid value "bar" (out of bound =~"fo"):
      //     ./in.cue:9:5
      //     ./in.cue:7:5
      //     ./in.cue:12:14
    }
    b: (string){ =~"oo" }
    c: (string){ =~"fo" }
  }
  o1: (struct){
    a: (string){ |((string){ string }, (string){ "bar" }) }
    b: (string){ string }
    c: (string){ "bar" }
  }
  o2: (struct){
    a: (string){ "foo" }
    b: (string){ string }
    c: (string){ "bar" }
  }
  o3: (_|_){
    // [eval]
    a: (_|_){
      // [eval] o3.a: 2 errors in empty disjunction:
      // o3.a: conflicting values "bar" and "foo":
      //     ./in.cue:15:12
      //     ./in.cue:17:5
      //     ./in.cue:20:5
      //     ./in.cue:20:14
      // o3.a: conflicting values "baz" and "foo":
      //     ./in.cue:15:9
      //     ./in.cue:20:5
      //     ./in.cue:20:14
      //     ./in.cue:20:24
    }
    b: (string){ "baz" }
    c: (string){ "bar" }
  }
  stringListErrors: (_|_){
    // [eval]
    a: (struct){
      x: (list){
        0: (string){ string }
      }
      result: (_|_){
        // [incomplete] stringListErrors.a.result: non-concrete value string for element 0 of string list argument 0:
        //     ./in.cue:26:11
        //     ./in.cue:25:7
      }
    }
    b: (_|_){
      // [eval]
      x: (list){
        0: (int){ int }
      }
      result: (_|_){
        // [eval] stringListErrors.b.result: invalid list element 0 in argument 0 to call: cannot use value int (int) as string:
        //     ./in.cue:31:11
        //     ./in.cue:30:7
      }
    }
    c: (_|_){
      // [eval]
      x: (#list){
      }
      result: (_|_){
        // [eval] stringListErrors.c.result: cannot use int (type int) as string in argument 2 to strings.Join:
        //     ./in.cue:36:27
      }
    }
  }
  decimalListErrors: (_|_){
    // [eval]
    a: (_|_){
      // [eval]
      x: (#list){
        0: (string){ string }
      }
      result: (_|_){
        // [eval] decimalListErrors.a.result: invalid list element 0 in argument 0 to call: cannot use value string (string) as number:
        //     ./in.cue:43:11
        //     ./in.cue:42:7
      }
    }
    b: (struct){
      x: (list){
        0: (int){ int }
      }
      result: (_|_){
        // [incomplete] decimalListErrors.b.result: non-concrete value int for element 0 of number list argument 0:
        //     ./in.cue:48:11
        //     ./in.cue:47:7
      }
    }
  }
  issue3648: (struct){
    reduced: (struct){
      foo: (struct){
        a: (#list){
          0: (struct){
          }
        }
        b: (#list){
          0: (struct){
          }
        }
      }
    }
    full: (struct){
      #Redirect: (#struct){
        path?: (string){ string }
      }
      foo: (struct){
        allRedirects: (#list){
        }
        redirects: (list){
        }
      }
    }
  }
}
-- out/compile --
--- in.cue
{
  a1: {
    a: and([
      〈1;b〉,
      〈1;c〉,
    ])
    b: =~"oo"
    c: =~"fo"
  }
  a2: (〈0;a1〉 & {
    a: "foo"
  })
  a3: (〈0;a1〉 & {
    a: "bar"
  })
  o1: {
    a: or([
      〈1;b〉,
      〈1;c〉,
    ])
    b: string
    c: "bar"
  }
  o2: (〈0;o1〉 & {
    a: "foo"
  })
  o3: (〈0;o1〉 & {
    a: "foo"
    b: "baz"
  })
  stringListErrors: {
    a: {
      x: [
        string,
        ...string,
      ]
      result: 〈import;strings〉.Join(〈0;x〉, " ")
    }
    b: {
      x: [
        int,
        ...string,
      ]
      result: 〈import;strings〉.Join(〈0;x〉, " ")
    }
    c: {
      x: []
      result: 〈import;strings〉.Join(〈0;x〉, int)
    }
  }
  decimalListErrors: {
    a: {
      x: [
        string,
      ]
      result: 〈import;list〉.Avg(〈0;x〉)
    }
    b: {
      x: [
        int,
        ...string,
      ]
      result: 〈import;list〉.Avg(〈0;x〉)
    }
  }
}
--- issue3648.cue
{
  issue3648: {
    reduced: {
      [string]: {
        a: 〈import;list〉.Concat([
          〈1;b〉,
        ])
        b: [
          {},
        ]
      }
      foo: {}
    }
  }
  issue3648: {
    full: {
      #Redirect: {
        path?: string
      }
      [string]: {
        allRedirects: 〈import;list〉.Concat([
          〈1;redirects〉,
        ])
        redirects: [
          ...〈2;#Redirect〉,
        ]
      }
      foo: {}
    }
  }
}
