import { PDataRepresentable } from "../../PType/PDataRepresentable.js";
import { UtilityTermOf } from "../../lib/std/UtilityTerms/addUtilityForType.js";
import { Methods, SopCtorDef, SopDefinition, SopT } from "../../type_system/types.js";
import { ToPType } from "../../type_system/ts-pluts-conversion.js";
import { Term } from "../../Term/index.js";
import { PType } from "../../PType/index.js";
/**
 * intermediate class useful to reconise structs form primitives
 */
declare class _PSop extends PType {
    protected _sop: never;
    protected constructor();
}
export type SopInstance<SCtorDef extends SopCtorDef> = {
    readonly [Field in keyof SCtorDef]: UtilityTermOf<ToPType<SCtorDef[Field]>>;
};
export type AnySopInstance<SCtorDef extends SopCtorDef> = {
    [Field in keyof SCtorDef]: Term<ToPType<SCtorDef[Field]>>;
};
export type PSop<SDef extends SopDefinition, SMethods extends Methods> = {
    new (): _PSop;
    /**
     * @deprecated
     */
    readonly termType: SopT<SDef, SMethods>;
    readonly type: SopT<SDef, SMethods>;
    [prop: string]: any;
} & PDataRepresentable & {
    [Ctor in keyof SDef]: (ctorFields: AnySopInstance<SDef[Ctor]>) => Term<PSop<SDef, SMethods>>;
};
/**
 *
 * @param {SopDef} def data-type definition of the sop
 *
 *  each property of the object is a possible constructor for the sop;
 *
 *  each constructor is defined by specifiying the fields that constructor expects and relative types
 *
 * @example
 * ```ts
 * const Shape = pstruct({
 *      Circle: {
 *          radius: int
 *      },
 *      Rectangle: {
 *          fstSide: int,
 *          sndSide: int
 *      }
 * });
 * ```
 *
 * @param {( self_t: SopT<SopDef,{}> ) => Methods} getMethods (optional) function to implement arbitrary methods on a given sop.
 *
 * the function takes as first argument the type of this same sop and expects an object with various methods to be implemented on a sop instance
 *
 * @example
 * ```ts
 * const Shape = pstruct({
 *      Circle: {
 *          radius: int
 *      },
 *      Rectangle: {
 *          fstSide: int,
 *          sndSide: int
 *      }
 * }, ( self_t ) => {
 *
 *      return {
 *          largestSide: pfn([ self_t ], int )
 *              ( self =>
 *                  pmatch( self )
 *                  .onCircle(({ radius }) => radius )
 *                  .onRectangle({ fstSide, sndSide } =>
 *                      pif( int ).$( fstSide.gt( sndSide ) )
 *                      .then( fstSide )
 *                      .else( sndSide )
 *                  )
 *              )
 *      };
 * });
 *
 * const isLargeShape = pfn([ Shape.type ], int )
 * ( shape => shape.largestSide.gtEq( 100 ) )
 * ```
 */
export declare function psop<SopDef extends SopDefinition, SMethods extends Methods>(def: SopDef, getMethods?: (self_t: SopT<SopDef, {}>) => SMethods): PSop<SopDef, SMethods>;
export {};
