import { type BaseData, Void } from '../../data/wgslTypes.ts';
import type { TgpuNamable } from '../../shared/meta.ts';
import type { InferGPU } from '../../shared/repr.ts';
import { $internal, $providing } from '../../shared/symbols.ts';
import type { Prettify } from '../../shared/utilityTypes.ts';
import type { DualFn } from '../../types.ts';
import { type Providing } from '../slot/slotTypes.ts';
import type { AnyFn, Implementation, InferArgs, InferImplSchema, InheritArgNames } from './fnTypes.ts';
import type { Withable } from '../root/rootTypes.ts';
/**
 * Describes a function signature (its arguments and return type)
 */
type TgpuFnShellHeader<Args extends BaseData[], Return extends BaseData> = {
    readonly [$internal]: true;
    readonly argTypes: Args;
    readonly returnType: Return;
};
/**
 * Describes a function signature (its arguments and return type).
 * Allows creating tgpu functions by calling this shell
 * and passing the implementation (as WGSL string or JS function) as the argument.
 */
export type TgpuFnShell<Args extends BaseData[], Return extends BaseData> = TgpuFnShellHeader<Args, Return> & (<T extends (...args: InferArgs<Args>) => InferGPU<Return>>(implementation: T) => TgpuFn<Prettify<InheritArgNames<(...args: Args) => Return, T>>['result']>) & ((implementation: string) => TgpuFn<(...args: Args) => Return>) & ((strings: TemplateStringsArray, ...values: unknown[]) => TgpuFn<(...args: Args) => Return>);
interface TgpuFnBase<ImplSchema extends AnyFn> extends TgpuNamable, Withable<TgpuFn<ImplSchema>> {
    [$internal]: {
        implementation: Implementation<ImplSchema>;
    };
    readonly resourceType: 'function';
    readonly shell: TgpuFnShellHeader<Parameters<ImplSchema>, Extract<ReturnType<ImplSchema>, BaseData>>;
    readonly [$providing]?: Providing | undefined;
    $uses(dependencyMap: Record<string, unknown>): this;
}
export type TgpuFn<ImplSchema extends AnyFn = (...args: any[]) => any> = DualFn<InferImplSchema<ImplSchema>> & TgpuFnBase<ImplSchema>;
/**
 * A function wrapper that allows providing slot and accessor overrides for shellless functions
 */
export interface TgpuGenericFn<T extends AnyFn> extends TgpuNamable, Withable<TgpuGenericFn<T>> {
    readonly [$internal]: {
        inner: T;
    };
    readonly [$providing]?: Providing | undefined;
    readonly resourceType: 'generic-function';
    (...args: Parameters<T>): ReturnType<T>;
}
export declare function fn<Args extends BaseData[] | []>(argTypes: Args, returnType?: undefined): TgpuFnShell<Args, Void>;
export declare function fn<Args extends BaseData[] | [], Return extends BaseData>(argTypes: Args, returnType: Return): TgpuFnShell<Args, Return>;
export declare function fn<T extends AnyFn>(inner: T): TgpuGenericFn<T>;
export declare function isTgpuFn<Args extends BaseData[] | [], Return extends BaseData>(value: unknown): value is TgpuFn<(...args: Args) => Return>;
export declare function isGenericFn<Callback extends AnyFn>(value: unknown): value is TgpuGenericFn<Callback>;
export {};
