trealla-multibundle
Version:
Trealla Prolog bindings for JS
470 lines • 21.6 kB
TypeScript
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