testLetExpr :: Test
testLetExpr = TestList
  [ testEq "Parse let expression with 0 binding"
           (LetExpr [] (VarExpr "bar"))
           "let in bar"
  , testEq "Parse let expression with 1 binding"
           (LetExpr [("bar", constNum 1)] (VarExpr "bar"))
           "let bar = 1 in bar"
  , testEq "Parse let expression with multi bindings"
           (LetExpr [("x", constNum 1), ("y", constNum 2), ("z", constNum 3)]
                    (VarExpr "bar"))
           "let x = 1 y = 2 z = 3 in bar"
  , testEq "Parse let recursive expression"
         (LetRecExpr
           [("double", ["xxx"], BinOpExpr Mul (constNum 2) (VarExpr "xxx"))]
           (CallExpr (VarExpr "double") [constNum 5]))
         "letrec double(xxx) = *(2, xxx) in (double 5)"
  ]
testLetExpr :: Test
testLetExpr = TestList
  [ testEq "Parse let expression with 0 binding"
           (LetExpr [] (VarExpr "bar"))
           "let in bar"
  , testEq "Parse let expression with 1 binding"
           (LetExpr [("bar", constNum 1)] (VarExpr "bar"))
           "let bar = 1 in bar"
  , testEq "Parse let expression with multi bindings"
           (LetExpr [("x", constNum 1), ("y", constNum 2), ("z", constNum 3)]
                    (VarExpr "bar"))
           "let x = 1 y = 2 z = 3 in bar"
  , testEq "Parse let recursive expression"
         (LetRecExpr
           [("double", ["xxx"], BinOpExpr Mul (constNum 2) (VarExpr "xxx"))]
           (CallExpr (VarExpr "double") [constNum 5]))
         "letrec double(xxx) = *(2, xxx) in (double 5)"
  ]
testLetExpr = TestList
  [ testEq "Parse let expression with 0 binding"
           (LetExpr [] (VarExpr "bar"))
           "let in bar"
  , testEq "Parse let expression with 1 binding"
           (LetExpr [("bar", constNum 1)] (VarExpr "bar"))
           "let bar = 1 in bar"
  , testEq "Parse let expression with multi bindings"
           (LetExpr [("x", constNum 1), ("y", constNum 2), ("z", constNum 3)]
                    (VarExpr "bar"))
           "let x = 1 y = 2 z = 3 in bar"
  , testEq "Parse let recursive expression"
         (LetRecExpr
           [("double", ["xxx"], BinOpExpr Mul (constNum 2) (VarExpr "xxx"))]
           (CallExpr (VarExpr "double") [constNum 5]))
         "letrec double(xxx) = *(2, xxx) in (double 5)"
  ]