// tracing: off
import * as S from "./_schema.js"
import { hasContinuation, SchemaContinuationSymbol } from "./_schema.js"
import * as Th from "./These.js"
/**
* @tsplus type ets/Schema/Constructor
*/
export type Constructor = {
(u: Input): Th.These
}
export const interpreters: ((
schema: S.SchemaAny
) => Opt<() => Constructor>)[] = [
Opt.partial(
miss =>
(schema: S.SchemaAny): (() => Constructor) => {
if (schema instanceof S.SchemaNamed) {
return () => {
const self = constructorFor(schema.self)
return u => Th.mapError_(self(u), e => S.namedE(schema.name, e))
}
}
if (schema instanceof S.SchemaMapConstructorError) {
return () => {
const self = constructorFor(schema.self)
return u => Th.mapError_(self(u), schema.mapError)
}
}
if (schema instanceof S.SchemaIdentity) {
return () => u => Th.succeed(u)
}
if (schema instanceof S.SchemaConstructor) {
return () => schema.of
}
if (schema instanceof S.SchemaRefinement) {
return () => {
const self = constructorFor(schema.self)
return u =>
Th.chain_(
pipe(
self(u),
Th.mapError(e => S.compositionE(Chunk(S.prevE(e))))
),
(
a,
w
): Th.These<
S.CompositionE | S.NextE>>,
unknown
> =>
schema.refinement(a)
? w._tag === "Some"
? Th.warn(a, w.value)
: Th.succeed(a)
: Th.fail(
S.compositionE(
w._tag === "None"
? Chunk(S.nextE(S.refinementE(schema.error(a))))
: w.value.errors.append(
S.nextE(S.refinementE(schema.error(a)))
)
)
)
)
}
}
return miss()
}
)
]
const cache = new WeakMap()
function constructorFor(
schema: S.Schema
): Constructor {
if (cache.has(schema)) {
return cache.get(schema)
}
if (schema instanceof S.SchemaLazy) {
const of_: Constructor = __ => constructorFor(schema.self())(__)
cache.set(schema, of_)
return of_ as Constructor
}
for (const interpreter of interpreters) {
const _ = interpreter(schema)
if (_._tag === "Some") {
let x: Constructor
const of_: Constructor = __ => {
if (!x) {
x = _.value()
}
return x(__)
}
cache.set(schema, of_)
return of_ as Constructor
}
}
if (hasContinuation(schema)) {
let x: Constructor
const of_: Constructor = __ => {
if (!x) {
x = constructorFor(schema[SchemaContinuationSymbol])
}
return x(__)
}
return of_ as Constructor
}
throw new Error(`Missing constructor integration for: ${JSON.stringify(schema)}`)
}
export { constructorFor as for }