UNPKG

trealla-multibundle

Version:

Trealla Prolog bindings for JS

470 lines 21.6 kB
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