================================================================================
basic/let
================================================================================

import "pkl:test"

res1 =
  let (x = 42)
    x + 1

res2 =
  let (res2 = 42)
    res2 + 1

res3 =
  let (x = 1)
    let (y = 2)
      x + y + x

res4 =
  let (x = 1)
    let (x = 2)
      x + x

res5 =
  let (price = 500) new {
    lowestPrice = price - 100
    averagePrice = new {
      price
    }
    highestPrice = new {
      ["price"] = price + 100
    }
  }

res6 =
  let (str = "Pigeon".reverse())
    str.reverse()

local pigeon = "Pigeon"

res7 =
  let (str = pigeon.reverse())
    str.reverse()

function f(a) =
  let (b = a * 2)
    a + b

res8 = f(3)

local g = (a) ->
  let (b = a * 2)
    a + b

res9 = g.apply(3)

local h = let (b = 2)
  (a) -> a + b

res10 = h.apply(3)

res11 = IntSeq(1, 5).map((n) -> let (x = n + 1) x + 1)

class Lets {
  x = 2
  y = let (z = 2) z + x
  function f(x) = let (z = 2) z + x
  z = f(x)
}

res12 = new Lets {
  x = 4
}

res13 =
  let (x = 1)
    let (y = x)
      let (z = y)
        x + y + z

// x can't access y
res14 = test.catch(() -> let (x = y) let (y = 2) x + y)

res15 = test.catch(() -> let (x = throw("ouch")) x + 1)
res16 = test.catch(() -> let (x = 1) throw("ouch"))
res17 = test.catch(() -> let (x = 1) let (y = throw("ouch")) x + y)
res18 = test.catch(() -> let (x = 1) let (y = 2) throw("ouch"))

// doesn't change meaning of `this`
res19 = let (x = this) let (y = this) x == y && y == this && this == module

--------------------------------------------------------------------------------

(module
  (importClause
    (stringConstant))
  (classProperty
    (identifier)
    (letExpr
      (typedIdentifier
        (identifier))
      (intLiteral)
      (binaryExpr
        (variableExpr
          (identifier))
        (intLiteral))))
  (classProperty
    (identifier)
    (letExpr
      (typedIdentifier
        (identifier))
      (intLiteral)
      (binaryExpr
        (variableExpr
          (identifier))
        (intLiteral))))
  (classProperty
    (identifier)
    (letExpr
      (typedIdentifier
        (identifier))
      (intLiteral)
      (letExpr
        (typedIdentifier
          (identifier))
        (intLiteral)
        (binaryExpr
          (binaryExpr
            (variableExpr
              (identifier))
            (variableExpr
              (identifier)))
          (variableExpr
            (identifier))))))
  (classProperty
    (identifier)
    (letExpr
      (typedIdentifier
        (identifier))
      (intLiteral)
      (letExpr
        (typedIdentifier
          (identifier))
        (intLiteral)
        (binaryExpr
          (variableExpr
            (identifier))
          (variableExpr
            (identifier))))))
  (classProperty
    (identifier)
    (letExpr
      (typedIdentifier
        (identifier))
      (intLiteral)
      (newExpr
        (objectBody
          (objectProperty
            (identifier)
            (binaryExpr
              (variableExpr
                (identifier))
              (intLiteral)))
          (objectProperty
            (identifier)
            (newExpr
              (objectBody
                (objectElement
                  (variableExpr
                    (identifier))))))
          (objectProperty
            (identifier)
            (newExpr
              (objectBody
                (objectEntry
                  (slStringLiteral)
                  (binaryExpr
                    (variableExpr
                      (identifier))
                    (intLiteral))))))))))
  (classProperty
    (identifier)
    (letExpr
      (typedIdentifier
        (identifier))
      (methodCallExpr
        (slStringLiteral)
        (identifier)
        (argumentList))
      (methodCallExpr
        (variableExpr
          (identifier))
        (identifier)
        (argumentList))))
  (classProperty
    (modifier)
    (identifier)
    (slStringLiteral))
  (classProperty
    (identifier)
    (letExpr
      (typedIdentifier
        (identifier))
      (methodCallExpr
        (variableExpr
          (identifier))
        (identifier)
        (argumentList))
      (methodCallExpr
        (variableExpr
          (identifier))
        (identifier)
        (argumentList))))
  (classMethod
    (methodHeader
      (identifier)
      (parameterList
        (typedIdentifier
          (identifier))))
    (letExpr
      (typedIdentifier
        (identifier))
      (binaryExpr
        (variableExpr
          (identifier))
        (intLiteral))
      (binaryExpr
        (variableExpr
          (identifier))
        (variableExpr
          (identifier)))))
  (classProperty
    (identifier)
    (methodCallExpr
      (identifier)
      (argumentList
        (intLiteral))))
  (classProperty
    (modifier)
    (identifier)
    (functionLiteral
      (parameterList
        (typedIdentifier
          (identifier)))
      (letExpr
        (typedIdentifier
          (identifier))
        (binaryExpr
          (variableExpr
            (identifier))
          (intLiteral))
        (binaryExpr
          (variableExpr
            (identifier))
          (variableExpr
            (identifier))))))
  (classProperty
    (identifier)
    (methodCallExpr
      (variableExpr
        (identifier))
      (identifier)
      (argumentList
        (intLiteral))))
  (classProperty
    (modifier)
    (identifier)
    (letExpr
      (typedIdentifier
        (identifier))
      (intLiteral)
      (functionLiteral
        (parameterList
          (typedIdentifier
            (identifier)))
        (binaryExpr
          (variableExpr
            (identifier))
          (variableExpr
            (identifier))))))
  (classProperty
    (identifier)
    (methodCallExpr
      (variableExpr
        (identifier))
      (identifier)
      (argumentList
        (intLiteral))))
  (classProperty
    (identifier)
    (methodCallExpr
      (methodCallExpr
        (identifier)
        (argumentList
          (intLiteral)
          (intLiteral)))
      (identifier)
      (argumentList
        (functionLiteral
          (parameterList
            (typedIdentifier
              (identifier)))
          (letExpr
            (typedIdentifier
              (identifier))
            (binaryExpr
              (variableExpr
                (identifier))
              (intLiteral))
            (binaryExpr
              (variableExpr
                (identifier))
              (intLiteral)))))))
  (clazz
    (identifier)
    (classBody
      (classProperty
        (identifier)
        (intLiteral))
      (classProperty
        (identifier)
        (letExpr
          (typedIdentifier
            (identifier))
          (intLiteral)
          (binaryExpr
            (variableExpr
              (identifier))
            (variableExpr
              (identifier)))))
      (classMethod
        (methodHeader
          (identifier)
          (parameterList
            (typedIdentifier
              (identifier))))
        (letExpr
          (typedIdentifier
            (identifier))
          (intLiteral)
          (binaryExpr
            (variableExpr
              (identifier))
            (variableExpr
              (identifier)))))
      (classProperty
        (identifier)
        (methodCallExpr
          (identifier)
          (argumentList
            (variableExpr
              (identifier)))))))
  (classProperty
    (identifier)
    (newExpr
      (type
        (qualifiedIdentifier
          (identifier)))
      (objectBody
        (objectProperty
          (identifier)
          (intLiteral)))))
  (classProperty
    (identifier)
    (letExpr
      (typedIdentifier
        (identifier))
      (intLiteral)
      (letExpr
        (typedIdentifier
          (identifier))
        (variableExpr
          (identifier))
        (letExpr
          (typedIdentifier
            (identifier))
          (variableExpr
            (identifier))
          (binaryExpr
            (binaryExpr
              (variableExpr
                (identifier))
              (variableExpr
                (identifier)))
            (variableExpr
              (identifier)))))))
  (lineComment)
  (classProperty
    (identifier)
    (methodCallExpr
      (variableExpr
        (identifier))
      (identifier)
      (argumentList
        (functionLiteral
          (parameterList)
          (letExpr
            (typedIdentifier
              (identifier))
            (variableExpr
              (identifier))
            (letExpr
              (typedIdentifier
                (identifier))
              (intLiteral)
              (binaryExpr
                (variableExpr
                  (identifier))
                (variableExpr
                  (identifier)))))))))
  (classProperty
    (identifier)
    (methodCallExpr
      (variableExpr
        (identifier))
      (identifier)
      (argumentList
        (functionLiteral
          (parameterList)
          (letExpr
            (typedIdentifier
              (identifier))
            (throwExpr
              (parenthesizedExpr
                (slStringLiteral)))
            (binaryExpr
              (variableExpr
                (identifier))
              (intLiteral)))))))
  (classProperty
    (identifier)
    (methodCallExpr
      (variableExpr
        (identifier))
      (identifier)
      (argumentList
        (functionLiteral
          (parameterList)
          (letExpr
            (typedIdentifier
              (identifier))
            (intLiteral)
            (throwExpr
              (parenthesizedExpr
                (slStringLiteral))))))))
  (classProperty
    (identifier)
    (methodCallExpr
      (variableExpr
        (identifier))
      (identifier)
      (argumentList
        (functionLiteral
          (parameterList)
          (letExpr
            (typedIdentifier
              (identifier))
            (intLiteral)
            (letExpr
              (typedIdentifier
                (identifier))
              (throwExpr
                (parenthesizedExpr
                  (slStringLiteral)))
              (binaryExpr
                (variableExpr
                  (identifier))
                (variableExpr
                  (identifier)))))))))
  (classProperty
    (identifier)
    (methodCallExpr
      (variableExpr
        (identifier))
      (identifier)
      (argumentList
        (functionLiteral
          (parameterList)
          (letExpr
            (typedIdentifier
              (identifier))
            (intLiteral)
            (letExpr
              (typedIdentifier
                (identifier))
              (intLiteral)
              (throwExpr
                (parenthesizedExpr
                  (slStringLiteral)))))))))
  (lineComment)
  (classProperty
    (identifier)
    (letExpr
      (typedIdentifier
        (identifier))
      (thisExpr)
      (letExpr
        (typedIdentifier
          (identifier))
        (thisExpr)
        (binaryExpr
          (binaryExpr
            (binaryExpr
              (variableExpr
                (identifier))
              (variableExpr
                (identifier)))
            (binaryExpr
              (variableExpr
                (identifier))
              (thisExpr)))
          (binaryExpr
            (thisExpr)
            (moduleExpr)))))))
