// Issues: #667, #695, #622

// Comparing against bottom is not officially supported by the spec.
// In practice it is used for a variety of purposes.
//
// TODO: It should really be replaced with two builtins:
//
//    - exists(reference): check if a certain field exists.
//    - isvalid(value):    check if a certain value is valid (recursively).
//
// For now it implements something in between these two: it fails if a value
// resolves to an error, but not necessarily if it does so recursively.
// Although adding a recursive check is easy, it will break existing
// configurations, as a recursive evaluation will trigger cycles where these
// are perhaps not expected.

// To verify these tests, each result should have a field
//
//     X: "user@example.com"
//
// for the large and medium examples and
//
//     X: "message: hello"
//
// for the simple example.
-- in.cue --
import "regexp"

simple: {
	#message: #"^(message: (?P<message>.*))?$"#

	p1: {

		X: "message: hello"
		#aux: {
			if Y.message == _|_ {
				message: ""
			}
			if Y.message != _|_ {
				message: "message: " + Y.message
			}
		}

		Y: regexp.FindNamedSubmatch(#message, X)
		X: #aux.message
	}
}

medium: {
	#userHostPort: #"^((?P<userinfo>[[:alnum:]]*)@)?(?P<host>[[:alnum:].]+)$"#

	p1: {

		Y: {
			userinfo: "user"
			host:     "mod.test"
		}

		// X: "user@example.com"
		X: #X.userinfo + #X.host

		#X: {
			// userinfo: "user@"
			// host:     "mod.test"

			if Y.userinfo == _|_ {
				userinfo: ""
			}
			if Y.userinfo != _|_ {
				userinfo: Y.userinfo + "@"
			}

			host: Y.host
		}

		Y: {
			// userinfo: "user"
			// host:     "mod.test"

			if #Y.userinfo != _|_ {
				userinfo: #Y.userinfo
			}

			host: #Y.host
		}

		#Y: regexp.FindNamedSubmatch(#userHostPort, X)
	}
}
-- out/compile --
--- in.cue
{
  simple: {
    #message: "^(message: (?P<message>.*))?$"
    p1: {
      X: "message: hello"
      #aux: {
        if (〈1;Y〉.message == _|_(explicit error (_|_ literal) in source)) {
          message: ""
        }
        if (〈1;Y〉.message != _|_(explicit error (_|_ literal) in source)) {
          message: ("message: " + 〈2;Y〉.message)
        }
      }
      Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#message〉, 〈0;X〉)
      X: 〈0;#aux〉.message
    }
  }
  medium: {
    #userHostPort: "^((?P<userinfo>[[:alnum:]]*)@)?(?P<host>[[:alnum:].]+)$"
    p1: {
      Y: {
        userinfo: "user"
        host: "mod.test"
      }
      X: (〈0;#X〉.userinfo + 〈0;#X〉.host)
      #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
      }
      Y: {
        if (〈1;#Y〉.userinfo != _|_(explicit error (_|_ literal) in source)) {
          userinfo: 〈2;#Y〉.userinfo
        }
        host: 〈1;#Y〉.host
      }
      #Y: 〈import;regexp〉.FindNamedSubmatch(〈1;#userHostPort〉, 〈0;X〉)
    }
  }
}
