// tracing: off import { Case } from "@effect-ts/system/Case" import type { AnyError } from "../_schema.js" import { drawError } from "../_schema.js" import type { Parser, ParserEnv } from "../Parser.js" /** * The Effect fails with the generic `E` type when the parser produces an invalid result * Otherwise success with the valid result. */ export function condemn( self: Parser ): (a: X, env?: ParserEnv) => Effect { return (x, env?: ParserEnv) => Effect.suspendSucceed(() => { const y = self(x, env).effect if (y._tag === "Left") { return Effect.fail(y.left) } const [a, w] = y.right return w._tag === "Some" ? Effect.fail(w.value) : Effect(a) }) } export class CondemnException extends Case<{ readonly message: string }> { readonly _tag = "CondemnException" override toString() { return this.message } } export class ThrowableCondemnException extends Error { readonly _tag = "CondemnException" constructor(readonly error: AnyError) { super(drawError(error)) } } /** * The Effect fails with `ThrowableCondemnException` when the parser produces an invalid result. * Otherwise succeeds with the valid result. */ export function condemnFail(self: Parser) { return (a: X, env?: ParserEnv) => Effect.suspendSucceed(() => { const res = self(a, env).effect if (res._tag === "Left") { return Effect.fail(new CondemnException({ message: drawError(res.left) })) } const warn = res.right[1] if (warn._tag === "Some") { return Effect.fail(new CondemnException({ message: drawError(warn.value) })) } return Effect(res.right[0]) }) } /** * The Effect dies with `ThrowableCondemnException` when the parser produces an invalid result. * Otherwise succeeds with the valid result. */ export function condemnDie(self: Parser) { const orFail = condemnFail(self) return (a: X, env?: ParserEnv) => orFail(a, env).orDie } /** * Throws a classic `ThrowableCondemnException` when the parser produces an invalid result. * Otherwise returns the valid result. */ export function unsafe(self: Parser) { return (a: X, env?: ParserEnv) => { const res = self(a, env).effect if (res._tag === "Left") { throw new ThrowableCondemnException(res.left) } const warn = res.right[1] if (warn._tag === "Some") { throw new ThrowableCondemnException(warn.value) } return res.right[0] } }