UNPKG

@dialog-db/query

Version:

Datalog query engine inspired by Datomic

521 lines 20.6 kB
export { $ }; export function select(selector: API.Select): Select; export function rule<Match extends API.Proposition>(source: API.DeductiveRule<Match>): DeductiveRule<Match>; export function formula<Operator extends API.SystemOperator["operator"]>(operator: Operator): Formula<API.SystemOperator & { operator: Operator; }>; export function recur<Match extends API.Proposition = API.Proposition>(terms: API.RuleBindings<Match>): RuleRecursion<Match>; export function from(source: API.Conjunct | API.Recur): Select | FormulaApplication | Negation | RuleApplication<any> | RuleRecursion<any>; /** * @template {API.Proposition} [Match=API.Proposition] * @implements {API.MatchRule<Match>} * @implements {API.RuleApplicationSyntax<Match>} */ export class RuleApplication<Match extends API.Proposition = API.Proposition> implements API.MatchRule<Match>, API.RuleApplicationSyntax<Match> { /** * @template {API.Proposition} [Match=API.Proposition] * @param {API.MatchRule<Match>} source * @returns {RuleApplication<Match>} */ static from<Match_1 extends API.Proposition = API.Proposition>(source: API.MatchRule<Match_1>): RuleApplication<Match_1>; /** * Creates a rule application with a given `rule` and set of `terms`. * * @template {API.Proposition} Match * @param {DeductiveRule<Match>} rule * @param {Partial<API.RuleBindings<Match>>} terms */ static "new"<Match_1 extends API.Proposition>(rule: DeductiveRule<Match_1>, terms: Partial<API.RuleBindings<Match_1>>): RuleApplication<Match_1>; /** * @param {Partial<API.RuleBindings<Match>> & {}} match * @param {DeductiveRule<Match>} rule * @param {API.Cursor} references * @param {API.MatchFrame} bindings * @param {Map<API.Variable, number>} cells */ constructor(match: Partial<API.RuleBindings<Match>> & {}, rule: DeductiveRule<Match>, references?: API.Cursor, bindings?: API.MatchFrame, cells?: Map<API.Variable, number>); match: Partial<API.RuleBindings<Match>>; rule: DeductiveRule<Match>; /** * Mapping between variables inside the rule and variables that they were * bound to via rule application. Given below example we will have mapping * `$.name → $.q`. * * ```js * { * match: { name: $.q }, * rule: { * match: { name: $.name }, * when: { * where: [{ match: { the: "person/name", is: $.name } }] * } * } * } * ``` */ references: API.Cursor; /** * Mapping between variables inside the rule and constants that they were * bound to via rule application. Given below example we will have a mapping * `$.name → "Irakli"`. * * ```js * { * match: { name: "Irakli", address: $.q }, * rule: { * match: { name: $.name, $.address }, * when: { * where: [ * { match: { the: "person/name", of: $.person, is: $.name } }, * { match: { the: "person/address", of: $.person, is: $.address } } * ] * } * } * } * ``` */ bindings: API.MatchFrame; /** * Mapping between variables that were bound in the application and the * cost estimate for them staying unbound. */ cells: Map<API.Variable<API.Scalar>, number>; get recurs(): null; /** * Base cost of the rule application is the base cost of the rule itself. */ get cost(): number; /** * Plans the rule execution in the given scope. `RuleApplication` links rule * variables (`this.rule.match`) to the variables passed in an application * (`this.match`). However rule application itself may be nested inside some * rule where terms (`this.match`) gets linked in this planning phase. * * @param {API.Scope} scope */ plan(scope: API.Scope): Plan.RuleApplication<Match>; prepare(): API.RuleApplicationPlan<Match>; /** * Runs this rule application as a query in on a given `input`. * * @param {object} input * @param {API.Querier} input.from */ query(input: { from: API.Querier; }): API.Task<API.MatchFrame[], Error, typeof import("./task.js").SUSPEND | import("./task.js").Join | import("./task.js").Throw<Error>>; toDebugString(): string; toJSON(): { match: object | API.Scalar; rule: { match: object | API.Scalar; when: { [k: string]: Conjunct[]; }; }; }; negate(): Negation; #private; } /** * @template {API.Proposition} [Match=API.Proposition] * @implements {API.DeductiveRuleSyntax<Match>} */ export class DeductiveRule<Match extends API.Proposition = API.Proposition> implements API.DeductiveRuleSyntax<Match> { /** * @template {API.Proposition} Case * @param {API.DeductiveRule<Case>} source */ static from<Case extends API.Proposition>(source: API.DeductiveRule<Case>): DeductiveRule<Case>; /** * @param {Match} match - Pattern to match against * @param {Map<API.Variable, number>} cells - Cost per variable when not bound * @param {number} cost - Base execution cost * @param {boolean} recurs * @param {Record<string, Join>} when - Named deductive branches that must be evaluated */ constructor(match: Match, cells: Map<API.Variable, number>, cost: number, recurs: boolean, when: Record<string, Join>); match: Match; cells: Map<API.Variable<API.Scalar>, number>; cost: number; recurs: boolean; when: Record<string, Join>; /** * @param {API.RuleBindings<Match>} terms * @returns {RuleApplication<Match>} */ apply(terms?: API.RuleBindings<Match>): RuleApplication<Match>; /** * @param {API.Scope} application */ plan(application: API.Scope): Plan.DeductiveRule<Match>; toDebugString(): string; toJSON(): { match: object | API.Scalar; when: { [k: string]: Conjunct[]; }; }; } /** * @template {API.Proposition} [Match=API.Proposition] * @implements {API.RuleRecursionSyntax<Match>} */ export class RuleRecursion<Match extends API.Proposition = API.Proposition> implements API.RuleRecursionSyntax<Match> { /** * @template {API.Proposition} [Match=API.Proposition] * @param {API.Recur<Match>} source */ static from<Match_1 extends API.Proposition = API.Proposition>({ recur: terms }: API.Recur<Match_1>): RuleRecursion<Match_1>; /** * @param {API.RuleBindings<Match>} terms * @param {Map<API.Variable, number>} cells */ constructor(terms: API.RuleBindings<Match>, cells: Map<API.Variable, number>); get recurs(): this; get references(): Map<any, any>; terms: API.RuleBindings<Match>; cells: Map<API.Variable<API.Scalar>, number>; get recur(): API.RuleBindings<Match>; get cost(): number; /** * @param {API.Scope} scope */ plan(scope: API.Scope): this; toJSON(): { recur: API.RuleBindings<Match>; }; toDebugString(): string; /** * Instead of direct recursion, we collect bindings to be processed later * in a breadth-first fixed-point iteration. * * @param {API.EvaluationContext} context */ evaluate({ self, selection, recur }: API.EvaluationContext): Generator<never, never[], unknown>; } /** * @implements {API.Every<API.Conjunct|API.Recur>} */ export class Join implements API.Every<API.Conjunct | API.Recur> { /** * @param {object} source * @param {Map<string, API.Variable>} source.bindings * @param {string} source.name * @param {API.Every<API.Conjunct|API.Recur>} source.conjuncts * @param {Set<API.Variable>} [source.variables] */ static from({ bindings, name, conjuncts: forms, variables, }: { bindings: Map<string, API.Variable>; name: string; conjuncts: API.Every<API.Conjunct | API.Recur>; variables?: Set<API.Variable<API.Scalar>> | undefined; }): Join; /** * Ensures that given bindings are referenced from inside this join. Throws * a `ReferenceError` if there is a binding that is not referenced. The reason * if rule contains binding that is not used is in it's body it will either * not get bound or will not contribute to the rule in both cases rule is * likely not captures intended logic. Note that it theory rule may use some * variables only in some logic branches in which case those variables could * be considered as required input, but even then it is indicative of bad rule * design which could be broken apart into multiple rules which is why we * choose to error on side of caution. It is also always possible to consume * variable in cases where it really isn't needed. * * @param {Map<API.Variable, number>} cells * @param {Map<string, API.Variable>} bindings * @param {string} name */ static ensureBindings(cells: Map<API.Variable, number>, bindings: Map<string, API.Variable>, name: string): typeof Join; /** * @param {Conjunct[]} conjuncts * @param {Map<API.Variable, number>} cells * @param {number} cost * @param {boolean} recurs * @param {string} name */ constructor(conjuncts: Conjunct[], cells: Map<API.Variable, number>, cost: number, recurs: boolean, name: string); conjuncts: Conjunct[]; cells: Map<API.Variable<API.Scalar>, number>; cost: number; name: string; recurs: boolean; /** * @param {API.Scope} scope * @returns {Plan.Join} */ plan(scope: API.Scope): Plan.Join; toJSON(): Conjunct[]; toDebugString(): string; /** * @returns {IterableIterator<API.Conjunct|API.Recur>} */ [Symbol.iterator](): IterableIterator<API.Conjunct | API.Recur>; } /** * @typedef {Select|FormulaApplication|RuleApplication} Constraint * @typedef {Select|FormulaApplication|RuleApplication|Negation|RuleRecursion} Conjunct * @implements {API.NegationSyntax} */ export class Negation implements API.NegationSyntax { /** * @param {API.Negation} source * @returns {Negation} */ static from({ not: constraint }: API.Negation): Negation; /** * @param {Constraint} constraint */ static "new"(constraint: Constraint): Negation; /** * @param {Constraint} constraint * @param {Map<API.Variable, number>} cells */ constructor(constraint: Constraint, cells: Map<API.Variable, number>); get recurs(): null; constraint: Constraint; cells: Map<API.Variable<API.Scalar>, number>; get references(): API.Cursor | Map<any, any>; get not(): API.Constraint; get cost(): number; /** * @param {API.Scope} scope * @returns {Plan.Negation} */ plan(scope: API.Scope): Plan.Negation; toJSON(): { not: { match: API.Select; } | { match: API.FormulaMatch<{ of: API.Numeric; by: API.Numeric; }, API.Numeric> | API.FormulaMatch<{ of: API.Numeric; by: API.Numeric; }, API.Numeric> | API.FormulaMatch<{ of: API.Numeric; by: API.Numeric; }, API.Numeric> | API.FormulaMatch<{ of: API.Numeric; with: API.Numeric; }, API.Numeric> | API.FormulaMatch<{ this: string | number; than: string | number; }, {}> | API.FormulaMatch<boolean, boolean> | API.FormulaMatch<{ this: string | number; than: string | number; }, {}> | API.FormulaMatch<{ this: string | number; than: string | number; }, {}> | API.FormulaMatch<{ this: string | number; than: string | number; }, {}> | API.FormulaMatch<API.Scalar, API.TypeName> | API.FormulaMatch<Record<string, API.Scalar>, API.Link<Record<string, API.Scalar>, 113, 30>> | API.FormulaMatch<{ text: string; pattern: string; }, string> | API.FormulaMatch<string, number> | API.FormulaMatch<string, string> | API.FormulaMatch<Uint8Array<ArrayBufferLike>, string> | API.FormulaMatch<string, Uint8Array<ArrayBufferLike>> | API.FormulaMatch<{ this: string; slice: string; }, true> | API.FormulaMatch<{ of: string; start: string; end: string; }, string> | API.FormulaMatch<{ of: string; with: string; }, string> | API.FormulaMatch<{ of: API.Numeric; by: API.Numeric; }, API.Numeric> | API.FormulaMatch<{ of: API.Numeric; by: API.Numeric; }, number> | API.FormulaMatch<number, number> | API.FormulaMatch<API.Scalar, API.Scalar>; operator: "/" | "*" | "%" | "+" | "<" | "!" | "==" | ">" | ">=" | "<=" | "data/type" | "data/refer" | "text/like" | "text/length" | "text/words" | "text/lines" | "text/case/upper" | "text/case/lower" | "text/trim" | "text/trim/start" | "text/trim/end" | "utf8/to/text" | "text/to/utf8" | "text/includes" | "text/slice" | "text/concat" | "-" | "**" | "math/absolute"; } | { match: object | API.Scalar; rule: { match: object | API.Scalar; when: { [k: string]: Conjunct[]; }; }; }; }; toDebugString(): string; } export type Constraint = Select | FormulaApplication | RuleApplication; export type Conjunct = Select | FormulaApplication | RuleApplication | Negation | RuleRecursion; import { $ } from './$.js'; import * as API from './api.js'; /** * @implements {API.SelectForm} * @implements {API.SelectSyntax} */ declare class Select implements API.SelectForm, API.SelectSyntax { /** * @param {API.SelectForm} source */ static from({ match }: API.SelectForm): Select; /** * @param {API.Select} selector * @param {Map<API.Variable, number>} cells */ constructor(selector: API.Select, cells: Map<API.Variable, number>); cells: Map<API.Variable<API.Scalar>, number>; selector: API.Select; get references(): Map<any, any>; get recurs(): null; get match(): API.Select; /** * Base execution cost of the select operation. */ get cost(): number; /** * * @param {API.Scope} scope */ plan({ references, bindings }: API.Scope): Plan.Select; toJSON(): { match: API.Select; }; toDebugString(): string; } /** * @template {API.SystemOperator} Operator */ declare class Formula<Operator extends API.SystemOperator> { /** * * @param {Operator['operator']} operator */ constructor(operator: Operator["operator"]); operator: Operator["operator"]; /** * @param {Operator['match']} terms */ apply(terms: Operator["match"]): FormulaApplication; } declare class FormulaApplication { /** * @param {API.SystemOperator} source */ static from(source: API.SystemOperator): FormulaApplication; /** * @param {API.SystemOperator} source * @param {Map<API.Variable, number>} cells * @param {Record<string, API.Term>|API.Term} from * @param {Record<string, API.Term>} to */ constructor(source: API.SystemOperator, cells: Map<API.Variable, number>, from: Record<string, API.Term> | API.Term, to: Record<string, API.Term>); cells: Map<API.Variable<API.Scalar>, number>; source: API.SystemOperator; from: API.Term<API.Scalar> | Record<string, API.Term<API.Scalar>>; to: Record<string, API.Term<API.Scalar>>; get references(): Map<any, any>; get match(): API.FormulaMatch<{ of: API.Numeric; by: API.Numeric; }, API.Numeric> | API.FormulaMatch<{ of: API.Numeric; by: API.Numeric; }, API.Numeric> | API.FormulaMatch<{ of: API.Numeric; by: API.Numeric; }, API.Numeric> | API.FormulaMatch<{ of: API.Numeric; with: API.Numeric; }, API.Numeric> | API.FormulaMatch<{ this: string | number; than: string | number; }, {}> | API.FormulaMatch<boolean, boolean> | API.FormulaMatch<API.Scalar, API.Scalar> | API.FormulaMatch<{ this: string | number; than: string | number; }, {}> | API.FormulaMatch<{ this: string | number; than: string | number; }, {}> | API.FormulaMatch<{ this: string | number; than: string | number; }, {}> | API.FormulaMatch<API.Scalar, API.TypeName> | API.FormulaMatch<Record<string, API.Scalar>, API.Link<Record<string, API.Scalar>, 113, 30>> | API.FormulaMatch<{ text: string; pattern: string; }, string> | API.FormulaMatch<string, number> | API.FormulaMatch<string, string> | API.FormulaMatch<Uint8Array<ArrayBufferLike>, string> | API.FormulaMatch<string, Uint8Array<ArrayBufferLike>> | API.FormulaMatch<{ this: string; slice: string; }, true> | API.FormulaMatch<{ of: string; start: string; end: string; }, string> | API.FormulaMatch<{ of: string; with: string; }, string> | API.FormulaMatch<{ of: API.Numeric; by: API.Numeric; }, API.Numeric> | API.FormulaMatch<{ of: API.Numeric; by: API.Numeric; }, number> | API.FormulaMatch<number, number>; get operator(): "/" | "*" | "%" | "+" | "<" | "!" | "==" | ">" | ">=" | "<=" | "data/type" | "data/refer" | "text/like" | "text/length" | "text/words" | "text/lines" | "text/case/upper" | "text/case/lower" | "text/trim" | "text/trim/start" | "text/trim/end" | "utf8/to/text" | "text/to/utf8" | "text/includes" | "text/slice" | "text/concat" | "-" | "**" | "math/absolute"; get recurs(): null; /** * Base execution cost of the formula application operation. */ get cost(): number; /** * @param {API.Scope} scope */ plan(scope: API.Scope): Plan.FormulaApplication; toJSON(): { match: API.FormulaMatch<{ of: API.Numeric; by: API.Numeric; }, API.Numeric> | API.FormulaMatch<{ of: API.Numeric; by: API.Numeric; }, API.Numeric> | API.FormulaMatch<{ of: API.Numeric; by: API.Numeric; }, API.Numeric> | API.FormulaMatch<{ of: API.Numeric; with: API.Numeric; }, API.Numeric> | API.FormulaMatch<{ this: string | number; than: string | number; }, {}> | API.FormulaMatch<boolean, boolean> | API.FormulaMatch<API.Scalar, API.Scalar> | API.FormulaMatch<{ this: string | number; than: string | number; }, {}> | API.FormulaMatch<{ this: string | number; than: string | number; }, {}> | API.FormulaMatch<{ this: string | number; than: string | number; }, {}> | API.FormulaMatch<API.Scalar, API.TypeName> | API.FormulaMatch<Record<string, API.Scalar>, API.Link<Record<string, API.Scalar>, 113, 30>> | API.FormulaMatch<{ text: string; pattern: string; }, string> | API.FormulaMatch<string, number> | API.FormulaMatch<string, string> | API.FormulaMatch<Uint8Array<ArrayBufferLike>, string> | API.FormulaMatch<string, Uint8Array<ArrayBufferLike>> | API.FormulaMatch<{ this: string; slice: string; }, true> | API.FormulaMatch<{ of: string; start: string; end: string; }, string> | API.FormulaMatch<{ of: string; with: string; }, string> | API.FormulaMatch<{ of: API.Numeric; by: API.Numeric; }, API.Numeric> | API.FormulaMatch<{ of: API.Numeric; by: API.Numeric; }, number> | API.FormulaMatch<number, number>; operator: "/" | "*" | "%" | "+" | "<" | "!" | "==" | ">" | ">=" | "<=" | "data/type" | "data/refer" | "text/like" | "text/length" | "text/words" | "text/lines" | "text/case/upper" | "text/case/lower" | "text/trim" | "text/trim/start" | "text/trim/end" | "utf8/to/text" | "text/to/utf8" | "text/includes" | "text/slice" | "text/concat" | "-" | "**" | "math/absolute"; }; toDebugString(): string; } import * as Plan from './plan.js'; //# sourceMappingURL=syntax.d.ts.map