blob: da66ae1491eecfe5c55f26496d758a82f7eb6c37 [file] [log] [blame]
// Issues: #667, #695, #622
-- in.cue --
import (
"strconv"
"regexp"
)
// In these test, it is impossible to determine the existence of some arcs due
// to mutual dependence on becoming concrete.
//
// This tests shows the essences of when an existence check cannot be resolved.
minimal: {
a: {
if b.port == _|_ {
port: ""
}
}
b: {
if a.port == _|_ {
port: ""
}
}
}
small: {
#userHostPort: #"^(:(?P<port>\d+))?$"#
p1: {
#Y: regexp.FindNamedSubmatch(#userHostPort, #X.port)
#X: {
if #Y.port == _|_ {
port: ""
}
if #Y.port != _|_ {
port: ":" + strconv.FormatInt(#Y.port, 10)
}
}
}
p2: {
#X: {
if #Y.port == _|_ {
port: ""
}
if #Y.port != _|_ {
port: ":" + strconv.FormatInt(#Y.port, 10)
}
}
#Y: regexp.FindNamedSubmatch(#userHostPort, #X.port)
}
}
medium: {
#userHostPort: #"^(:(?P<port>\d+))?$"#
p1: {
#Y: regexp.FindNamedSubmatch(#userHostPort, #X.port)
Y: {
if #Y.port != _|_ {
port: strconv.Atoi(#Y.port)
}
}
#X: {
// Can never determine whether Y.port exists as its resolution
// depends on #Y becoming finalized, which, in turn, depends on #X
// becoming finalized.
if Y.port == _|_ {
port: ""
}
if Y.port != _|_ {
port: ":" + strconv.FormatInt(Y.port, 10)
}
}
}
p2: {
#Y: regexp.FindNamedSubmatch(#userHostPort, #X.port)
#X: {
// Can never determine whether Y.port exists as its resolution
// depends on #Y becoming finalized, which, in turn, depends on #X
// becoming finalized.
if Y.port == _|_ {
port: ""
}
if Y.port != _|_ {
port: ":" + strconv.FormatInt(Y.port, 10)
}
}
Y: {
if #Y.port != _|_ {
port: strconv.Atoi(#Y.port)
}
}
}
p3: {
Y: {
if #Y.port != _|_ {
port: strconv.Atoi(#Y.port)
}
}
#Y: regexp.FindNamedSubmatch(#userHostPort, #X.port)
#X: {
// Can never determine whether Y.port exists as its resolution
// depends on #Y becoming finalized, which, in turn, depends on #X
// becoming finalized.
if Y.port == _|_ {
port: ""
}
if Y.port != _|_ {
port: ":" + strconv.FormatInt(Y.port, 10)
}
}
}
p4: {
Y: {
if #Y.port != _|_ {
port: strconv.Atoi(#Y.port)
}
}
#X: {
// Can never determine whether Y.port exists as its resolution
// depends on #Y becoming finalized, which, in turn, depends on #X
// becoming finalized.
if Y.port == _|_ {
port: ""
}
if Y.port != _|_ {
port: ":" + strconv.FormatInt(Y.port, 10)
}
}
#Y: regexp.FindNamedSubmatch(#userHostPort, #X.port)
}
p5: {
#X: {
// Can never determine whether Y.port exists as its resolution
// depends on #Y becoming finalized, which, in turn, depends on #X
// becoming finalized.
if Y.port == _|_ {
port: ""
}
if Y.port != _|_ {
port: ":" + strconv.FormatInt(Y.port, 10)
}
}
#Y: regexp.FindNamedSubmatch(#userHostPort, #X.port)
Y: {
if #Y.port != _|_ {
port: strconv.Atoi(#Y.port)
}
}
}
p6: {
#X: {
// Can never determine whether Y.port exists as its resolution
// depends on #Y becoming finalized, which, in turn, depends on #X
// becoming finalized.
if Y.port == _|_ {
port: ""
}
if Y.port != _|_ {
port: ":" + strconv.FormatInt(Y.port, 10)
}
}
Y: {
if #Y.port != _|_ {
port: strconv.Atoi(#Y.port)
}
}
#Y: regexp.FindNamedSubmatch(#userHostPort, #X.port)
}
}
large: {
#userHostPort: #"^((?P<userinfo>[[:alnum:]]*)@)?(?P<host>[[:alnum:].]+)(:(?P<port>\d+))?$"#
p1: {
Y: {
userinfo: "user"
host: "example.com"
}
X: #X.userinfo + #X.host + #X.port
#X: {
if Y.userinfo == _|_ {
userinfo: ""
}
if Y.userinfo != _|_ {
userinfo: Y.userinfo + "@"
}
host: Y.host
if Y.port == _|_ {
port: ""
}
if Y.port != _|_ {
port: ":" + strconv.FormatInt(Y.port, 10)
}
}
Y: {
if #Y.userinfo != _|_ {
userinfo: #Y.userinfo
}
host: #Y.host
if #Y.port != _|_ {
port: strconv.Atoi(#Y.port)
}
}
#Y: regexp.FindNamedSubmatch(#userHostPort, X)
}
p2: {
X: #X.userinfo + #X.host + #X.port
Y: {
userinfo: "user"
host: "example.com"
}
#X: {
if Y.userinfo == _|_ {
userinfo: ""
}
if Y.userinfo != _|_ {
userinfo: Y.userinfo + "@"
}
host: Y.host
if Y.port == _|_ {
port: ""
}
if Y.port != _|_ {
port: ":" + strconv.FormatInt(Y.port, 10)
}
}
Y: {
if #Y.userinfo != _|_ {
userinfo: #Y.userinfo
}
host: #Y.host
if #Y.port != _|_ {
port: strconv.Atoi(#Y.port)
}
}
#Y: regexp.FindNamedSubmatch(#userHostPort, X)
}
p3: {
X: #X.userinfo + #X.host + #X.port
#X: {
if Y.userinfo == _|_ {
userinfo: ""
}
if Y.userinfo != _|_ {
userinfo: Y.userinfo + "@"
}
host: Y.host
if Y.port == _|_ {
port: ""
}
if Y.port != _|_ {
port: ":" + strconv.FormatInt(Y.port, 10)
}
}
Y: {
userinfo: "user"
host: "example.com"
}
Y: {
if #Y.userinfo != _|_ {
userinfo: #Y.userinfo
}
host: #Y.host
if #Y.port != _|_ {
port: strconv.Atoi(#Y.port)
}
}
#Y: regexp.FindNamedSubmatch(#userHostPort, X)
}
p4: {
X: #X.userinfo + #X.host + #X.port
#X: {
if Y.userinfo == _|_ {
userinfo: ""
}
if Y.userinfo != _|_ {
userinfo: Y.userinfo + "@"
}
host: Y.host
if Y.port == _|_ {
port: ""
}
if Y.port != _|_ {
port: ":" + strconv.FormatInt(Y.port, 10)
}
}
#Y: regexp.FindNamedSubmatch(#userHostPort, X)
Y: {
userinfo: "user"
host: "example.com"
}
Y: {
if #Y.userinfo != _|_ {
userinfo: #Y.userinfo
}
host: #Y.host
if #Y.port != _|_ {
port: strconv.Atoi(#Y.port)
}
}
}
}
-- out/eval --
Errors:
large.p1.Y: cycle: field inserted by if clause that was previously evaluated by another if clause: port
large.p2.#Y: cycle: field was added after an if clause evaluated it: userinfo
large.p2.Y: cycle: field inserted by if clause that was previously evaluated by another if clause: port
large.p3.#Y: cycle: field was added after an if clause evaluated it: userinfo
large.p3.Y: cycle: field inserted by if clause that was previously evaluated by another if clause: port
large.p4.#Y: cycle: field was added after an if clause evaluated it: userinfo
medium.p1.#Y: cycle: field was added after an if clause evaluated it: port
medium.p2.#Y: cycle: field was added after an if clause evaluated it: port
medium.p3.Y: cycle: field inserted by if clause that was previously evaluated by another if clause: port
medium.p4.Y: cycle: field inserted by if clause that was previously evaluated by another if clause: port
minimal.b: cycle: field inserted by if clause that was previously evaluated by another if clause: port
small.p1.#Y: cycle: field was added after an if clause evaluated it: port
error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
./in.cue:104:23
error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
./in.cue:126:23
error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
./in.cue:228:23
error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
./in.cue:269:23
error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
./in.cue:310:23
Result:
(_|_){
// [eval]
minimal: (_|_){
// [eval]
a: (struct){
}
b: (_|_){
// [eval] minimal.b: cycle: field inserted by if clause that was previously evaluated by another if clause: port
port: (string){ "" }
}
}
small: (_|_){
// [eval]
#userHostPort: (string){ "^(:(?P<port>\\d+))?$" }
p1: (_|_){
// [eval]
#Y: (_|_){
// [eval] small.p1.#Y: cycle: field was added after an if clause evaluated it: port
port: (string){ "" }
}
#X: (#struct){
port: (string){ "" }
}
}
p2: (struct){
#X: (#struct){
port: (string){ "" }
}
#Y: (_|_){
// [incomplete] small.p2.#Y: undefined field: port:
// ./in.cue:50:50
port: (string){ "" }
}
}
}
medium: (_|_){
// [eval]
#userHostPort: (string){ "^(:(?P<port>\\d+))?$" }
p1: (_|_){
// [eval]
#Y: (_|_){
// [eval] medium.p1.#Y: cycle: field was added after an if clause evaluated it: port
port: (string){ "" }
}
Y: (struct){
}
#X: (#struct){
port: (string){ "" }
}
}
p2: (_|_){
// [eval]
#Y: (_|_){
// [eval] medium.p2.#Y: cycle: field was added after an if clause evaluated it: port
port: (string){ "" }
}
#X: (#struct){
port: (string){ "" }
}
Y: (struct){
}
}
p3: (_|_){
// [eval]
Y: (_|_){
// [eval] medium.p3.Y: cycle: field inserted by if clause that was previously evaluated by another if clause: port
port: (_|_){
// [eval] error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
// ./in.cue:104:23
}
}
#Y: (#struct){
port: (string){ "" }
}
#X: (#struct){
port: (string){ "" }
}
}
p4: (_|_){
// [eval]
Y: (_|_){
// [eval] medium.p4.Y: cycle: field inserted by if clause that was previously evaluated by another if clause: port
port: (_|_){
// [eval] error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
// ./in.cue:126:23
}
}
#X: (#struct){
port: (string){ "" }
}
#Y: (#struct){
port: (string){ "" }
}
}
p5: (struct){
#X: (#struct){
port: (string){ "" }
}
#Y: (_|_){
// [incomplete] medium.p5.#Y: undefined field: port:
// ./in.cue:158:56
port: (string){ "" }
}
Y: (struct){
}
}
p6: (struct){
#X: (#struct){
port: (string){ "" }
}
Y: (struct){
}
#Y: (_|_){
// [incomplete] medium.p6.#Y: undefined field: port:
// ./in.cue:186:56
port: (string){ "" }
}
}
}
large: (_|_){
// [eval]
#userHostPort: (string){ "^((?P<userinfo>[[:alnum:]]*)@)?(?P<host>[[:alnum:].]+)(:(?P<port>\\d+))?$" }
p1: (_|_){
// [eval]
Y: (_|_){
// [eval] large.p1.Y: cycle: field inserted by if clause that was previously evaluated by another if clause: port
userinfo: (string){ "user" }
host: (string){ "example.com" }
port: (_|_){
// [eval] error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
// ./in.cue:228:23
}
}
X: (string){ "user@example.com" }
#X: (#struct){
host: (string){ "example.com" }
userinfo: (string){ "user@" }
port: (string){ "" }
}
#Y: (#struct){
host: (string){ "example.com" }
port: (string){ "" }
userinfo: (string){ "user" }
}
}
p2: (_|_){
// [eval]
X: (string){ "user@example.com" }
Y: (_|_){
// [eval] large.p2.Y: cycle: field inserted by if clause that was previously evaluated by another if clause: port
userinfo: (string){ "user" }
host: (string){ "example.com" }
port: (_|_){
// [eval] error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
// ./in.cue:269:23
}
}
#X: (#struct){
host: (string){ "example.com" }
userinfo: (string){ "user@" }
port: (string){ "" }
}
#Y: (_|_){
// [eval] large.p2.#Y: cycle: field was added after an if clause evaluated it: userinfo
host: (string){ "example.com" }
port: (string){ "" }
userinfo: (string){ "user" }
}
}
p3: (_|_){
// [eval]
X: (string){ "user@example.com" }
#X: (#struct){
host: (string){ "example.com" }
userinfo: (string){ "user@" }
port: (string){ "" }
}
Y: (_|_){
// [eval] large.p3.Y: cycle: field inserted by if clause that was previously evaluated by another if clause: port
userinfo: (string){ "user" }
host: (string){ "example.com" }
port: (_|_){
// [eval] error in call to strconv.Atoi: strconv.Atoi: parsing "": invalid syntax:
// ./in.cue:310:23
}
}
#Y: (_|_){
// [eval] large.p3.#Y: cycle: field was added after an if clause evaluated it: userinfo
host: (string){ "example.com" }
port: (string){ "" }
userinfo: (string){ "user" }
}
}
p4: (_|_){
// [eval]
X: (string){ "user@example.com" }
#X: (#struct){
host: (string){ "example.com" }
userinfo: (string){ "user@" }
port: (string){ "" }
}
#Y: (_|_){
// [eval] large.p4.#Y: cycle: field was added after an if clause evaluated it: userinfo
host: (string){ "example.com" }
port: (string){ "" }
userinfo: (string){ "user" }
}
Y: (_|_){
// [eval]
userinfo: (string){ "user" }
host: (_|_){
// [eval] large.p4.#Y: cycle: field was added after an if clause evaluated it: userinfo
}
}
}
}
}
-- out/compile --
--- in.cue
{
minimal: {
a: {
if (〈1;b〉.port == _|_(explicit error (_|_ literal) in source)) {
port: ""
}
}
b: {
if (〈1;a〉.port == _|_(explicit error (_|_ literal) in source)) {
port: ""
}
}
}
small: {
#userHostPort: "^(:(?P<port>\\d+))?$"
p1: {
#Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port)
#X: {
if (〈1;#Y〉.port == _|_(explicit error (_|_ literal) in source)) {
port: ""
}
if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: (":" + import;strconv〉.FormatInt(〈2;#Y〉.port, 10))
}
}
}
p2: {
#X: {
if (〈1;#Y〉.port == _|_(explicit error (_|_ literal) in source)) {
port: ""
}
if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: (":" + import;strconv〉.FormatInt(〈2;#Y〉.port, 10))
}
}
#Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port)
}
}
medium: {
#userHostPort: "^(:(?P<port>\\d+))?$"
p1: {
#Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port)
Y: {
if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: import;strconv〉.Atoi(〈2;#Y〉.port)
}
}
#X: {
if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) {
port: ""
}
if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: (":" + import;strconv〉.FormatInt(〈2;Y〉.port, 10))
}
}
}
p2: {
#Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port)
#X: {
if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) {
port: ""
}
if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: (":" + import;strconv〉.FormatInt(〈2;Y〉.port, 10))
}
}
Y: {
if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: import;strconv〉.Atoi(〈2;#Y〉.port)
}
}
}
p3: {
Y: {
if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: import;strconv〉.Atoi(〈2;#Y〉.port)
}
}
#Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port)
#X: {
if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) {
port: ""
}
if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: (":" + import;strconv〉.FormatInt(〈2;Y〉.port, 10))
}
}
}
p4: {
Y: {
if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: import;strconv〉.Atoi(〈2;#Y〉.port)
}
}
#X: {
if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) {
port: ""
}
if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: (":" + import;strconv〉.FormatInt(〈2;Y〉.port, 10))
}
}
#Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port)
}
p5: {
#X: {
if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) {
port: ""
}
if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: (":" + import;strconv〉.FormatInt(〈2;Y〉.port, 10))
}
}
#Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port)
Y: {
if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: import;strconv〉.Atoi(〈2;#Y〉.port)
}
}
}
p6: {
#X: {
if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) {
port: ""
}
if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: (":" + import;strconv〉.FormatInt(〈2;Y〉.port, 10))
}
}
Y: {
if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: import;strconv〉.Atoi(〈2;#Y〉.port)
}
}
#Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;#X〉.port)
}
}
large: {
#userHostPort: "^((?P<userinfo>[[:alnum:]]*)@)?(?P<host>[[:alnum:].]+)(:(?P<port>\\d+))?$"
p1: {
Y: {
userinfo: "user"
host: "example.com"
}
X: ((〈0;#X〉.userinfo + 0;#X〉.host) + 0;#X〉.port)
#X: {
if (〈1;Y〉.userinfo == _|_(explicit error (_|_ literal) in source)) {
userinfo: ""
}
if (〈1;Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) {
userinfo: (〈2;Y〉.userinfo + "@")
}
host: 1;Y〉.host
if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) {
port: ""
}
if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: (":" + import;strconv〉.FormatInt(〈2;Y〉.port, 10))
}
}
Y: {
if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) {
userinfo: 2;#Y〉.userinfo
}
host: 1;#Y〉.host
if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: import;strconv〉.Atoi(〈2;#Y〉.port)
}
}
#Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉)
}
p2: {
X: ((〈0;#X〉.userinfo + 0;#X〉.host) + 0;#X〉.port)
Y: {
userinfo: "user"
host: "example.com"
}
#X: {
if (〈1;Y〉.userinfo == _|_(explicit error (_|_ literal) in source)) {
userinfo: ""
}
if (〈1;Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) {
userinfo: (〈2;Y〉.userinfo + "@")
}
host: 1;Y〉.host
if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) {
port: ""
}
if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: (":" + import;strconv〉.FormatInt(〈2;Y〉.port, 10))
}
}
Y: {
if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) {
userinfo: 2;#Y〉.userinfo
}
host: 1;#Y〉.host
if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: import;strconv〉.Atoi(〈2;#Y〉.port)
}
}
#Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉)
}
p3: {
X: ((〈0;#X〉.userinfo + 0;#X〉.host) + 0;#X〉.port)
#X: {
if (〈1;Y〉.userinfo == _|_(explicit error (_|_ literal) in source)) {
userinfo: ""
}
if (〈1;Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) {
userinfo: (〈2;Y〉.userinfo + "@")
}
host: 1;Y〉.host
if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) {
port: ""
}
if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: (":" + import;strconv〉.FormatInt(〈2;Y〉.port, 10))
}
}
Y: {
userinfo: "user"
host: "example.com"
}
Y: {
if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) {
userinfo: 2;#Y〉.userinfo
}
host: 1;#Y〉.host
if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: import;strconv〉.Atoi(〈2;#Y〉.port)
}
}
#Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉)
}
p4: {
X: ((〈0;#X〉.userinfo + 0;#X〉.host) + 0;#X〉.port)
#X: {
if (〈1;Y〉.userinfo == _|_(explicit error (_|_ literal) in source)) {
userinfo: ""
}
if (〈1;Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) {
userinfo: (〈2;Y〉.userinfo + "@")
}
host: 1;Y〉.host
if (〈1;Y〉.port == _|_(explicit error (_|_ literal) in source)) {
port: ""
}
if (〈1;Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: (":" + import;strconv〉.FormatInt(〈2;Y〉.port, 10))
}
}
#Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉)
Y: {
userinfo: "user"
host: "example.com"
}
Y: {
if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) {
userinfo: 2;#Y〉.userinfo
}
host: 1;#Y〉.host
if (〈1;#Y〉.port != _|_(explicit error (_|_ literal) in source)) {
port: import;strconv〉.Atoi(〈2;#Y〉.port)
}
}
}
}
}