# This issue addresses evaluation in nested lets.
-- nested.cue --
issue3801: let: reduced: {
	let F = {
		base: {
			in: string
			let X = {a: "\(in)"}.a
			out: X
		}
		filled: base & {in: "foo"} // failure is here
	}
	z: F.filled.out
}
issue3801: nonRooted: reduced: {
	#Output: output: {
		#base: {
			val0: string
			msgObj: {a: val0}.a
			value: msgObj
		}
		out: #base & {val0: "foo"}
	}
	out: (#Output & {}).output // non-concrete
}
issue3801: let: full: {
	#Resource: {
		someMsg: string
		obs: {} | *{missing: true}

		let pickMsg = [
			if obs.missing {msg: "\(someMsg)"},
			{msg: "bar"},
		][0]
		patches: [{
			op:    "add"
			path:  "/metadata"
			value: pickMsg.msg
		}]
	}

	#Patches: [string]: _
	#JSONPatch: {
		namespace?: string
		patch: [...#JSONOp]
		output: #Patches & {(namespace): patch}
	}
	#JSONOp: {
		op:    "add"
		path:  string
		value: _
	} | {
		op:   "remove"
		path: string
	}

	#Main: {
		NS=namespace: string

		output: jsonPatch.output

		let jsonPatch = #JSONPatch & {
			let base = #Resource & {}
			let withMsg = base & {someMsg: "foo"}

			namespace: NS

			patch: withMsg.patches
		}
	}
	out: (#Main & {namespace: "ns1"}).output
}
issue3801: nonRooted: full: {
	#Output: {
		NS=namespace: string
		output: (#SubOutput & {
			namespace: NS
			let base2 = {
				let base = #Base & {}
				output: base & {val0: "foo"}
			}
			patch: base2.output.value
		}).output
	}
	out: (#Output & {namespace: "ns1"}).output

	#SubOutput: {
		namespace?: string

		patch: _
		output: (namespace): patch
	}

	#Base: {
		val0: string
		let msgObj = [val0][0]
		value: msgObj
	}
}
-- out/compile --
--- nested.cue
{
  issue3801: {
    let: {
      reduced: {
        let F#1 = {
          base: {
            in: string
            let X#2 = {
              a: "\(〈1;in〉)"
            }.a
            out: 〈0;let X#2〉
          }
          filled: (〈0;base〉 & {
            in: "foo"
          })
        }
        z: 〈0;let F#1〉.filled.out
      }
    }
  }
  issue3801: {
    nonRooted: {
      reduced: {
        #Output: {
          output: {
            #base: {
              val0: string
              msgObj: {
                a: 〈1;val0〉
              }.a
              value: 〈0;msgObj〉
            }
            out: (〈0;#base〉 & {
              val0: "foo"
            })
          }
        }
        out: (〈0;#Output〉 & {}).output
      }
    }
  }
  issue3801: {
    let: {
      full: {
        #Resource: {
          someMsg: string
          obs: ({}|*{
            missing: true
          })
          let pickMsg#4 = [
            if 〈1;obs〉.missing {
              msg: "\(〈2;someMsg〉)"
            },
            {
              msg: "bar"
            },
          ][0]
          patches: [
            {
              op: "add"
              path: "/metadata"
              value: 〈2;let pickMsg#4〉.msg
            },
          ]
        }
        #Patches: {
          [string]: _
        }
        #JSONPatch: {
          namespace?: string
          patch: [
            ...〈2;#JSONOp〉,
          ]
          output: (〈1;#Patches〉 & {
            〈1;namespace〉: 〈1;patch〉
          })
        }
        #JSONOp: ({
          op: "add"
          path: string
          value: _
        }|{
          op: "remove"
          path: string
        })
        #Main: {
          namespace: string
          output: 〈0;let jsonPatch#5〉.output
          let jsonPatch#5 = (〈1;#JSONPatch〉 & {
            let base#8 = (〈2;#Resource〉 & {})
            let withMsg#9 = (〈0;let base#8〉 & {
              someMsg: "foo"
            })
            namespace: 〈1;namespace〉
            patch: 〈0;let withMsg#9〉.patches
          })
        }
        out: (〈0;#Main〉 & {
          namespace: "ns1"
        }).output
      }
    }
  }
  issue3801: {
    nonRooted: {
      full: {
        #Output: {
          namespace: string
          output: (〈1;#SubOutput〉 & {
            namespace: 〈1;namespace〉
            let base2#A = {
              let base#B = (〈3;#Base〉 & {})
              output: (〈0;let base#B〉 & {
                val0: "foo"
              })
            }
            patch: 〈0;let base2#A〉.output.value
          }).output
        }
        out: (〈0;#Output〉 & {
          namespace: "ns1"
        }).output
        #SubOutput: {
          namespace?: string
          patch: _
          output: {
            〈1;namespace〉: 〈1;patch〉
          }
        }
        #Base: {
          val0: string
          let msgObj#D = [
            〈1;val0〉,
          ][0]
          value: 〈0;let msgObj#D〉
        }
      }
    }
  }
}
