check :: Expression () -> JSType -> Expression () -> Expression ()
check x jsType continue =
    CondExpr () (jsFold OpLOr checks x) continue throw
  where
    jsFold op checks value =
        foldl1 (InfixExpr () op) (map ($ value) checks)

    throw =
        obj ["_U","badPort"] `call` [ StringLit () (typeToString jsType), x ]

    checks =
        case jsType of
          JSNumber ->
            [typeof "number"]

          JSInt ->
            [jsFold OpLAnd intChecks]

          JSBoolean ->
            [typeof "boolean"]

          JSString ->
            [typeof "string", instanceof "String"]

          JSArray ->
            [instanceof "Array"]

          JSObject fields ->
            [jsFold OpLAnd (typeof "object" : map member fields)]
check :: Expression () -> JSType -> Expression () -> Expression ()
check x jsType continue =
    CondExpr () (jsFold OpLOr checks x) continue throw
  where
    jsFold op checks value =
        foldl1 (InfixExpr () op) (map ($ value) checks)

    throw =
        obj ["_U","badPort"] `call` [ StringLit () (typeToString jsType), x ]

    checks =
        case jsType of
          JSNumber ->
            [typeof "number"]

          JSInt ->
            [jsFold OpLAnd intChecks]

          JSBoolean ->
            [typeof "boolean"]

          JSString ->
            [typeof "string", instanceof "String"]

          JSArray ->
            [instanceof "Array"]

          JSObject fields ->
            [jsFold OpLAnd (typeof "object" : map member fields)]
check x jsType continue =
    CondExpr () (jsFold OpLOr checks x) continue throw
  where
    jsFold op checks value =
        foldl1 (InfixExpr () op) (map ($ value) checks)

    throw =
        obj ["_U","badPort"] `call` [ StringLit () (typeToString jsType), x ]

    checks =
        case jsType of
          JSNumber ->
            [typeof "number"]

          JSInt ->
            [jsFold OpLAnd intChecks]

          JSBoolean ->
            [typeof "boolean"]

          JSString ->
            [typeof "string", instanceof "String"]

          JSArray ->
            [instanceof "Array"]

          JSObject fields ->
            [jsFold OpLAnd (typeof "object" : map member fields)]