declare module "buffer" {
    /** Growable byte buffer. Why isn't this part of the standard library? */
    export class ByteBuffer {
        buf: Uint8Array;
        len: number;
        constructor(cap?: number);
        get cap(): number;
        get data(): Uint8Array<ArrayBuffer>;
        toString(): string;
        write(data: Uint8Array): void;
        copyFrom(other: ByteBuffer): void;
        grow(size: number): void;
        reset(): void;
    }
}
declare module "c" {
    export const PTRSIZE: size_t;
    export const ALIGN: int_t;
    export const NULL: Ptr<any>;
    export const FALSE: bool_t;
    export const TRUE: bool_t;
    export type Ptr<T> = number & {
        _tag?: T;
    };
    export type char_t = void;
    export type void_t = void;
    export type size_t = number;
    export type int_t = number;
    export type bool_t = 0 | 1;
    export interface WASI extends WebAssembly.Instance {
        exports: ABI;
    }
    export interface ABI extends WebAssembly.Exports {
        memory: WebAssembly.Memory;
        canonical_abi_realloc<T>(ptr: Ptr<T> | typeof NULL, old_size: size_t, align: int_t, size: size_t): Ptr<T>;
        canonical_abi_free<T>(ptr: Ptr<T>, size: size_t, align: int_t): void;
        _start(): int_t;
    }
    export class CString {
        instance: WASI;
        ptr: Ptr<char_t>;
        size: number;
        constructor(instance: WASI, text: string);
        free(): void;
    }
    export function readString(instance: WASI, ptr: Ptr<char_t>, size?: number): string;
    export function indirect<T extends Ptr<U>, U extends number>(instance: WASI, addr: T): Deref<T>;
    export type Deref<T> = T extends Ptr<infer U> ? U extends number ? U : never : never;
    export function writeUint32<T>(instance: WASI, addr: Ptr<T>, int: number): void;
    export function wasiError(errno: number, context?: string): Error;
}
declare module "fs" {
    import { ConsoleStdout, PreopenDirectory, OpenFile, File as WASIFile, Inode, WASI, wasi } from 'browser_wasi_shim_gaiden';
    import { ByteBuffer } from "buffer";
    /** Virtual filesystem roughly compatible with wasmer-js. */
    export class FS {
        private os;
        private wasi;
        constructor(wasi: WASI, os: OS);
        readDir(name: string): Array<DirEntry>;
        createDir(path: string): void;
        removeDir(path: string): void;
        removeFile(name: string): void;
        rename(path: string, to: string): void;
        metadata(path: string): wasi.Filestat | null;
        open(path: string, options?: Partial<OpenMode>): File;
    }
    export type DirEntry = {
        /** Full file path. */
        path: string;
        inode: Inode;
        metadata: {
            dev: bigint;
            ino: bigint;
            filetype: {
                dir: boolean;
                file: boolean;
                symlink: boolean;
                type: FileType;
            };
            nlink: bigint;
            /** File size. */
            size: bigint;
            /** Last access time. */
            accessed: bigint;
            /** Last modified time. */
            modified: bigint;
            /** Creation time. */
            created: bigint;
        };
    };
    type FileType = typeof wasi.FILETYPE_UNKNOWN | typeof wasi.FILETYPE_BLOCK_DEVICE | typeof wasi.FILETYPE_CHARACTER_DEVICE | typeof wasi.FILETYPE_DIRECTORY | typeof wasi.FILETYPE_REGULAR_FILE | typeof wasi.FILETYPE_SOCKET_DGRAM | typeof wasi.FILETYPE_SOCKET_STREAM | typeof wasi.FILETYPE_SYMBOLIC_LINK;
    export type OpenMode = {
        create: boolean;
        write: boolean;
        append: boolean;
        truncate: boolean;
    };
    export class File {
        private openfile?;
        private entity;
        constructor(f: WASIFile | OpenFile);
        lastAccessed(): bigint;
        lastModified(): bigint;
        createdTime(): bigint;
        size(): bigint;
        read(into?: Uint8Array): Uint8Array;
        readString(): string;
        write(buf: Uint8Array): number;
        writeString(buf: string): number;
        flush(): void;
        seek(position: bigint): bigint;
    }
    export type OS = {
        stdout: OutputStream;
        stderr: OutputStream;
        root: PreopenDirectory;
    };
    export function newOS(): OS;
    class OutputStream {
        buf: ByteBuffer;
        fd: ConsoleStdout;
        constructor();
        reset(): void;
    }
}
declare module "toplevel" {
    import { Prolog, JSONEncodingOptions, PrologEncodingOptions } from "prolog";
    import { Termlike } from "term";
    export interface Toplevel<T, Options> {
        /** Prepare query string, returns goal to execute. */
        query(pl: Prolog, goal: string, bind?: Record<string, Termlike>, options?: Options): string;
        /** Parse stdout and return an answer. */
        parse(pl: Prolog, status: boolean, stdout: Uint8Array, stderr: Uint8Array, options?: Options, answer?: string): T;
        /** Yield simple truth value, when output is blank.
            For queries such as `true.` and `1=2.`.
            Return null to bail early and yield no values. */
        truth(pl: Prolog, status: boolean, stderr: Uint8Array, options?: Options): T | null;
    }
    export const FORMATS: {
        json: {
            query: (_: Prolog, query: string, bind: Record<string, Termlike>) => string;
            parse: (_pl: Prolog, _status: boolean, stdout: Uint8Array, stderr: Uint8Array, opts: JSONEncodingOptions, answer: string) => any;
            truth: () => null;
        };
        prolog: {
            query: (_: Prolog, query: string, bind: Record<string, Termlike>) => string;
            parse: (_: Prolog, _status: boolean, stdout: Uint8Array, stderr: Uint8Array, opts: PrologEncodingOptions) => string;
            truth: (_: Prolog, status: boolean, stderr: Uint8Array, opts: PrologEncodingOptions) => string;
        };
    };
}
declare module "prolog" {
    import { WASI } from 'browser_wasi_shim_gaiden';
    import { Ptr, int_t, char_t, bool_t, size_t, WASI as StandardInstance, ABI } from "c";
    import { FORMATS, Toplevel } from "toplevel";
    import { Goal, Term, Termlike } from "term";
    import { Predicate, Continuation } from "interop";
    import { FS, OS } from "fs";
    /** Load the Trealla runtime. Must be called before constructing `Prolog` instances. */
    export function load(): Promise<void>;
    export interface PrologOptions {
        /** Library files path (default: "/library")
            This is to set the search path for use_module(library(...)). */
        library?: string;
        /** Environment variables.
            Accessible with the predicate getenv/2. */
        env?: Record<string, string>;
        /** Quiet mode. Disables warnings printed to stderr if true. */
        quiet?: boolean;
        /** Manually specify module instead of the default. */
        module?: WebAssembly.Module;
    }
    export interface QueryOptions {
        /** Mapping of variables to bind in the query. */
        bind?: Record<string, Termlike>;
        /** Prolog program text to evaluate before the query. */
        program?: string | Uint8Array;
        /** Answer format. This changes the return type of the query generator.
            `"json"` (default) returns Javascript objects.
            `"prolog"` returns the standard Prolog toplevel output as strings.
            You can add custom formats to the global `FORMATS` object.
            You can also pass in a `Toplevel` object directly. */
        format?: keyof typeof FORMATS | Toplevel<any, any>;
        /** Encoding options for "json" or custom formats. */
        encode?: EncodingOptions;
        /** Automatic yield interval in milliseconds. Default is 20ms. */
        autoyield?: number;
    }
    export type EncodingOptions = JSONEncodingOptions | PrologEncodingOptions | Record<string, unknown>;
    export interface JSONEncodingOptions {
        /** Encoding for Prolog atoms. Default is "object". */
        atoms?: "string" | "object";
        /** Encoding for Prolog strings. Default is "string". */
        strings?: "string" | "list";
        /** Encoding for Prolog integers. Default is "fit", which uses bigints if outside of the safe integer range. */
        integers?: "fit" | "bigint" | "number";
        /** Functor for compounds of arity 1 to be converted to booleans.
            For example, `"{}"` to turn the Prolog term `{true}` into true ala Tau,
            or `"@"` for SWI-ish behavior that uses `@(true)`. */
        booleans?: string;
        /** Functor for compounds of arity 1 to be converted to null.
            For example, `"{}"` to turn the Prolog term `{null}` into null`. */
        nulls?: string;
        /** Functor for compounds of arity 1 to be converted to undefined.
            For example, `"{}"` to turn the Prolog term `{undefined}` into undefined`. */
        undefineds?: string;
    }
    export interface PrologEncodingOptions {
        /** Include the fullstop "." in results. */
        /** True by default. */
        dot?: boolean;
    }
    /** Answer for the "json" format. */
    export type Answer = {
        /** Standard output text (`user_output` stream in Prolog) */
        stdout?: string;
        /** Standard error text (`user_error` stream in Prolog) */
        stderr?: string;
    } & (Success | Failure | ErrorReply);
    export interface Success {
        status: "success";
        answer: Substitution;
        /** Standard output text (`user_output` stream in Prolog) */
        stdout?: string;
        /** Standard error text (`user_error` stream in Prolog) */
        stderr?: string;
        goal?: Goal;
    }
    export interface Failure {
        status: "failure";
    }
    export interface ErrorReply {
        status: "error";
        error: Term;
    }
    /** Mapping of variable name → Term substitutions. */
    export type Substitution = Record<string, Term>;
    export type prolog_t = void;
    export type subquery_t = void;
    export type Ctrl = {
        subq: Ptr<subquery_t>;
        get subquery(): Ptr<subquery_t>;
        alive: boolean;
        stdout: (str: string) => void;
        stderr: (str: string) => void;
        answers: string[];
    };
    interface Instance extends StandardInstance {
        exports: Trealla;
    }
    interface Trealla extends ABI {
        pl_global(): Ptr<prolog_t>;
        pl_query(pl: Ptr<prolog_t>, goal: Ptr<char_t>, subqptr: Ptr<Ptr<subquery_t>>, autoyield: int_t): bool_t;
        pl_redo(pl: Ptr<prolog_t>): bool_t;
        pl_done(pl: Ptr<prolog_t>): void;
        get_status(pl: Ptr<prolog_t>): bool_t;
        get_error(pl: Ptr<prolog_t>): bool_t;
        pl_did_yield(subquery: Ptr<subquery_t>): bool_t;
        pl_yield_at(subquery: Ptr<subquery_t>, msec: int_t): void;
        pl_consult(pl: Ptr<prolog_t>, str: Ptr<char_t>): bool_t;
    }
    export interface Thunk {
        cont?: AsyncGenerator<Continuation<Goal>, Continuation<Goal>, void>;
        value?: Goal | boolean;
        done: boolean;
    }
    export interface Task {
        id: number;
        promise: Promise<Tick | undefined> | null;
        cancel: (() => void) | null;
        query: AsyncGenerator<Tick, void, undefined>;
    }
    export type Tick = {
        task_id: number;
        answer: Answer & {
            goal: Goal;
        } | undefined;
        time: number;
        depth: number;
    };
    /** Prolog interpreter instance. */
    export class Prolog {
        wasi: WASI;
        os: OS;
        fs: FS;
        instance: Instance;
        ptr: Ptr<prolog_t>;
        n: number;
        taskcount: number;
        scratch: number;
        finalizers: FinalizationRegistry<Ctrl> | undefined;
        yielding: Map<Ptr<void>, Thunk>;
        procs: Record<string, Predicate<any>>;
        tasks: Map<number, Task>;
        subqs: Map<Ptr<void>, Ctrl>;
        spawning: Map<Ptr<Ptr<void>>, Ctrl>;
        /**	Create a new Prolog interpreter instance. */
        constructor(options?: Partial<PrologOptions>);
        /**	Instantiate this interpreter. Automatically called by other methods if necessary. */
        init(): Promise<void>;
        /** Run a query. This is an asynchronous generator function.
         *  Use a `for await` loop to easily iterate through results.
         *  Exiting the loop will automatically destroy the query and reclaim memory.
         *  Call the `return()` method of the generator to kill it early if manually iterating with `next()`.
         *  Runtimes that support finalizers will make a best effort attempt to kill live but garbage-collected queries.
         **/
        query(goal: string, options?: QueryOptions): AsyncGenerator<Answer>;
        /** Runs a query and returns a single solution, ignoring others. */
        queryOnce(goal: string, options?: QueryOptions): Promise<Answer>;
        /** Consult (load) a Prolog file with the given text content.
         *	Use fs to manipulate the filesystem. */
        consult(filename: string): Promise<void>;
        /** Consult (load) Prolog text. */
        consultText(code: string | Uint8Array): Promise<void>;
        consultTextInto(code: string, module?: string): Promise<void>;
        register<G extends Goal>(pred: Predicate<G> | Predicate<Goal>[], module?: string): Promise<void>;
        registerPredicates(predicates: (Predicate<Goal>)[], module?: string): Promise<void>;
        writeScratchFile(code: string | Uint8Array): Promise<string>;
        addTask(query: AsyncGenerator<Answer & {
            goal: Goal;
        }, void, unknown>): number;
        runTask(id: number, query: AsyncGenerator<Answer & {
            goal: Goal;
        }, void, unknown>): AsyncGenerator<Tick, void, unknown>;
        tickTask(task: Task): Promise<Tick | undefined>;
        ctrl(subquery: Ptr<subquery_t>): Ctrl;
        _host_call(subquery: Ptr<subquery_t>, ptr: Ptr<char_t>, msgsize: size_t, replyptrptr: Ptr<Ptr<char_t>>, replysizeptr: size_t): HostCallReply;
        _host_resume(subquery: Ptr<subquery_t>, replyptrptr: Ptr<Ptr<char_t>>, replysizeptr: Ptr<size_t>): HostCallReply;
        _host_push_answer(subquery: Ptr<subquery_t>, ptr: Ptr<char_t>, msgsize: size_t): void;
    }
    const WASM_HOST_CALL_ERROR = 0;
    const WASM_HOST_CALL_OK = 1;
    const WASM_HOST_CALL_YIELD = 2;
    const WASM_HOST_CALL_CHOICE = 3;
    const WASM_HOST_CALL_FAIL = 4;
    type HostCallReply = typeof WASM_HOST_CALL_ERROR | typeof WASM_HOST_CALL_OK | typeof WASM_HOST_CALL_YIELD | typeof WASM_HOST_CALL_CHOICE | typeof WASM_HOST_CALL_FAIL;
}
declare module "term" {
    import { JSONEncodingOptions } from "prolog";
    export type Term = Atom | Compound<Functor, Args> | Variable | List | string | Numeric | Rational;
    export type Numeric = number | bigint;
    export type List = Term[];
    export type Functor = string;
    export type Args = [Term, ...Term[]];
    export type Goal = Atom | Compound<Functor, Args>;
    export type PredicateIndicator = Compound<"/", [Atom, number]>;
    /** Terms or objects that encode into terms. Uint8Array becomes a Prolog string. */
    export type Termlike = Term | Float | Literal | Uint8Array | {
        toProlog: () => string;
    };
    /** Prolog atom term. */
    export class Atom<Text extends string = string> {
        /** Value of the atom. */
        functor: Text;
        args: [];
        constructor(functor: Text);
        /** Value of the atom. */
        get value(): Text;
        set value(v: Text);
        get pi(): Compound<"/", [Atom<Text>, 0]>;
        toProlog(): string;
        toString(): string;
    }
    /** Template string tag for making atoms. */
    export function atom(text: TemplateStringsArray, ...values: (string | number | bigint)[]): Atom<string>;
    /** Template literal function for escaping Prolog text. `${values}` will be interpreted as Prolog terms. */
    export function prolog(text: TemplateStringsArray, ...values: Termlike[]): string;
    export function Atomic(functor: string, args: Term[]): typeof args extends Args ? Compound<typeof functor, typeof args> : Atom;
    export function Atomic(functor: string, args: []): Atom;
    /** Prolog compound term. */
    export class Compound<Functor extends string, Arguments extends Args> {
        functor: Functor;
        args: Arguments;
        constructor(functor: Functor, args: Arguments);
        get pi(): Compound<"/", [Atom<Functor>, number]>;
        toProlog(): string;
        toString(): string;
    }
    /** Prolog rational term. */
    export class Rational {
        numerator: Numeric;
        denominator: Numeric;
        constructor(numerator: Numeric, denominator: Numeric);
        toProlog(): string;
        toString(): string;
    }
    export function isAtom(x: unknown, name?: string): x is Atom;
    export function isCompound<F extends string>(x: unknown, name?: F, arity?: number): x is Compound<F, Args>;
    export function isList(x: unknown): x is List;
    export function isNumber(x: unknown): x is Numeric;
    export function isRational(x: unknown): x is Rational;
    export function isString(x: unknown): x is string;
    export function isCallable(term: unknown): term is Goal;
    export function isVariable(term: unknown): term is Variable;
    export function isTerm(term: unknown): term is Term;
    /** Prolog variable term. */
    export class Variable {
        var: string;
        attr?: Term[];
        constructor(name: string, attr?: Term[]);
        toProlog(): string;
        toString(): string;
    }
    export class Literal {
        value: string;
        constructor(value: string);
        toProlog(): string;
    }
    /** Number that will always encode to a Prolog float. */
    export class Float {
        value: number;
        constructor(value: number);
        [Symbol.toPrimitive](): number;
        toProlog(): string;
        toJSON(): number;
    }
    export function piTerm<const P extends string, const N extends number>(name: P, arity: N): Compound<'/', [Atom<P>, N]>;
    /** Converts the given term object into Prolog text. */
    export function toProlog(obj: unknown): string;
    export function escapeAtom(atom: string): string;
    export function escapeString(str: string): string;
    export function fromJSON(json: string, options?: JSONEncodingOptions): Term;
    export function toJSON(term: Term, indent: string): string;
    export function reviver(opts?: JSONEncodingOptions): (k: string, v: unknown) => {} | null | undefined;
}
declare module "interop" {
    import { Compound, Atom, Variable, Goal, Term, PredicateIndicator } from "term";
    import { Ptr } from "c";
    import { Ctrl, Prolog, subquery_t } from "prolog";
    export type PredicateFunction<G extends Goal> = (pl: Prolog, subq: Ptr<subquery_t>, goal: G, ctrl: Ctrl) => Continuation<G> | Promise<Continuation<G>> | AsyncIterable<Continuation<G>>;
    export type Continuation<G extends Goal> = G | boolean;
    export class Predicate<G extends Goal> {
        name: string;
        arity: number;
        proc: PredicateFunction<G>;
        async: boolean;
        constructor(name: string, arity: number, fn: PredicateFunction<G>, async?: boolean);
        eval(pl: Prolog, subquery: number, goal: G, ctrl: Ctrl): AsyncGenerator<any, false | Compound<"error", [Compound<"system_error", [string, Term]>, PredicateIndicator]> | Compound<"throw", [Term]>, any>;
        shim(): string;
        get pi(): Compound<"/", [Atom<string>, number]>;
    }
    type PromiseTerm = Compound<"$promise", [number, Goal]>;
    export const sleep_1: Predicate<Compound<"sleep", [number]>>;
    export const delay_1: Predicate<Compound<"delay", [number]>>;
    export const console_log_1: Predicate<Compound<"console_log", [string]>>;
    export const js_eval_2: Predicate<Compound<"js_eval", [string, Term]>>;
    export const js_eval_json_2: Predicate<Compound<"js_eval_json", [string, Term]>>;
    export const future_2: Predicate<Compound<"future", [Goal, PromiseTerm]>>;
    export const sys_await_1: Predicate<Compound<"$await", [PromiseTerm]>>;
    export const await_any_3: Predicate<Compound<"await_any", [PromiseTerm[], Variable | PromiseTerm, Variable | PromiseTerm[]]>>;
    export const future_cancel_1: Predicate<Compound<string, [PromiseTerm]>>;
    export const sys_await_all_1: Predicate<Compound<string, [PromiseTerm[]]>>;
    export const sys_await_some_3: Predicate<Compound<string, [PromiseTerm[], Variable | PromiseTerm[], PromiseTerm[]]>>;
    export function sys_missing_n(_pl: Prolog, _subq: Ptr<subquery_t>, goal: Goal): void;
    export function throwTerm(ball: Term): Compound<"throw", [Term]>;
    export function type_error(type: string, value: Term, context: PredicateIndicator): Compound<"error", [Compound<"type_error", [string, Term]>, PredicateIndicator]>;
    export function domain_error(type: string, value: Term, context: PredicateIndicator): Compound<"error", [Compound<"domain_error", [string, Term]>, PredicateIndicator]>;
    export function existence_error(type: string, value: Term, context: PredicateIndicator): Compound<"error", [Compound<"existence_error", [string, Term]>, PredicateIndicator]>;
    export function system_error(type: string, value: Term, context: PredicateIndicator): Compound<"error", [Compound<"system_error", [string, Term]>, PredicateIndicator]>;
    export const LIBRARY: Predicate<any>[];
}
declare module "trealla" {
    export * from "prolog";
    export * from "toplevel";
    export * from "term";
    export * from "interop";
    export * from "fs";
}
//# sourceMappingURL=index.d.ts.map