@formaui-net/nexo 0.0.0 → 1.0.0-preview.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +2 -0
- package/README.md +148 -6
- package/package.json +23 -3
- package/src/common/ArrayUtils.mjs +16 -0
- package/src/common/ObjectUtils.mjs +33 -0
- package/src/language/DefinitionLocations.mjs +41 -0
- package/src/language/DefinitionValidator.mjs +1265 -0
- package/src/language/DefinitionWriter.mjs +475 -0
- package/src/language/Dictionary.mjs +52 -0
- package/src/language/Evaluator.mjs +3480 -0
- package/src/language/ImportedVocabulary.mjs +137 -0
- package/src/language/Imports.mjs +141 -0
- package/src/language/Index.mjs +29 -0
- package/src/language/LanguageResolver.mjs +4068 -0
- package/src/language/Limits.mjs +78 -0
- package/src/language/LineStructure.mjs +385 -0
- package/src/language/Lowering.mjs +453 -0
- package/src/language/MemberSelector.mjs +89 -0
- package/src/language/Names.mjs +65 -0
- package/src/language/NexoError.mjs +145 -0
- package/src/language/Pair.mjs +21 -0
- package/src/language/ParameterBindings.mjs +361 -0
- package/src/language/ParsedTexts.mjs +62 -0
- package/src/language/Parser.mjs +1817 -0
- package/src/language/Range.mjs +51 -0
- package/src/language/RecentlyUsed.mjs +50 -0
- package/src/language/ResolvedDefinition.mjs +219 -0
- package/src/language/ResultPath.mjs +101 -0
- package/src/language/ScopeLocals.mjs +102 -0
- package/src/language/StructureTypes.mjs +48 -0
- package/src/language/SyntaxTree.mjs +203 -0
- package/src/language/TextLocations.mjs +185 -0
- package/src/language/TextPositions.mjs +23 -0
- package/src/language/Tokenizer.mjs +917 -0
- package/src/language/Type.mjs +401 -0
- package/src/language/TypeChecker.mjs +449 -0
- package/src/language/ValueCapture.mjs +315 -0
- package/src/language/Versions.mjs +14 -0
- package/src/language/vocabulary/Declarations.mjs +64 -0
- package/src/language/vocabulary/ItemPositions.mjs +48 -0
- package/src/language/vocabulary/ListOrdering.mjs +145 -0
- package/src/language/vocabulary/MemberFailure.mjs +21 -0
- package/src/language/vocabulary/NexoModule.mjs +1119 -0
- package/src/language/vocabulary/NexoRegistry.mjs +1540 -0
- package/src/language/vocabulary/TypeNameScope.mjs +63 -0
- package/src/language/vocabulary/Vocabulary.mjs +640 -0
- package/src/nexo.d.ts +743 -0
- package/src/nexo.js +338 -0
package/src/nexo.d.ts
ADDED
|
@@ -0,0 +1,743 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nexo's API: reading a text into its definition, validating a definition's structure, writing its canonical text, creating the modules that declare a vocabulary
|
|
3
|
+
* and the registries a host resolves scripts against.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** A script as a host gives it: its source, the text read into its definition, or the definition itself. */
|
|
7
|
+
export type NexoScript = string | NexoDefinition;
|
|
8
|
+
|
|
9
|
+
/** A Nexo definition: the JSON document that records a script's meaning, its expression tree with the version of its format and its imports, without the values its script parameters are bound to. */
|
|
10
|
+
export interface NexoDefinition {
|
|
11
|
+
readonly version: number;
|
|
12
|
+
/** The script's imports, those its text writes and those its host supplies, each once, in order of the local name it gives. */
|
|
13
|
+
readonly imports: readonly NexoImport[];
|
|
14
|
+
readonly expression: NexoDefinitionNode;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** An import, as a definition records it: its registered module, the local name of the one type it imports where it imports one, and its alias where it gives a local name other than its own. */
|
|
18
|
+
export interface NexoImport {
|
|
19
|
+
readonly module: string;
|
|
20
|
+
readonly type?: string;
|
|
21
|
+
readonly alias?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** An import a host supplies: a module's name, imported under its own, or an import as a definition records it. */
|
|
25
|
+
export type NexoSuppliedImport = string | NexoImport;
|
|
26
|
+
|
|
27
|
+
/** The options of reading or writing a script: the imports the host, or the text's destination, supplies. */
|
|
28
|
+
export interface NexoScriptOptions {
|
|
29
|
+
readonly imports?: readonly NexoSuppliedImport[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* A property access, the member a call names, or a named indexer's name: its receiver, its name or a computed property access's expression, and whether it is optional; an extension access's first name holds
|
|
34
|
+
* `extension`, and each later name `continues`, which resolution reads as the access's member, its extension, that extension's module, or an ordinary access of the member's answer.
|
|
35
|
+
*/
|
|
36
|
+
export interface NexoDefinitionMemberAccess {
|
|
37
|
+
readonly kind: 'memberAccess';
|
|
38
|
+
readonly receiver: NexoDefinitionNode;
|
|
39
|
+
readonly name: string | NexoDefinitionNode;
|
|
40
|
+
readonly optional?: true;
|
|
41
|
+
readonly extension?: true;
|
|
42
|
+
readonly continues?: true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** A node of a definition. */
|
|
46
|
+
export type NexoDefinitionNode =
|
|
47
|
+
| { readonly kind: 'literal'; readonly value: string | number | boolean | null }
|
|
48
|
+
| { readonly kind: 'scriptParameter'; readonly name: string }
|
|
49
|
+
| { readonly kind: 'it' }
|
|
50
|
+
| { readonly kind: 'root' }
|
|
51
|
+
/** A module's namespace, by the local name the script's imports give it, the receiver of a member read or called through it alone. */
|
|
52
|
+
| { readonly kind: 'namespace'; readonly name: string }
|
|
53
|
+
| { readonly kind: 'local'; readonly name: string }
|
|
54
|
+
| NexoDefinitionMemberAccess
|
|
55
|
+
/** A call: of the member its callee names, or of the function the local its callee names holds. */
|
|
56
|
+
| { readonly kind: 'call'; readonly callee: NexoDefinitionMemberAccess | { readonly kind: 'local'; readonly name: string }; readonly arguments: readonly NexoDefinitionNode[] }
|
|
57
|
+
| { readonly kind: 'indexerAccess'; readonly receiver: NexoDefinitionNode; readonly argument: NexoDefinitionNode; readonly optional?: true }
|
|
58
|
+
| { readonly kind: 'object'; readonly context?: NexoDefinitionNode; readonly locals?: readonly NexoDefinitionLocal[]; readonly objectFields: readonly NexoDefinitionObjectField[] }
|
|
59
|
+
/** A list a collection expression writes: its items in order. */
|
|
60
|
+
| { readonly kind: 'list'; readonly items: readonly NexoDefinitionNode[] }
|
|
61
|
+
/** A dictionary a collection expression writes: its entries in the order written, each its key's string and its value, no two of one key. */
|
|
62
|
+
| { readonly kind: 'dictionary'; readonly entries: readonly { readonly key: string; readonly value: NexoDefinitionNode }[] }
|
|
63
|
+
| { readonly kind: 'optionalChain'; readonly chain: NexoDefinitionNode }
|
|
64
|
+
| { readonly kind: 'coalescing'; readonly value: NexoDefinitionNode; readonly fallback: NexoDefinitionNode }
|
|
65
|
+
| { readonly kind: 'not'; readonly operand: NexoDefinitionNode }
|
|
66
|
+
| { readonly kind: 'function'; readonly parameters: readonly string[]; readonly body: NexoDefinitionNode; readonly arrow?: true }
|
|
67
|
+
| { readonly kind: 'body'; readonly locals: readonly NexoDefinitionLocal[]; readonly result: NexoDefinitionNode }
|
|
68
|
+
| { readonly kind: 'do'; readonly body: NexoDefinitionNode }
|
|
69
|
+
| { readonly kind: 'interpolatedString'; readonly parts: readonly ({ readonly kind: 'text'; readonly value: string } | { readonly kind: 'expression'; readonly expression: NexoDefinitionNode })[] }
|
|
70
|
+
| { readonly kind: 'comparison'; readonly operands: readonly NexoDefinitionNode[]; readonly operators: readonly ('<' | '<=' | '>' | '>=')[] }
|
|
71
|
+
| { readonly kind: 'arithmetic'; readonly operator: '+' | '-' | '*' | '/' | '%'; readonly left: NexoDefinitionNode; readonly right: NexoDefinitionNode }
|
|
72
|
+
| { readonly kind: 'arithmeticNegation'; readonly operand: NexoDefinitionNode }
|
|
73
|
+
| { readonly kind: 'fromEndIndex'; readonly offset: NexoDefinitionNode }
|
|
74
|
+
| { readonly kind: 'range'; readonly start?: NexoDefinitionNode; readonly end?: NexoDefinitionNode }
|
|
75
|
+
| { readonly kind: 'cast'; readonly type: string; readonly operand: NexoDefinitionNode }
|
|
76
|
+
| { readonly kind: 'conversion'; readonly type: string; readonly operand: NexoDefinitionNode }
|
|
77
|
+
| { readonly kind: 'try'; readonly operand: NexoDefinitionNode }
|
|
78
|
+
| { readonly kind: 'equality'; readonly left: NexoDefinitionNode; readonly right: NexoDefinitionNode }
|
|
79
|
+
| { readonly kind: 'conditional'; readonly condition?: NexoDefinitionNode; readonly binding?: { readonly name: string; readonly value: NexoDefinitionNode }; readonly consequent: NexoDefinitionNode; readonly alternative: NexoDefinitionNode }
|
|
80
|
+
| { readonly kind: 'and' | 'or'; readonly operands: readonly NexoDefinitionNode[] };
|
|
81
|
+
|
|
82
|
+
/** A local of a body or an object expression: its name, which a `local` node uses, and the value it names, never output. */
|
|
83
|
+
export interface NexoDefinitionLocal {
|
|
84
|
+
readonly name: string;
|
|
85
|
+
readonly value: NexoDefinitionNode;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** An object field of an object expression: its name, always written, and its value. */
|
|
89
|
+
export interface NexoDefinitionObjectField {
|
|
90
|
+
readonly name: string;
|
|
91
|
+
readonly value: NexoDefinitionNode;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** The values supplied by parameter name, each typed from the value itself. */
|
|
95
|
+
export interface NexoBindingValues {
|
|
96
|
+
[name: string]: unknown;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Bindings as a registry's `createBindings` creates them, the registry's own: data a frozen copy of the data given, or of what its declared type captures of it, each reference itself, and the resolution key that says which resolutions they may reuse. */
|
|
100
|
+
export interface NexoBindings {
|
|
101
|
+
/** Each binding's type by its qualified identity, with each primitive binding's value, which a resolution is reused with. */
|
|
102
|
+
readonly resolutionKey: string;
|
|
103
|
+
/** Whether a value is bound to the name. */
|
|
104
|
+
has(name: string): boolean;
|
|
105
|
+
/** Reads the value bound to the name: data as a frozen copy, a reference as itself. */
|
|
106
|
+
readValue(name: string): unknown;
|
|
107
|
+
/** The type the value bound to the name gives it, or its host declared for it, in type notation, as `List<Number?>`. */
|
|
108
|
+
getType(name: string): string | undefined;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** How a registry binds values: the type declared for a top-level binding, by its name, a notation whose names are unqualified or qualified by their module, in place of typing its value by itself. */
|
|
112
|
+
export interface NexoBindingsOptions {
|
|
113
|
+
/**
|
|
114
|
+
* The type declared for a top-level binding, by the binding's name: a notation, its names unqualified or qualified, read against the registry. A reference type's value belongs to it; any other type captures the
|
|
115
|
+
* value as a value a host call supplies is captured, as `{ routes: 'List<Input.Route>' }` does.
|
|
116
|
+
*/
|
|
117
|
+
types?: Record<string, string>;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** A reference type a module declares: its name, the supertype it names, whether it is abstract, the modules whose types its declaration names unqualified, its own members included, the membership a value of it passes, and its own members. */
|
|
121
|
+
export interface NexoReferenceTypeDeclaration {
|
|
122
|
+
name: string;
|
|
123
|
+
kind: 'reference';
|
|
124
|
+
/** Whether the value belongs to the type, answered synchronously, changing nothing. */
|
|
125
|
+
isInstance(value: unknown): boolean;
|
|
126
|
+
supertype?: string;
|
|
127
|
+
abstract?: boolean;
|
|
128
|
+
import?: string[];
|
|
129
|
+
/** The members it declares within it, each taking it as its receiver, and its operators. */
|
|
130
|
+
members?: (NexoMemberDeclaration | NexoOperatorDeclaration)[];
|
|
131
|
+
/** Whether it is available within its declaring module alone, `false` where left out: no other module's declaration names it, and no script reaches it; its members are internal with it. */
|
|
132
|
+
internal?: boolean;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** A structured type a module declares, a type of immutable data: its name, the modules whose types its declaration names unqualified, its own members included, and its own members, its data shape among them. */
|
|
136
|
+
export interface NexoStructuredTypeDeclaration {
|
|
137
|
+
name: string;
|
|
138
|
+
kind: 'structured';
|
|
139
|
+
import?: string[];
|
|
140
|
+
/**
|
|
141
|
+
* The members it declares within it, each taking it as its receiver: its data shape is the properties it declares without `updates`, each naming its value's type as its `result`, which
|
|
142
|
+
* Nexo reads from the data and never invokes, so each takes no `impl`; and its operators.
|
|
143
|
+
*/
|
|
144
|
+
members?: (NexoMemberDeclaration | NexoOperatorDeclaration)[];
|
|
145
|
+
/** Whether it is available within its declaring module alone, `false` where left out: no other module's declaration names it, and no script reaches it; its members are internal with it. */
|
|
146
|
+
internal?: boolean;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* An extension a module declares among its types: the members it adds to its one target, a type another module owns, one of Nexo's own or a parameter it declares, which its members take as their receiver. It is
|
|
151
|
+
* never a value's type.
|
|
152
|
+
*/
|
|
153
|
+
export interface NexoExtensionDeclaration {
|
|
154
|
+
/** Its local name, and the type parameters its target and its members share, `ListExtensions<T>`. */
|
|
155
|
+
name: string;
|
|
156
|
+
kind: 'extension';
|
|
157
|
+
/** The type its members extend, never `Any` or nullable: a foreign type qualified, one of Nexo's own, or a parameter it declares. */
|
|
158
|
+
target: string;
|
|
159
|
+
/** The members it adds, each taking its target as its receiver, and its operators. */
|
|
160
|
+
members?: (NexoMemberDeclaration | NexoOperatorDeclaration)[];
|
|
161
|
+
/** Whether it is available within its declaring module alone, `false` where left out; its members are internal with it. */
|
|
162
|
+
internal?: boolean;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** A type a module declares, of the kind it says, or an extension it declares among its types. */
|
|
166
|
+
export type NexoTypeDeclaration = NexoReferenceTypeDeclaration | NexoStructuredTypeDeclaration | NexoExtensionDeclaration;
|
|
167
|
+
|
|
168
|
+
/** The input a projection was given for an item, of the kind its established type gives it: a reference as the host holds it, data as Nexo's own frozen copy, or null; a source and a provenance entry alike. */
|
|
169
|
+
export type NexoProjectionSource = { readonly kind: 'reference'; readonly value: unknown } | { readonly kind: 'data'; readonly value: unknown } | { readonly kind: 'null' };
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Where something stands, by one group of attributes, never two: in a script, `pointer`, a JSON Pointer into its definition, with `offset`, `line` and `column` where the definition was read from text, and those three
|
|
173
|
+
* alone for a syntax error, which stands in text no definition holds yet; in a module, `module`, with `type` where it concerns a declaration nested in a type, `declaration` where it concerns a declaration, and `declarationKey`, the key it concerns, a declaration's or, with no
|
|
174
|
+
* declaration, the module's own; or in the bindings, `binding`. A failure of the API's use that stands nowhere, as bindings another registry made, holds none. `getLocation` answers the script group; an error, any one.
|
|
175
|
+
*/
|
|
176
|
+
export interface NexoLocation {
|
|
177
|
+
/** The node's JSON Pointer into the definition. */
|
|
178
|
+
pointer?: string;
|
|
179
|
+
offset?: number;
|
|
180
|
+
line?: number;
|
|
181
|
+
column?: number;
|
|
182
|
+
binding?: string;
|
|
183
|
+
module?: string;
|
|
184
|
+
/** The type a declaration nested in it stands in, a member a type declares within it. */
|
|
185
|
+
type?: string;
|
|
186
|
+
declaration?: string;
|
|
187
|
+
/** The key it concerns, a declaration's, as `updates.misses`, or the module's own. */
|
|
188
|
+
declarationKey?: string;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** A failure of Nexo, in the stage it happened in, and where. Its `name` is `NexoError`. */
|
|
192
|
+
export declare class NexoError extends Error {
|
|
193
|
+
private constructor();
|
|
194
|
+
readonly name: 'NexoError';
|
|
195
|
+
/** The code of the condition that failed: `NEXO` and four digits for Nexo's own, in its kind's range, and a host's own prefix for a host's. */
|
|
196
|
+
readonly code: string;
|
|
197
|
+
/** The kind of the failure: `syntax`, text that breaks the grammar; `structure`, what a caller gave breaking a structural rule, a definition `nexo.validate` refuses among it; `validation`, a script resolution finds does not fit its vocabulary or its types; `module`, a declaration breaking its contract; `evaluation`, a failure while evaluating. */
|
|
198
|
+
readonly kind: 'syntax' | 'structure' | 'validation' | 'module' | 'evaluation';
|
|
199
|
+
readonly location: NexoLocation;
|
|
200
|
+
/** A failure of what a caller gave: bindings, a definition's structure or a host's use of the API. */
|
|
201
|
+
static structure(code: string, message: string, location: NexoLocation): NexoError;
|
|
202
|
+
/** A script resolution finds does not fit its vocabulary or its types, before anything is evaluated. */
|
|
203
|
+
static validation(code: string, message: string, location: NexoLocation): NexoError;
|
|
204
|
+
/** A declaration breaking its contract, as a host refuses a declaration whose keys of the host's own break the host's rules. */
|
|
205
|
+
static module(code: string, message: string, location: NexoLocation): NexoError;
|
|
206
|
+
/** A failure while evaluating, with what caused it. */
|
|
207
|
+
static evaluation(code: string, message: string, location: NexoLocation, options?: { cause?: unknown }): NexoError;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** How a member changes. */
|
|
211
|
+
export type NexoChangeCategory = 'constant' | 'observable' | 'partly-observable' | 'unobserved' | 'derived';
|
|
212
|
+
|
|
213
|
+
/** How a member reads. */
|
|
214
|
+
export type NexoReadingMode = 'fresh' | 'maintained' | 'captured' | 'derived';
|
|
215
|
+
|
|
216
|
+
/** A reference to the argument a call gives for a parameter of the member. */
|
|
217
|
+
export interface NexoArgumentReference {
|
|
218
|
+
argument: string;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** An argument of the member with a prefix joined to it, for a value parameter of type `String`, as `{ argument: 'name', prefix: 'aria-' }` names the attribute `aria-` and the name. */
|
|
222
|
+
export interface NexoPrefixedArgumentReference extends NexoArgumentReference {
|
|
223
|
+
/** What is joined before the argument, a string no empty one. */
|
|
224
|
+
prefix: string;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** An argument an observation gives its observation type: a literal, a reference to an argument of the member, which can carry a prefix, or a list of them. */
|
|
228
|
+
export type NexoObservationArgument = string | number | boolean | null | NexoArgumentReference | NexoPrefixedArgumentReference | NexoObservationArgument[];
|
|
229
|
+
|
|
230
|
+
/** An observation that covers a member's changes: its type, what it observes, and the arguments its type takes. */
|
|
231
|
+
export interface NexoObservationDeclaration {
|
|
232
|
+
/** The name of the type of observation, which a module declares. */
|
|
233
|
+
type: string;
|
|
234
|
+
/** What it observes: the receiver; a target the module declaring its type declares, by its name; or the argument of the member that names it. A module member takes no receiver, and observes neither it nor a target found from it. */
|
|
235
|
+
of: string | NexoArgumentReference;
|
|
236
|
+
[argument: string]: NexoObservationArgument | undefined;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** How a member changes and reads, the changes it misses, the tolerance it is compared within and the observations that cover its changes. */
|
|
240
|
+
export interface NexoUpdates {
|
|
241
|
+
changes: NexoChangeCategory;
|
|
242
|
+
reads: NexoReadingMode;
|
|
243
|
+
/** The changes a partly observable declaration's observations miss; required where it is partly observable, and refused otherwise. */
|
|
244
|
+
misses?: string;
|
|
245
|
+
/** How far a number it returns, or each number a structured result of it holds, may move before a host reports a different result; taken by a numeric or a structured result alone. */
|
|
246
|
+
tolerance?: number;
|
|
247
|
+
/** The observations that cover its changes, which an observable or partly observable declaration names and no other does. */
|
|
248
|
+
observations?: NexoObservationDeclaration[];
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** What an implementation of an observation type receives: the request it observes, `{ type, target, arguments }`, as the specification's observation types define it, the function it calls when something may have changed, and the environment. */
|
|
252
|
+
export interface NexoObservationTypeImplementationInput {
|
|
253
|
+
readonly request: Readonly<Record<string, unknown>>;
|
|
254
|
+
readonly notify: () => void;
|
|
255
|
+
readonly env: unknown;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/** A type of observation: what its observations provide, and the implementation that starts one. */
|
|
259
|
+
export interface NexoObservationTypeDeclaration {
|
|
260
|
+
name: string;
|
|
261
|
+
/** A signal that a result may have changed, or a sampled value a member reads. */
|
|
262
|
+
contract: 'invalidation' | 'maintained';
|
|
263
|
+
/** The arguments that belong to the identity of an observation, beside its target. */
|
|
264
|
+
identity?: string[];
|
|
265
|
+
/** Whether equivalent requests share one observation; one that is not shared is kept for each of its host's evaluations alone. */
|
|
266
|
+
shared?: boolean;
|
|
267
|
+
/** Starts an observation, and answers an object whose `stop` ends it and, for a maintained one, whose `sample` answers its latest sample as `{ pending, value }`, pending until the first arrives. */
|
|
268
|
+
impl?: (input: NexoObservationTypeImplementationInput) => { stop(): void; sample?(): { pending: boolean; value?: unknown } };
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/** A type selector, through which a function's fixed argument selects the type of its result: declared by its name alone. */
|
|
272
|
+
export interface NexoTypeSelectorDeclaration {
|
|
273
|
+
name: string;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/** A mapping of one key of a type selector to the type it maps to, its selector and its key its identity. */
|
|
277
|
+
export interface NexoMappingDeclaration {
|
|
278
|
+
/** The type selector the key belongs to. */
|
|
279
|
+
selector: string;
|
|
280
|
+
/** The key, any string, as a fixed argument gives it. */
|
|
281
|
+
key: string;
|
|
282
|
+
/** The type the key maps to, in Nexo's notation. */
|
|
283
|
+
type: string;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/** A target a module's observation types observe besides the receiver and an argument of the member, which the host resolves. */
|
|
287
|
+
export interface NexoObservationTargetDeclaration {
|
|
288
|
+
/** Its name, which an observation's `of` gives, and never `receiver`. */
|
|
289
|
+
name: string;
|
|
290
|
+
/** Whether it is found from the receiver, so a module member observes none of it, or independent of it, the default. */
|
|
291
|
+
from?: 'receiver';
|
|
292
|
+
/** Whether it is several targets, each observed alike, which a maintained observation never observes, or one, the default. */
|
|
293
|
+
count?: 'many';
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/** What an implementation of an operator receives: the value, never null, and `reject`. */
|
|
297
|
+
export interface NexoOperatorImplementationInput {
|
|
298
|
+
readonly value: unknown;
|
|
299
|
+
/**
|
|
300
|
+
* Rejects the value, which the operator does not cast or convert, with a reason that is a diagnostic string. It throws a signal private to Nexo and to this attempt at the operator,
|
|
301
|
+
* so it never returns and the implementation stops where it calls it, unlike a promise's `reject`. Any other exception it throws, and a value not of its destination, is a fault.
|
|
302
|
+
*/
|
|
303
|
+
reject(reason: string): never;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/** A parameter of a member. */
|
|
307
|
+
export interface NexoParameterDeclaration {
|
|
308
|
+
name: string;
|
|
309
|
+
/**
|
|
310
|
+
* A value; an expression, a body of each item, written as an expression evaluated against it or as a function of it; a predicate, an expression of any value whose truthiness the implementation receives; or a function: an arrow function, a function a name holds, a module's function
|
|
311
|
+
* by reference or an implicit body, which only a member of kind `function` takes. The implementation receives an expression, a predicate and a function as a function it calls only while its own invocation lasts, with the
|
|
312
|
+
* arguments its contract declares: one item for an expression and a predicate. A function the host invokes takes value and function parameters, its host keeping a function argument until it disposes the prepared call.
|
|
313
|
+
*/
|
|
314
|
+
kind: 'value' | 'expression' | 'predicate' | 'function';
|
|
315
|
+
/** The parameter's type, in Nexo's notation; a predicate's is `Boolean`, what the implementation receives, and a function parameter's the type of its function's result. */
|
|
316
|
+
type: string;
|
|
317
|
+
/** The types its function is called with, in order, in Nexo's notation, which may write a type parameter its member's receiver binds; only a function parameter declares them, beside its member's `parameters`, which are declarations. */
|
|
318
|
+
parameterTypes?: string[];
|
|
319
|
+
/** Whether its argument must be given, `true` where it is left out unless it declares a default; a module's copy always holds it. */
|
|
320
|
+
required?: boolean;
|
|
321
|
+
/** The value a missing optional argument takes, which a required parameter declares none of. */
|
|
322
|
+
default?: unknown;
|
|
323
|
+
/** Whether the argument names something the vocabulary resolves before any evaluation; a fixed parameter is a value parameter of type `String`. */
|
|
324
|
+
fixed?: boolean;
|
|
325
|
+
/** What a fixed parameter names, and only a fixed one: a type, which a function's result writes as `@selected`, through the type selector `selector` names. */
|
|
326
|
+
selects?: 'type';
|
|
327
|
+
/** The type selector a parameter that selects a type selects through. */
|
|
328
|
+
selector?: string;
|
|
329
|
+
/** Whether a null argument makes the call answer null, `'propagate'` where it is left out, or is accepted; a function parameter leaves it out, since a function is never null. */
|
|
330
|
+
nulls?: 'propagate' | 'accept';
|
|
331
|
+
/** What an expression or a predicate argument is evaluated against. */
|
|
332
|
+
context?: 'item';
|
|
333
|
+
/** What the member does where an optional argument is left out, said in words for its documentation. */
|
|
334
|
+
omitted?: string;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/** What a member's implementation receives, by name: its receiver, which a module member has none of, its arguments by parameter name, the environment, and what its kind adds. */
|
|
338
|
+
export interface NexoMemberImplementationInput {
|
|
339
|
+
readonly receiver?: unknown;
|
|
340
|
+
readonly args: Readonly<Record<string, unknown>>;
|
|
341
|
+
readonly env: unknown;
|
|
342
|
+
/** A member that reads maintained values: its observations' latest samples, in the order its declaration names them. */
|
|
343
|
+
readonly samples?: readonly unknown[];
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* A property, a function or an indexer a module declares, each taking the fields it needs alone: within a type, whose receiver the type is, within an extension, whose receiver its target is, or among the module's
|
|
348
|
+
* `members`, a module member, which takes no receiver and is read through its module's namespace. An operator is declared as a `NexoOperatorDeclaration`.
|
|
349
|
+
* A property answers a value, and a function the evaluator invokes its result; a script ending in a call of a function the host invokes ends in a host call, and the function has no implementation Nexo calls.
|
|
350
|
+
*/
|
|
351
|
+
export interface NexoMemberDeclaration {
|
|
352
|
+
/** The Nexo name, and the type parameters it declares in angle brackets after it, `identity<T>`, where it is declared within a type, an extension or the module; left out for an unnamed indexer, which brackets after its receiver invoke. */
|
|
353
|
+
name?: string;
|
|
354
|
+
/** A property, read by its name; a function, called; or an indexer, given its one key in brackets, after its name, `it.setting["mode"]`, or, unnamed, after its receiver, `rooms[0]`. */
|
|
355
|
+
kind: 'property' | 'function' | 'indexer';
|
|
356
|
+
/** Who invokes a function: the evaluator, the default, or the host, which a script ending in a call of it is prepared for; a function the host invokes takes value and function parameters, and neither updates nor an implementation. */
|
|
357
|
+
invokedBy?: 'evaluator' | 'host';
|
|
358
|
+
/** The form its arguments take where it has parameters, an optional one included: one for each parameter, in order, the required ones before the optional ones, or one options object whose fields supply them; a function alone takes it, since an indexer's one key is positional. */
|
|
359
|
+
arguments?: 'positional' | 'options';
|
|
360
|
+
/** Its parameters; a property takes none. */
|
|
361
|
+
parameters?: NexoParameterDeclaration[];
|
|
362
|
+
/** The type of its result, in Nexo's notation; a function the host invokes declares the type of each value its host supplies, left out where it supplies none. */
|
|
363
|
+
result?: string;
|
|
364
|
+
/** How it changes and reads; a property and a function the evaluator invokes take it, and a function the host invokes refuses it. */
|
|
365
|
+
updates?: NexoUpdates;
|
|
366
|
+
/** What carries it out, given one object it reads by name; a member without one is resolved against and never invoked. */
|
|
367
|
+
impl?: (input: NexoMemberImplementationInput) => unknown;
|
|
368
|
+
/** Whether it is available within its declaring module alone, `false` where left out: no other module's declaration names it, and no script reaches it; a member within an internal type is internal whatever it says. */
|
|
369
|
+
internal?: boolean;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/** An operator a type or an extension declares among its members: a cast, which `as` invokes, or a conversion, which `to` invokes, from a value of its receiver's type to its result. */
|
|
373
|
+
export interface NexoOperatorDeclaration {
|
|
374
|
+
kind: 'operator';
|
|
375
|
+
name: 'cast' | 'convert';
|
|
376
|
+
/** Its destination, in Nexo's notation. */
|
|
377
|
+
result: string;
|
|
378
|
+
/** Casts or converts the value, or rejects it; a cast operator without one answers its value. */
|
|
379
|
+
impl?: (input: NexoOperatorImplementationInput) => unknown;
|
|
380
|
+
/** Whether it is available within its declaring module alone, `false` where left out; an operator within an internal type is internal whatever it says. */
|
|
381
|
+
internal?: boolean;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/** What a module declares. */
|
|
385
|
+
export interface NexoModuleContents {
|
|
386
|
+
/** Its recognition of a host's value: the name of the most specific of its own reference types the value is of, or null. */
|
|
387
|
+
typeOf?(value: unknown): string | null;
|
|
388
|
+
/** The reference types and the structured types it declares, and its extensions. */
|
|
389
|
+
types?: NexoTypeDeclaration[];
|
|
390
|
+
/** Its module members, each named as a name is, which take no receiver; a member of a type stands within the type or an extension of it. */
|
|
391
|
+
members?: NexoMemberDeclaration[];
|
|
392
|
+
/** The type selectors it declares, each by its name alone, named once across every module. */
|
|
393
|
+
typeSelectors?: NexoTypeSelectorDeclaration[];
|
|
394
|
+
/** The keys it maps for type selectors, its own or a module's registered before it, each once in its selector. */
|
|
395
|
+
mappings?: NexoMappingDeclaration[];
|
|
396
|
+
/** The types of observation it declares. */
|
|
397
|
+
observationTypes?: NexoObservationTypeDeclaration[];
|
|
398
|
+
/** The targets its observation types observe besides the receiver and an argument of the member, each named once. */
|
|
399
|
+
observationTargets?: NexoObservationTargetDeclaration[];
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/** A vocabulary's declarations as data, each that runs code carrying its implementation. */
|
|
403
|
+
export interface NexoModule {
|
|
404
|
+
readonly name: string;
|
|
405
|
+
readonly typeOf: ((value: unknown) => string | null) | undefined;
|
|
406
|
+
readonly types: readonly NexoStoredDeclaration<NexoTypeDeclaration>[];
|
|
407
|
+
readonly members: readonly NexoStoredDeclaration<NexoMemberDeclaration>[];
|
|
408
|
+
readonly typeSelectors: readonly NexoTypeSelectorDeclaration[];
|
|
409
|
+
readonly mappings: readonly NexoMappingDeclaration[];
|
|
410
|
+
readonly observationTypes: readonly NexoObservationTypeDeclaration[];
|
|
411
|
+
readonly observationTargets: readonly NexoObservationTargetDeclaration[];
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* A dictionary as an implementation receives one, immutable: its entries in their order, each key once by Nexo's key equality. A host gives one as a `Map` where a declaration names a `Dictionary<K, V>`, and a result
|
|
416
|
+
* exports one as `{ entries: [{ key, value }, …] }`.
|
|
417
|
+
*/
|
|
418
|
+
export interface NexoDictionary<K = unknown, V = unknown> {
|
|
419
|
+
readonly count: number;
|
|
420
|
+
/** Whether it holds the key, a key whose value is null among them. */
|
|
421
|
+
has(key: K): boolean;
|
|
422
|
+
/** The key's value, or null where it holds no such key. */
|
|
423
|
+
get(key: K): V | null;
|
|
424
|
+
/** The key's entry, or null where it holds no such key. */
|
|
425
|
+
getEntry(key: K): NexoPair<K, V> | null;
|
|
426
|
+
readonly keys: readonly K[];
|
|
427
|
+
readonly values: readonly V[];
|
|
428
|
+
readonly entries: readonly NexoPair<K, V>[];
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/** An index as an implementation receives one, immutable: a position counted from a list's end, `^1` the last item and `^0` the end past it. Neither data nor a key, so no result holds one. */
|
|
432
|
+
export interface NexoIndex {
|
|
433
|
+
/** How far from the end it stands, a nonnegative safe integer. */
|
|
434
|
+
readonly offset: number;
|
|
435
|
+
/** The offset from the start it stands at within a list of the length, the length less its offset. */
|
|
436
|
+
resolveIn(length: number): number;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/** A range as an implementation receives one, immutable: a half-open interval of two boundaries, each a number counted from the start, an index from the end, or null where the range leaves it out. */
|
|
440
|
+
export interface NexoRange {
|
|
441
|
+
readonly start: number | NexoIndex | null;
|
|
442
|
+
readonly end: number | NexoIndex | null;
|
|
443
|
+
/** The offsets from the start its boundaries stand at within a list of the length, applied to that one length: a start left out 0 and an end left out the length. */
|
|
444
|
+
resolveIn(length: number): { readonly start: number; readonly end: number };
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/** A pair as an implementation receives one, immutable: a key and its value. A host gives one as `{ key, value }` where a declaration names a `Pair<K, V>`, and a result exports one so. */
|
|
448
|
+
export interface NexoPair<K = unknown, V = unknown> {
|
|
449
|
+
readonly key: K;
|
|
450
|
+
readonly value: V;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* What an evaluation tells of a value it answers, beside the value and never part of it: the origin, a token for the expression that produced it, the same token exactly where one expression of one resolution,
|
|
455
|
+
* with one candidate selected, produced two values; the tolerance the producing member declares, applying to every number within the value but a part with a record of its own; the records of the object fields
|
|
456
|
+
* an object expression built and of the items a projection built, with the input each item came from, a list no projection built having no sources; and each such item's provenance. A part with no record inherits its
|
|
457
|
+
* parent's origin and tolerance, and a record's null tolerance overrides it.
|
|
458
|
+
*/
|
|
459
|
+
export interface NexoResultMetadata {
|
|
460
|
+
readonly origin: object;
|
|
461
|
+
readonly tolerance: number | null;
|
|
462
|
+
readonly objectFields?: Readonly<Record<string, NexoResultMetadata>>;
|
|
463
|
+
readonly items?: readonly NexoResultMetadata[];
|
|
464
|
+
/** The input each item of a list a projection built came from, its immediate input, a null one included; absent for a list no projection built. */
|
|
465
|
+
readonly sources?: readonly NexoProjectionSource[];
|
|
466
|
+
/**
|
|
467
|
+
* Each item's provenance, beside `sources`: the source the earliest projection the item descends from recorded for it, so a list projected from a projection's items names the references the first projection read, and a
|
|
468
|
+
* projection of a list that carries none records its own sources here too. Absent wherever `sources` is, entries repeated where an input repeats, and never a key nor a promise of a unique correspondence.
|
|
469
|
+
*/
|
|
470
|
+
readonly provenance?: readonly NexoProjectionSource[];
|
|
471
|
+
/**
|
|
472
|
+
* The reads whose samples were pending, on a result's own record alone, and only where one was: one for each distinct read, the request its host's `beforeInvoke` answered `{ pending: true }` for, and the origin of the
|
|
473
|
+
* value the read gave, which that value's record carries. Made when the metadata is first read.
|
|
474
|
+
*/
|
|
475
|
+
readonly pending?: readonly NexoPendingRead[];
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/** A read whose sample was pending: the request its host answered pending for, and the origin of the null it gave, which the record of that value carries. */
|
|
479
|
+
export interface NexoPendingRead extends NexoInvocationRequest {
|
|
480
|
+
readonly origin: object;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/** What a member's invocation is, as a hook's request and a prepared host call each give it: its declaration as its module declared it, its receiver, which a module member has none of, its arguments by parameter name, and where the call stands. */
|
|
484
|
+
export interface NexoInvocationRequest {
|
|
485
|
+
readonly declaration: NexoMemberDeclaration;
|
|
486
|
+
/** Its receiver, a qualified form's first argument, which a module member has none of. */
|
|
487
|
+
readonly receiver?: unknown;
|
|
488
|
+
/** Its arguments, by parameter name. */
|
|
489
|
+
readonly args: Readonly<Record<string, unknown>>;
|
|
490
|
+
/** Where the call stands in the definition, a JSON Pointer `getLocation` expands; a call within a script function's body names the part of the body it is, whichever call of the function reached it. */
|
|
491
|
+
readonly pointer: string;
|
|
492
|
+
/** Whether the member was selected as it was evaluated, its receiver a value of `Any`, rather than by resolution; a prepared host call never is. */
|
|
493
|
+
readonly isDeferred: boolean;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/** How an evaluation ended: completed, pending where a sample a member read was pending, or failed. */
|
|
497
|
+
export type NexoEvaluationOutcome = { readonly kind: 'completed' | 'pending'; readonly value: unknown } | { readonly kind: 'failed'; readonly error: unknown };
|
|
498
|
+
|
|
499
|
+
/** The hooks a host gives an evaluation, each optional. */
|
|
500
|
+
export interface NexoEvaluationHooks {
|
|
501
|
+
/** Called before a member's implementation is invoked: answers a maintained member's samples, that one is pending, the implementation then not invoked, or nothing. */
|
|
502
|
+
beforeInvoke?(request: NexoInvocationRequest): readonly unknown[] | { readonly pending: true } | undefined;
|
|
503
|
+
/** Called after an implementation answered a value of its member's result type. */
|
|
504
|
+
afterInvoke?(request: NexoInvocationRequest, value: unknown): void;
|
|
505
|
+
/** Called once as the evaluation ends; its failure after a success fails the evaluation, and after a failure is recorded on it as its `suppressed`. */
|
|
506
|
+
afterEvaluation?(outcome: NexoEvaluationOutcome): void;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/** What an evaluation answers, frozen through its value and its metadata: the detached value, whether a member it read was pending, and the metadata that describes the value. */
|
|
510
|
+
export interface NexoEvaluation {
|
|
511
|
+
readonly value: unknown;
|
|
512
|
+
readonly isPending: boolean;
|
|
513
|
+
readonly metadata: NexoResultMetadata;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/** An evaluator of a resolution: one binding set and the environment the host owns, evaluating one evaluation at a time while its resolution is current. */
|
|
517
|
+
export interface NexoEvaluator {
|
|
518
|
+
/** Evaluates a script that gives a value, refusing one that ends in a host call. */
|
|
519
|
+
evaluate(hooks?: NexoEvaluationHooks | null): NexoEvaluation;
|
|
520
|
+
/** Prepares the host call a script ends in: evaluates the locals before it, then its receiver and arguments, once, without hooks, as `evaluate` given none evaluates, refusing a script that gives a value. */
|
|
521
|
+
prepareHostCall(): NexoPreparedCall | NexoSkippedCall;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/** A host call prepared for its host: the invocation its host carries out, which keeps the locals it was prepared with, apart from every other prepared call of its evaluator. */
|
|
525
|
+
export interface NexoPreparedCall extends NexoInvocationRequest {
|
|
526
|
+
readonly kind: 'prepared';
|
|
527
|
+
/**
|
|
528
|
+
* Projects one value its host supplies: checks it against the call's declared result, then evaluates the result projection against it, reading the locals the call was prepared with, as an evaluation with the hooks given;
|
|
529
|
+
* a call whose host supplies nothing has none. Checking a reference asks the `isInstance` of the declared type and its supertypes, and the modules' `typeOf` where it does not belong, and the evaluation calls
|
|
530
|
+
* the host's hooks as `evaluate` does. It refuses a value the declared result does not admit (NEXO5015), a resolution no longer current (NEXO2040), and a projection while its evaluator is evaluating (NEXO5010).
|
|
531
|
+
*/
|
|
532
|
+
readonly project?: (value: unknown, hooks?: NexoEvaluationHooks | null) => NexoEvaluation;
|
|
533
|
+
/**
|
|
534
|
+
* Ends the kept functions its function arguments gave the host, each called later in the context preparation found, as an evaluation of its own without hooks, checked against its contract; a call of one after it fails
|
|
535
|
+
* (NEXO5051). A call that keeps none needs no disposal, and disposing again does nothing.
|
|
536
|
+
*/
|
|
537
|
+
readonly dispose: () => void;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/** A host call there is nothing to invoke for: its receiver, or an argument whose parameter propagates null, is null, or it has no declaration yet. */
|
|
541
|
+
export interface NexoSkippedCall {
|
|
542
|
+
readonly kind: 'skipped';
|
|
543
|
+
/** Where the call stands in the definition, a JSON Pointer `getLocation` expands. */
|
|
544
|
+
readonly pointer: string;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/** A declaration a resolution uses, a member or an operator, with its names and where it is used. */
|
|
548
|
+
export interface NexoUsedDeclaration {
|
|
549
|
+
readonly declaration: object;
|
|
550
|
+
/** Its declared name, as `total`, an operator's `convert` or `cast`, and null for an unnamed indexer. */
|
|
551
|
+
readonly name: string | null;
|
|
552
|
+
/**
|
|
553
|
+
* The name a message gives it: qualified by the first of its declaration's receiver types the receiver applies to it by, as `String.total`, or by its module, as `shop.greet`, for a module member or a function referenced
|
|
554
|
+
* through its namespace; its declared name alone where that receiver type is any receiver or a type parameter; an unnamed indexer's brackets after its type, as `List[]`; and an operator by the syntax that
|
|
555
|
+
* invokes it, as `String to Number` and `Meter as Device`. A candidate declaration is qualified by the type it is declared for, its type's or its extension's target.
|
|
556
|
+
*/
|
|
557
|
+
readonly qualifiedName: string;
|
|
558
|
+
/** Where it is used, a definition pointer `getLocation` expands; a declaration a script function's body uses is used once at its place in the body, whichever calls reach it. */
|
|
559
|
+
readonly pointer: string;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/** An access whose member is selected during evaluation, by its receiver's actual type, since its receiver is a value of `Any`. */
|
|
563
|
+
export interface NexoDeferredAccess {
|
|
564
|
+
/** The name it accesses, null for an unnamed indexer. */
|
|
565
|
+
readonly name: string | null;
|
|
566
|
+
/** Where it stands, a definition pointer `getLocation` expands; an access in a script function's body is reported once, whichever calls reach it. */
|
|
567
|
+
readonly pointer: string;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/** Every declaration an evaluation could select, and whether that is an overestimate. */
|
|
571
|
+
export interface NexoCandidateDeclarations {
|
|
572
|
+
/**
|
|
573
|
+
* The used declarations, and each deferred access's candidates at its pointer: every accessible declaration of the name and the form it accesses, inherited members and visible extensions among them, which its value's
|
|
574
|
+
* actual type selects one of, or none of.
|
|
575
|
+
*/
|
|
576
|
+
readonly declarations: readonly NexoUsedDeclaration[];
|
|
577
|
+
/** True where a deferred access remains, so its candidates include declarations no evaluation may select; false where the declarations are the used ones alone. */
|
|
578
|
+
readonly isOverestimate: boolean;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/** A script resolved against a registry with bindings of one resolution key, reused with any bindings of that key while it is current. */
|
|
582
|
+
export interface NexoResolution {
|
|
583
|
+
readonly definition: NexoDefinition;
|
|
584
|
+
/** The host call the script ends in, null for a script that gives a value. */
|
|
585
|
+
readonly hostCall: NexoHostCall | null;
|
|
586
|
+
/** The type of the result, in type notation, null for a host call whose host supplies no values. */
|
|
587
|
+
readonly type: string | null;
|
|
588
|
+
/**
|
|
589
|
+
* Every declaration it has selected, operators among them, one only an unreached branch uses included, each once at each place it is used. Where a deferred access remains, they are not everything an evaluation might
|
|
590
|
+
* use: `getCandidateDeclarations` answers that, as an overestimate.
|
|
591
|
+
*/
|
|
592
|
+
readonly usedDeclarations: readonly NexoUsedDeclaration[];
|
|
593
|
+
/** The accesses whose member is selected during evaluation, in the order they were resolved; empty where every member is selected during resolution. */
|
|
594
|
+
readonly deferredAccesses: readonly NexoDeferredAccess[];
|
|
595
|
+
/** Every declaration an evaluation could select: the used declarations, and each deferred access's candidates, an overestimate while a deferred access remains. */
|
|
596
|
+
getCandidateDeclarations(): NexoCandidateDeclarations;
|
|
597
|
+
/** The type a result path reaches, in type notation, refusing a path of another shape (NEXO2646), as `nexo.paths.validate` does, and a path the type does not hold. */
|
|
598
|
+
typeAt(path: readonly (string | number)[]): string;
|
|
599
|
+
/** Where a pointer stands in the source the definition was read from, as `nexo.getLocation` answers given the resolution's definition. */
|
|
600
|
+
getLocation(pointer: string): NexoLocation;
|
|
601
|
+
/**
|
|
602
|
+
* Whether it is current, so its evaluators evaluate and their prepared calls project: false once a module declaring a `typeOf` is registered where it may recognize values as it is evaluated, a declaration it uses,
|
|
603
|
+
* in any branch, giving it a value of `Any`, or its host call supplying a type that holds a nullable reference; true for good where it may not.
|
|
604
|
+
*/
|
|
605
|
+
readonly isCurrent: boolean;
|
|
606
|
+
/**
|
|
607
|
+
* An evaluator holding bindings of this resolution's key and the environment the host gives it. Binding plain values asks the modules' `typeOf` and `isInstance`, as `createBindings` does, and nothing else calls host code
|
|
608
|
+
* until it evaluates. It refuses bindings another registry made (NEXO2024), bindings of another resolution key (NEXO2025), a resolution no longer current (NEXO2040), and a script using a declaration
|
|
609
|
+
* that has no implementation, a conversion operator among them, even in a branch it may not take (NEXO4001). Its `options.limits` bound the work each of its evaluations does; options it takes none of are refused (NEXO2048),
|
|
610
|
+
* and options or limits that are no object, or an `items` that is no whole number a list can hold (NEXO2049).
|
|
611
|
+
*/
|
|
612
|
+
createEvaluator(bindings?: NexoBindings | NexoBindingValues, env?: unknown, options?: NexoEvaluatorOptions): NexoEvaluator;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/** What an evaluator takes beside its bindings and its environment. */
|
|
616
|
+
export interface NexoEvaluatorOptions {
|
|
617
|
+
/** The bounds its host sets on the work each of its evaluations does, none where it sets none. */
|
|
618
|
+
readonly limits?: NexoEvaluationLimits;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* The bounds a host sets on the work an evaluation does. A list one of Nexo's own members makes, where its size is not its receiver's, as `sequence` and `concat` make, is refused at the call before it is made where it would
|
|
623
|
+
* hold more than `items` (NEXO5054), and the evaluator goes on evaluating. They bound each such list alone, not what a script builds of many.
|
|
624
|
+
*/
|
|
625
|
+
export interface NexoEvaluationLimits {
|
|
626
|
+
/** The most items such a list holds, a whole number from 0 to 4294967295. */
|
|
627
|
+
readonly items?: number;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/** The host call a script ends in: its name, where it stands, the declaration it resolved to, null while its receiver's type is unknown, and its candidates. */
|
|
631
|
+
export interface NexoHostCall {
|
|
632
|
+
readonly name: string;
|
|
633
|
+
/** The JSON Pointer of the call in the definition. */
|
|
634
|
+
readonly pointer: string;
|
|
635
|
+
readonly declaration: NexoMemberDeclaration | null;
|
|
636
|
+
/** The declaration alone, or, while the receiver's type is unknown, every declaration that takes the call as it is written, which agree that the host invokes it. */
|
|
637
|
+
readonly candidates: readonly NexoMemberDeclaration[];
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/** A registry a host resolves scripts against: Nexo's own module and the modules the host registers. It reads no text of its own, since a script's imports alone decide how its text reads, which `nexo.parse`, `format` and `quote` read and write for every registry. No registry is shared. */
|
|
641
|
+
export interface NexoRegistry {
|
|
642
|
+
/** Registers a module's vocabulary, which every script resolved afterwards may use. */
|
|
643
|
+
registerModule(module: NexoModule): void;
|
|
644
|
+
/** The names of the modules registered, Nexo's own first. */
|
|
645
|
+
readonly moduleNames: readonly string[];
|
|
646
|
+
/** A number that changes whenever the registry's vocabulary does; whether a resolution made before a registration is still current is the resolution's `isCurrent`. */
|
|
647
|
+
readonly revision: number;
|
|
648
|
+
/** The observation type of the name, as the module that declares it declared it. */
|
|
649
|
+
getObservationType(name: string): object | undefined;
|
|
650
|
+
/** The name of the module that declares the declaration. */
|
|
651
|
+
getDeclaringModuleName(declaration: object): string | undefined;
|
|
652
|
+
/** The implementation that carries the declaration out, as its module gives it. */
|
|
653
|
+
getImplementation(declaration: object): ((input: any) => unknown) | undefined;
|
|
654
|
+
/**
|
|
655
|
+
* Creates bindings of values by name against the registry, its modules recognizing which are references, each module's `typeOf` asked of every object and the `isInstance` of each type it names, or of a top-level
|
|
656
|
+
* binding's declared type: data as a frozen copy, each reference as itself, a top-level binding of a declared type typed by it, its data captured as that type.
|
|
657
|
+
*/
|
|
658
|
+
createBindings(values?: NexoBindingValues, options?: NexoBindingsOptions): NexoBindings;
|
|
659
|
+
/**
|
|
660
|
+
* Resolves a script against the registered vocabulary and the bindings, the registry's own or plain values it binds, its source read as `parse` reads it, or throws where it does not resolve. Binding plain values asks
|
|
661
|
+
* the modules' `typeOf` and `isInstance`, as `createBindings` does; resolving calls no host code. It reads a source with the imports `options.imports` supplies, a definition recording its own, and refuses
|
|
662
|
+
* bindings another registry made (NEXO2024), an import the registry can't give (NEXO3002, NEXO3052, NEXO3053), and a script that does not resolve, a validation error locating it.
|
|
663
|
+
*/
|
|
664
|
+
resolve(script: NexoScript, bindings?: NexoBindings | NexoBindingValues, options?: NexoScriptOptions): NexoResolution;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/** What a helper's options give a member declaration: every key of one but those its arguments give, so an inline `impl` reads its input typed. */
|
|
668
|
+
export type NexoMemberDeclarationOptions = Partial<Omit<NexoMemberDeclaration, 'name' | 'kind' | 'result'>>;
|
|
669
|
+
|
|
670
|
+
/** A declaration as a module holds it once validated: read-only, named by its local name, with the type parameters it declares beside it. */
|
|
671
|
+
export type NexoStoredDeclaration<T> = Readonly<T> & { readonly typeParameters?: readonly string[] };
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* The declaration helpers, each creating a declaration as a module declares it, constructing a record and registering nothing; each writes every option it is given over its defaults, leaving none out, so a module
|
|
675
|
+
* refuses one its declaration doesn't take. A member takes no receiver of its own, since where it stands gives it one.
|
|
676
|
+
*/
|
|
677
|
+
export interface NexoDeclarations {
|
|
678
|
+
/** A property: with updates, one the evaluator invokes, or, without them, a property of a structured type's data where it stands directly in that type. */
|
|
679
|
+
createPropertyDeclaration(name: string, result: string, options?: NexoMemberDeclarationOptions): NexoMemberDeclaration;
|
|
680
|
+
/** A member a script calls with arguments, or, with `invokedBy: 'host'`, that its host invokes, its result left out where its host supplies nothing. */
|
|
681
|
+
createFunctionDeclaration(name: string, result: string | undefined, options?: NexoMemberDeclarationOptions): NexoMemberDeclaration;
|
|
682
|
+
/** An indexer, given its key in brackets: a named one, `x.name[key]`, or, where its name is null, the unnamed one of its receivers, `x[key]`. */
|
|
683
|
+
createIndexerDeclaration(name: string | null, result: string, options?: NexoMemberDeclarationOptions): NexoMemberDeclaration;
|
|
684
|
+
/** A value parameter, required unless its options give a default. */
|
|
685
|
+
createValueParameterDeclaration(name: string, type: string, options?: Partial<NexoParameterDeclaration>): NexoParameterDeclaration;
|
|
686
|
+
/** An expression of each item, its `nulls` `'propagate'` by default, so a null item answers null without its body being evaluated, or `'accept'`, which evaluates its body against every item, its `it` of the item's type. */
|
|
687
|
+
createExpressionParameterDeclaration(type: string, options?: Partial<NexoParameterDeclaration>): NexoParameterDeclaration;
|
|
688
|
+
/** A predicate of each item, whose truthiness its implementation receives, its `nulls` `'propagate'` by default, so a null item answers null, which is falsy, or `'accept'`, which evaluates its body against it. */
|
|
689
|
+
createPredicateParameterDeclaration(options?: Partial<NexoParameterDeclaration>): NexoParameterDeclaration;
|
|
690
|
+
/** A function parameter, always required: the types of the arguments the member calls its function with, in order, and the type of the result it takes from it. */
|
|
691
|
+
createFunctionParameterDeclaration(name: string, type: string, parameterTypes: readonly string[]): NexoParameterDeclaration;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
/** Result paths: a path's shape validated, and the value it reaches in a result. */
|
|
695
|
+
export interface NexoPaths {
|
|
696
|
+
/** Refuses a path that is no list of field names and list indices, whole numbers that are not negative (NEXO2646). */
|
|
697
|
+
validate(path: readonly (string | number)[]): void;
|
|
698
|
+
/** The value the path reaches, an object field the value holds or a list's item at each step, null where a step holds nothing; a path of another shape is refused as `validate` refuses it. */
|
|
699
|
+
valueAt(value: unknown, path: readonly (string | number)[]): unknown;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/** The versions an implementation of Nexo reports, which change apart. */
|
|
703
|
+
export interface NexoVersions {
|
|
704
|
+
/** The implementation's release version, which the packages and the bundle carry. */
|
|
705
|
+
readonly implementation: string;
|
|
706
|
+
/** The language specification version the implementation follows. */
|
|
707
|
+
readonly language: string;
|
|
708
|
+
/** The definition format version the implementation supports. */
|
|
709
|
+
readonly definition: number;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
/** Which build this is and what it follows. */
|
|
713
|
+
export interface NexoInfo {
|
|
714
|
+
readonly versions: NexoVersions;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
export interface Nexo {
|
|
718
|
+
/**
|
|
719
|
+
* Reads a text into its definition, its imports and those `options.imports` supplies deciding which of its names begin namespaces, refusing a syntax error, a supplied import that breaks an import's rules (NEXO2008)
|
|
720
|
+
* or a structure the definition cannot have. A text read with the same imports gives the same definition, whatever registry reads it.
|
|
721
|
+
*/
|
|
722
|
+
parse(source: string, options?: NexoScriptOptions): NexoDefinition;
|
|
723
|
+
/**
|
|
724
|
+
* Validates a definition given directly against the definition format's structural rules, answering it frozen, as a text giving it would; it checks no vocabulary or types, which resolution validates. It calls
|
|
725
|
+
* no host code, answers a definition it answered already as it is, and refuses a definition of another version (NEXO2007) and any other structure the format does not allow, a structure error at its pointer.
|
|
726
|
+
*/
|
|
727
|
+
validate(definition: unknown): NexoDefinition;
|
|
728
|
+
/** The canonical text of a text or a definition: every import it records, but those `options.imports` says its destination supplies, then its body, laid out on lines. */
|
|
729
|
+
format(script: NexoScript, options?: NexoScriptOptions): string;
|
|
730
|
+
/** The compact canonical text of a text or a definition, as a diagnostic quotes it: its imports, but those its destination supplies, each on a line of its own, and its body on one line where its layout allows. */
|
|
731
|
+
quote(script: NexoScript, options?: NexoScriptOptions): string;
|
|
732
|
+
/** Where a pointer stands in the source a definition was read from, or the pointer alone for a definition given directly; a pointer the definition does not hold is refused. */
|
|
733
|
+
getLocation(definition: NexoDefinition, pointer: string): NexoLocation;
|
|
734
|
+
/** Creates a module from the declarations it holds and the implementations that carry them out. */
|
|
735
|
+
createModule(name: string, contents?: NexoModuleContents): NexoModule;
|
|
736
|
+
readonly declarations: NexoDeclarations;
|
|
737
|
+
/** Creates a registry of Nexo's own module and the modules given, which the host registers more modules with. */
|
|
738
|
+
createRegistry(modules?: readonly NexoModule[]): NexoRegistry;
|
|
739
|
+
readonly paths: NexoPaths;
|
|
740
|
+
readonly info: NexoInfo;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
export declare const nexo: Nexo;
|