@valancex/mesh-compiler 0.4.0 → 0.6.0
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/README.md +5 -1
- package/dist/engine.d.ts +44 -3
- package/dist/engine.js +119 -29
- package/dist/index.d.ts +30 -3
- package/dist/index.js +30 -2
- package/dist/mesh.wasm +0 -0
- package/dist/runtime-document.d.ts +80 -0
- package/dist/runtime-document.js +1 -0
- package/dist/template.d.ts +104 -0
- package/dist/template.js +11 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
The [MESH](https://github.com/ValanceX/Mesh) compiler, built for WebAssembly. Check MPRX, with or without a component manifest, and get back exactly the diagnostics `mesh check --format json` prints for the same inputs.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Or compile it, and also get the component's **template**, exactly what `mesh compile` writes: the checked MPRX with every name resolved and no values, which the MESH runtime renders.
|
|
6
|
+
|
|
7
|
+
It's the Rust compiler itself, compiled to WebAssembly, not a reimplementation: this package adds no rule of its own.
|
|
6
8
|
|
|
7
9
|
```js
|
|
8
10
|
import { check } from "@valancex/mesh-compiler";
|
|
@@ -28,6 +30,8 @@ The [Using MESH from JavaScript](https://github.com/ValanceX/Mesh/blob/main/docs
|
|
|
28
30
|
## The API
|
|
29
31
|
|
|
30
32
|
- **`check(input)`** returns a promise of the diagnostics document, the one [`schemas/diagnostics-v1.schema.json`](https://github.com/ValanceX/Mesh/blob/main/schemas/diagnostics-v1.schema.json) describes. Anything wrong with your MPRX or your manifest is a diagnostic in it, never an exception. Diagnostics about the manifest carry the manifest's `path`. Each position has a `byte` offset, a 1-based `line` and `column`, and, for JavaScript, `utf16` (an offset into your string) and `utf16Column`.
|
|
33
|
+
- **`compile(input)`** takes `check`'s input, with `model` required, and returns a promise of `{ diagnostics, template? }`. `diagnostics` is the document `check` returns for the same input. `template` is the `template-v1` document ([`schemas/template-v1.schema.json`](https://github.com/ValanceX/Mesh/blob/main/schemas/template-v1.schema.json)), present exactly when the diagnostics have no error; warnings don't stop it. A template is data to store and pass to the runtime, not to interpret. The `Template` type describes it.
|
|
34
|
+
- **`checkProgram({ model, root, templates })`** checks a program of templates: the manifest's text, the root component, and the templates' texts in order. It returns a promise of the runtime diagnostics document ([`schemas/runtime-diagnostics-v1.schema.json`](https://github.com/ValanceX/Mesh/blob/main/schemas/runtime-diagnostics-v1.schema.json)), empty when the program is valid: exactly what `mesh check-program --format json` prints, and what the runtime's render reports for the same program. The `RuntimeDiagnosticsDocument` type describes it.
|
|
31
35
|
- **`init(module)`** loads the WebAssembly module: a URL, its bytes, or a compiled `WebAssembly.Module`. In Node you don't need it; the package loads its own. In a browser, call it once before the first check, with the URL of `@valancex/mesh-compiler/mesh.wasm` as your setup serves it. Automatic loading by bundlers isn't part of this package's contract.
|
|
32
36
|
- **`version`**: the package's version.
|
|
33
37
|
- **`MeshVersionError`**: the WebAssembly module isn't this version's. No check runs against it.
|
package/dist/engine.d.ts
CHANGED
|
@@ -4,12 +4,15 @@
|
|
|
4
4
|
* out of it, and discarding it after a failure.
|
|
5
5
|
*
|
|
6
6
|
* Deliberately boring (outline v0.4 I6): nothing here knows MPRX, the
|
|
7
|
-
* manifest, positions or
|
|
8
|
-
*
|
|
9
|
-
* document
|
|
7
|
+
* manifest, positions, diagnostics or templates. It transfers UTF-8 in
|
|
8
|
+
* and the result out (a diagnostics document, or for a compile, that
|
|
9
|
+
* document and a template), and checks only that what came out has that
|
|
10
|
+
* shape at all. Not public API (D11): the package's `exports` map
|
|
10
11
|
* doesn't expose this file.
|
|
11
12
|
*/
|
|
12
13
|
import type { DiagnosticsDocument } from "./document.js";
|
|
14
|
+
import type { RuntimeDiagnosticsDocument } from "./runtime-document.js";
|
|
15
|
+
import type { Template } from "./template.js";
|
|
13
16
|
/**
|
|
14
17
|
* A failure at the boundary with the compiler: a trap (a Rust panic, or
|
|
15
18
|
* running out of memory), or a result that isn't a diagnostics document.
|
|
@@ -45,6 +48,40 @@ export interface CheckInput {
|
|
|
45
48
|
component: string;
|
|
46
49
|
};
|
|
47
50
|
}
|
|
51
|
+
/** One compile's inputs: a check's, with the model required. */
|
|
52
|
+
export interface CompileInput {
|
|
53
|
+
/** The MPRX source text. */
|
|
54
|
+
source: string;
|
|
55
|
+
/** An opaque identifier for the source, used only to name it in diagnostics. Never read. */
|
|
56
|
+
path: string;
|
|
57
|
+
/** The model to check against: a template is always a component's. */
|
|
58
|
+
model: {
|
|
59
|
+
/** The manifest's text. */
|
|
60
|
+
manifest: string;
|
|
61
|
+
/** An opaque identifier for the manifest, used only to name it in diagnostics. Never read. */
|
|
62
|
+
path: string;
|
|
63
|
+
/** The component whose template the source is. Always explicit. */
|
|
64
|
+
component: string;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* What a compile gives: the diagnostics document `check` would return for
|
|
69
|
+
* the same inputs, and, only when it has no error, the template.
|
|
70
|
+
*/
|
|
71
|
+
export interface CompileResult {
|
|
72
|
+
diagnostics: DiagnosticsDocument;
|
|
73
|
+
/** The `template-v1` document. Absent when the diagnostics have an error. */
|
|
74
|
+
template?: Template;
|
|
75
|
+
}
|
|
76
|
+
/** One program check's inputs. */
|
|
77
|
+
export interface ProgramInput {
|
|
78
|
+
/** The manifest's text: the model the templates were compiled against. */
|
|
79
|
+
model: string;
|
|
80
|
+
/** The root component: the one the program renders. */
|
|
81
|
+
root: string;
|
|
82
|
+
/** The program's templates (`template-v1` documents, as text), in order. */
|
|
83
|
+
templates: readonly string[];
|
|
84
|
+
}
|
|
48
85
|
/**
|
|
49
86
|
* Loads the module from `source` and checks its version. In Node, the
|
|
50
87
|
* package loads its own module on the first check, so this is only
|
|
@@ -54,6 +91,10 @@ export interface CheckInput {
|
|
|
54
91
|
export declare function init(source: ModuleSource): Promise<void>;
|
|
55
92
|
/** Checks `input`. See the package's `check`. */
|
|
56
93
|
export declare function check(input: CheckInput): Promise<DiagnosticsDocument>;
|
|
94
|
+
/** Compiles `input`. See the package's `compile`. */
|
|
95
|
+
export declare function compile(input: CompileInput): Promise<CompileResult>;
|
|
96
|
+
/** Checks a program. See the package's `checkProgram`. */
|
|
97
|
+
export declare function checkProgram(input: ProgramInput): Promise<RuntimeDiagnosticsDocument>;
|
|
57
98
|
/**
|
|
58
99
|
* The instance in use, if any, for the package's own memory and failure
|
|
59
100
|
* tests. Not API.
|
package/dist/engine.js
CHANGED
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* out of it, and discarding it after a failure.
|
|
5
5
|
*
|
|
6
6
|
* Deliberately boring (outline v0.4 I6): nothing here knows MPRX, the
|
|
7
|
-
* manifest, positions or
|
|
8
|
-
*
|
|
9
|
-
* document
|
|
7
|
+
* manifest, positions, diagnostics or templates. It transfers UTF-8 in
|
|
8
|
+
* and the result out (a diagnostics document, or for a compile, that
|
|
9
|
+
* document and a template), and checks only that what came out has that
|
|
10
|
+
* shape at all. Not public API (D11): the package's `exports` map
|
|
10
11
|
* doesn't expose this file.
|
|
11
12
|
*/
|
|
12
13
|
import { version } from "./version.js";
|
|
@@ -31,6 +32,8 @@ const CHECK_EXPORTS = [
|
|
|
31
32
|
"mesh_alloc",
|
|
32
33
|
"mesh_free",
|
|
33
34
|
"mesh_check",
|
|
35
|
+
"mesh_compile",
|
|
36
|
+
"mesh_check_program",
|
|
34
37
|
"mesh_result_ptr",
|
|
35
38
|
"mesh_result_len",
|
|
36
39
|
"mesh_result_clear",
|
|
@@ -57,7 +60,7 @@ async function bytesOf(location) {
|
|
|
57
60
|
}
|
|
58
61
|
return response.arrayBuffer();
|
|
59
62
|
}
|
|
60
|
-
async function
|
|
63
|
+
async function compileModule(source) {
|
|
61
64
|
if (source instanceof WebAssembly.Module) {
|
|
62
65
|
return source;
|
|
63
66
|
}
|
|
@@ -113,7 +116,7 @@ export function init(source) {
|
|
|
113
116
|
const run = queue.then(async () => {
|
|
114
117
|
compiled = undefined;
|
|
115
118
|
instance = undefined;
|
|
116
|
-
const module = await
|
|
119
|
+
const module = await compileModule(source);
|
|
117
120
|
instance = await instantiate(module);
|
|
118
121
|
compiled = module;
|
|
119
122
|
});
|
|
@@ -128,7 +131,7 @@ async function current() {
|
|
|
128
131
|
if (!isNode()) {
|
|
129
132
|
throw new Error("@valancex/mesh-compiler: call init() with the URL of mesh.wasm before the first check");
|
|
130
133
|
}
|
|
131
|
-
const module = await
|
|
134
|
+
const module = await compileModule(new URL("./mesh.wasm", import.meta.url));
|
|
132
135
|
instance = await instantiate(module);
|
|
133
136
|
compiled = module;
|
|
134
137
|
return instance;
|
|
@@ -149,18 +152,21 @@ function isDocument(value) {
|
|
|
149
152
|
"version" in value &&
|
|
150
153
|
Array.isArray(value.diagnostics));
|
|
151
154
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
155
|
+
function isCompileResult(value) {
|
|
156
|
+
if (typeof value !== "object" || value === null) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
const { diagnostics, template } = value;
|
|
160
|
+
return isDocument(diagnostics) && (template === null || (typeof template === "object" && template !== undefined));
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* One call on `exports`: copies `inputs` into the module, calls `call`
|
|
164
|
+
* with each one's address and length, frees them, and returns the
|
|
165
|
+
* result, parsed. Any exception means the instance failed.
|
|
166
|
+
*/
|
|
167
|
+
function transfer(exports, inputs, call) {
|
|
168
|
+
const buffers = inputs.map((bytes) => ({ ptr: put(exports, bytes), len: bytes.length }));
|
|
169
|
+
const status = call(buffers.flatMap(({ ptr, len }) => [ptr, len]));
|
|
164
170
|
for (const { ptr, len } of buffers) {
|
|
165
171
|
exports.mesh_free(ptr, len);
|
|
166
172
|
}
|
|
@@ -169,20 +175,70 @@ function transfer(exports, input) {
|
|
|
169
175
|
}
|
|
170
176
|
const bytes = new Uint8Array(exports.memory.buffer, exports.mesh_result_ptr(), exports.mesh_result_len()).slice();
|
|
171
177
|
exports.mesh_result_clear();
|
|
172
|
-
|
|
173
|
-
|
|
178
|
+
return JSON.parse(decoder.decode(bytes));
|
|
179
|
+
}
|
|
180
|
+
/** A check's or compile's five texts, as the module takes them. */
|
|
181
|
+
function checkInputs(input) {
|
|
182
|
+
const model = input.model;
|
|
183
|
+
return [
|
|
184
|
+
input.source,
|
|
185
|
+
input.path,
|
|
186
|
+
model?.manifest ?? "",
|
|
187
|
+
model?.path ?? "",
|
|
188
|
+
model?.component ?? "",
|
|
189
|
+
].map((text) => encoder.encode(text));
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* A text list, as the module reads one: a u32 count, then each text as a
|
|
193
|
+
* u32 byte length and its UTF-8 bytes, little-endian.
|
|
194
|
+
*/
|
|
195
|
+
function textList(texts) {
|
|
196
|
+
const encoded = texts.map((text) => encoder.encode(text));
|
|
197
|
+
const size = 4 + encoded.reduce((sum, bytes) => sum + 4 + bytes.length, 0);
|
|
198
|
+
const list = new Uint8Array(size);
|
|
199
|
+
const view = new DataView(list.buffer);
|
|
200
|
+
view.setUint32(0, encoded.length, true);
|
|
201
|
+
let at = 4;
|
|
202
|
+
for (const bytes of encoded) {
|
|
203
|
+
view.setUint32(at, bytes.length, true);
|
|
204
|
+
list.set(bytes, at + 4);
|
|
205
|
+
at += 4 + bytes.length;
|
|
206
|
+
}
|
|
207
|
+
return list;
|
|
208
|
+
}
|
|
209
|
+
function checkResult(value) {
|
|
210
|
+
if (!isDocument(value)) {
|
|
174
211
|
throw new MeshInternalError("the compiler's result isn't a diagnostics document");
|
|
175
212
|
}
|
|
176
|
-
return
|
|
213
|
+
return value;
|
|
214
|
+
}
|
|
215
|
+
function programResult(value) {
|
|
216
|
+
if (!isDocument(value)) {
|
|
217
|
+
throw new MeshInternalError("the compiler's result isn't a runtime diagnostics document");
|
|
218
|
+
}
|
|
219
|
+
return value;
|
|
177
220
|
}
|
|
178
|
-
function
|
|
221
|
+
function compileResult(value) {
|
|
222
|
+
if (!isCompileResult(value)) {
|
|
223
|
+
throw new MeshInternalError("the compiler's result isn't a compile result");
|
|
224
|
+
}
|
|
225
|
+
const diagnostics = value.diagnostics;
|
|
226
|
+
return value.template === null
|
|
227
|
+
? { diagnostics }
|
|
228
|
+
: { diagnostics, template: value.template };
|
|
229
|
+
}
|
|
230
|
+
function validate(input, compiling) {
|
|
231
|
+
const what = compiling ? "compile() takes an object: { source, path, model }" : "check() takes an object: { source, path, model? }";
|
|
179
232
|
if (typeof input !== "object" || input === null) {
|
|
180
|
-
throw new TypeError(
|
|
233
|
+
throw new TypeError(what);
|
|
181
234
|
}
|
|
182
235
|
const strings = [
|
|
183
236
|
["source", input.source],
|
|
184
237
|
["path", input.path],
|
|
185
238
|
];
|
|
239
|
+
if (compiling && input.model === undefined) {
|
|
240
|
+
throw new TypeError("compile() needs a model: { manifest, path, component }");
|
|
241
|
+
}
|
|
186
242
|
if (input.model !== undefined) {
|
|
187
243
|
const model = input.model;
|
|
188
244
|
if (typeof model !== "object" || model === null) {
|
|
@@ -196,11 +252,25 @@ function validate(input) {
|
|
|
196
252
|
}
|
|
197
253
|
}
|
|
198
254
|
}
|
|
199
|
-
|
|
200
|
-
|
|
255
|
+
function validateProgram(input) {
|
|
256
|
+
if (typeof input !== "object" || input === null) {
|
|
257
|
+
throw new TypeError("checkProgram() takes an object: { model, root, templates }");
|
|
258
|
+
}
|
|
259
|
+
if (typeof input.model !== "string") {
|
|
260
|
+
throw new TypeError("model must be a string");
|
|
261
|
+
}
|
|
262
|
+
if (typeof input.root !== "string") {
|
|
263
|
+
throw new TypeError("root must be a string");
|
|
264
|
+
}
|
|
265
|
+
if (!Array.isArray(input.templates) || !input.templates.every((t) => typeof t === "string")) {
|
|
266
|
+
throw new TypeError("templates must be an array of strings");
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/** One call, on the current instance, discarding it if it fails. */
|
|
270
|
+
async function runNow(inputs, call, shape) {
|
|
201
271
|
const exports = await current();
|
|
202
272
|
try {
|
|
203
|
-
return transfer(exports,
|
|
273
|
+
return shape(transfer(exports, inputs, (pointers) => call(exports, pointers)));
|
|
204
274
|
}
|
|
205
275
|
catch (cause) {
|
|
206
276
|
// The instance may be half-updated: never call it again (outline D6).
|
|
@@ -213,12 +283,32 @@ async function checkNow(input) {
|
|
|
213
283
|
throw new MeshInternalError("the compiler failed", { cause });
|
|
214
284
|
}
|
|
215
285
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
const run = queue.then(() => checkNow(input));
|
|
286
|
+
function enqueue(work) {
|
|
287
|
+
const run = queue.then(work);
|
|
219
288
|
queue = run.catch(() => undefined);
|
|
220
289
|
return run;
|
|
221
290
|
}
|
|
291
|
+
/** Checks `input`. See the package's `check`. */
|
|
292
|
+
export function check(input) {
|
|
293
|
+
return enqueue(async () => {
|
|
294
|
+
validate(input, false);
|
|
295
|
+
return runNow(checkInputs(input), (exports, pointers) => exports.mesh_check(...pointers, input.model ? 1 : 0), checkResult);
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
/** Compiles `input`. See the package's `compile`. */
|
|
299
|
+
export function compile(input) {
|
|
300
|
+
return enqueue(async () => {
|
|
301
|
+
validate(input, true);
|
|
302
|
+
return runNow(checkInputs(input), (exports, pointers) => exports.mesh_compile(...pointers), compileResult);
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
/** Checks a program. See the package's `checkProgram`. */
|
|
306
|
+
export function checkProgram(input) {
|
|
307
|
+
return enqueue(async () => {
|
|
308
|
+
validateProgram(input);
|
|
309
|
+
return runNow([encoder.encode(input.model), encoder.encode(input.root), textList(input.templates)], (exports, pointers) => exports.mesh_check_program(...pointers), programResult);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
222
312
|
/**
|
|
223
313
|
* The instance in use, if any, for the package's own memory and failure
|
|
224
314
|
* tests. Not API.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The MESH compiler, in WebAssembly: check MPRX against a component
|
|
3
3
|
* manifest, and get back exactly the diagnostics `mesh check --format
|
|
4
|
-
* json` prints for the same inputs
|
|
4
|
+
* json` prints for the same inputs; compile it, and get the template
|
|
5
|
+
* `mesh compile` writes too; or check a program of templates, as
|
|
6
|
+
* `mesh check-program` does.
|
|
5
7
|
*
|
|
6
8
|
* ```js
|
|
7
9
|
* import { check } from "@valancex/mesh-compiler";
|
|
@@ -19,10 +21,13 @@
|
|
|
19
21
|
*
|
|
20
22
|
* @packageDocumentation
|
|
21
23
|
*/
|
|
22
|
-
import type { CheckInput, ModuleSource } from "./engine.js";
|
|
24
|
+
import type { CheckInput, CompileInput, CompileResult, ModuleSource, ProgramInput } from "./engine.js";
|
|
23
25
|
import type { DiagnosticsDocument } from "./document.js";
|
|
26
|
+
import type { RuntimeDiagnosticsDocument } from "./runtime-document.js";
|
|
24
27
|
export type { Diagnostic, DiagnosticsDocument, Position, Severity, Span, Suggestion, } from "./document.js";
|
|
25
|
-
export type { CheckInput, ModuleSource } from "./engine.js";
|
|
28
|
+
export type { CheckInput, CompileInput, CompileResult, ModuleSource, ProgramInput } from "./engine.js";
|
|
29
|
+
export type { ModelPosition, ModelSpan, RuntimeDiagnostic, RuntimeDiagnosticsDocument, RuntimeLocation, SourceOffset, SourceSpan, } from "./runtime-document.js";
|
|
30
|
+
export type { Offset, Template, TemplateChild, TemplateElement, TemplateExpression, TemplateSpan, } from "./template.js";
|
|
26
31
|
export { MeshInternalError, MeshVersionError } from "./engine.js";
|
|
27
32
|
export { version } from "./version.js";
|
|
28
33
|
/**
|
|
@@ -36,6 +41,28 @@ export { version } from "./version.js";
|
|
|
36
41
|
* call {@link init} first.
|
|
37
42
|
*/
|
|
38
43
|
export declare function check(input: CheckInput): Promise<DiagnosticsDocument>;
|
|
44
|
+
/**
|
|
45
|
+
* Checks `input.source` as the template of `input.model.component`, as
|
|
46
|
+
* {@link check} does, and, only when that finds no error, compiles it to
|
|
47
|
+
* a template (`template-v1`): exactly what `mesh compile` reports and
|
|
48
|
+
* writes for the same inputs. Warnings don't stop it. A model is
|
|
49
|
+
* required, since a template is always a component's.
|
|
50
|
+
*
|
|
51
|
+
* `diagnostics` is the document `check` returns; `template` is absent
|
|
52
|
+
* when it has an error. It rejects as `check` does.
|
|
53
|
+
*/
|
|
54
|
+
export declare function compile(input: CompileInput): Promise<CompileResult>;
|
|
55
|
+
/**
|
|
56
|
+
* Checks a program: the manifest `input.model`, then each of
|
|
57
|
+
* `input.templates` (well-formed, of a format version this MESH reads,
|
|
58
|
+
* and compiled against this model), then the assembly rules, with
|
|
59
|
+
* `input.root` as the root component. Returns the runtime diagnostics
|
|
60
|
+
* document, which is empty when the program is valid: exactly what
|
|
61
|
+
* `mesh check-program --format json` prints, and what the runtime's
|
|
62
|
+
* render reports for the same program before it looks at a snapshot.
|
|
63
|
+
* It produces nothing else. It rejects as `check` does.
|
|
64
|
+
*/
|
|
65
|
+
export declare function checkProgram(input: ProgramInput): Promise<RuntimeDiagnosticsDocument>;
|
|
39
66
|
/**
|
|
40
67
|
* Loads the WebAssembly module from `source`: a URL (or a string resolved
|
|
41
68
|
* against the page), its bytes, or a compiled `WebAssembly.Module`, and
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The MESH compiler, in WebAssembly: check MPRX against a component
|
|
3
3
|
* manifest, and get back exactly the diagnostics `mesh check --format
|
|
4
|
-
* json` prints for the same inputs
|
|
4
|
+
* json` prints for the same inputs; compile it, and get the template
|
|
5
|
+
* `mesh compile` writes too; or check a program of templates, as
|
|
6
|
+
* `mesh check-program` does.
|
|
5
7
|
*
|
|
6
8
|
* ```js
|
|
7
9
|
* import { check } from "@valancex/mesh-compiler";
|
|
@@ -19,7 +21,7 @@
|
|
|
19
21
|
*
|
|
20
22
|
* @packageDocumentation
|
|
21
23
|
*/
|
|
22
|
-
import { check as checkWith, init as initWith } from "./engine.js";
|
|
24
|
+
import { check as checkWith, checkProgram as checkProgramWith, compile as compileWith, init as initWith, } from "./engine.js";
|
|
23
25
|
export { MeshInternalError, MeshVersionError } from "./engine.js";
|
|
24
26
|
export { version } from "./version.js";
|
|
25
27
|
/**
|
|
@@ -35,6 +37,32 @@ export { version } from "./version.js";
|
|
|
35
37
|
export function check(input) {
|
|
36
38
|
return checkWith(input);
|
|
37
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Checks `input.source` as the template of `input.model.component`, as
|
|
42
|
+
* {@link check} does, and, only when that finds no error, compiles it to
|
|
43
|
+
* a template (`template-v1`): exactly what `mesh compile` reports and
|
|
44
|
+
* writes for the same inputs. Warnings don't stop it. A model is
|
|
45
|
+
* required, since a template is always a component's.
|
|
46
|
+
*
|
|
47
|
+
* `diagnostics` is the document `check` returns; `template` is absent
|
|
48
|
+
* when it has an error. It rejects as `check` does.
|
|
49
|
+
*/
|
|
50
|
+
export function compile(input) {
|
|
51
|
+
return compileWith(input);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Checks a program: the manifest `input.model`, then each of
|
|
55
|
+
* `input.templates` (well-formed, of a format version this MESH reads,
|
|
56
|
+
* and compiled against this model), then the assembly rules, with
|
|
57
|
+
* `input.root` as the root component. Returns the runtime diagnostics
|
|
58
|
+
* document, which is empty when the program is valid: exactly what
|
|
59
|
+
* `mesh check-program --format json` prints, and what the runtime's
|
|
60
|
+
* render reports for the same program before it looks at a snapshot.
|
|
61
|
+
* It produces nothing else. It rejects as `check` does.
|
|
62
|
+
*/
|
|
63
|
+
export function checkProgram(input) {
|
|
64
|
+
return checkProgramWith(input);
|
|
65
|
+
}
|
|
38
66
|
/**
|
|
39
67
|
* Loads the WebAssembly module from `source`: a URL (or a string resolved
|
|
40
68
|
* against the page), its bytes, or a compiled `WebAssembly.Module`, and
|
package/dist/mesh.wasm
CHANGED
|
Binary file
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The runtime diagnostics document, as
|
|
3
|
+
* `schemas/runtime-diagnostics-v1.schema.json` describes it: what
|
|
4
|
+
* `mesh check-program --format json` prints, what {@link checkProgram}
|
|
5
|
+
* returns, and what the runtime's render and dispatch report. A later
|
|
6
|
+
* version may add properties; ignore any you don't know.
|
|
7
|
+
*/
|
|
8
|
+
export interface RuntimeDiagnosticsDocument {
|
|
9
|
+
/** The version of the document's shape. */
|
|
10
|
+
version: 1;
|
|
11
|
+
/** Every diagnostic, in the order MESH reports them. */
|
|
12
|
+
diagnostics: RuntimeDiagnostic[];
|
|
13
|
+
}
|
|
14
|
+
export interface RuntimeDiagnostic {
|
|
15
|
+
/** Always `error`: the runtime has no warnings. */
|
|
16
|
+
severity: "error";
|
|
17
|
+
/** The stable code, such as `"assembly-cycle"`. Match on this, not on `message`. */
|
|
18
|
+
code: string;
|
|
19
|
+
/** The human-readable message. It may change between versions. */
|
|
20
|
+
message: string;
|
|
21
|
+
location: RuntimeLocation;
|
|
22
|
+
}
|
|
23
|
+
/** Where a runtime diagnostic is: one of six forms, by `kind`. */
|
|
24
|
+
export type RuntimeLocation =
|
|
25
|
+
/** In the model: a span in the manifest's text. */
|
|
26
|
+
{
|
|
27
|
+
kind: "model";
|
|
28
|
+
span: ModelSpan;
|
|
29
|
+
}
|
|
30
|
+
/** The program as a whole. */
|
|
31
|
+
| {
|
|
32
|
+
kind: "program";
|
|
33
|
+
}
|
|
34
|
+
/** A template, by its 0-based position in the list given, with its component when it can be read. */
|
|
35
|
+
| {
|
|
36
|
+
kind: "template";
|
|
37
|
+
index: number;
|
|
38
|
+
component?: string;
|
|
39
|
+
}
|
|
40
|
+
/** A place in a template: its component, and a span in the source it was compiled from. */
|
|
41
|
+
| {
|
|
42
|
+
kind: "source";
|
|
43
|
+
component: string;
|
|
44
|
+
span: SourceSpan;
|
|
45
|
+
}
|
|
46
|
+
/** A value the host gave: a path from a scope name, or from `$event`. */
|
|
47
|
+
| {
|
|
48
|
+
kind: "input";
|
|
49
|
+
path: (string | number)[];
|
|
50
|
+
}
|
|
51
|
+
/** The handler identifier dispatch was given. */
|
|
52
|
+
| {
|
|
53
|
+
kind: "handler";
|
|
54
|
+
};
|
|
55
|
+
export interface ModelSpan {
|
|
56
|
+
start: ModelPosition;
|
|
57
|
+
end: ModelPosition;
|
|
58
|
+
}
|
|
59
|
+
/** A position in the manifest, as the diagnostics document gives one. */
|
|
60
|
+
export interface ModelPosition {
|
|
61
|
+
/** 0-based byte offset into the UTF-8 text. */
|
|
62
|
+
byte: number;
|
|
63
|
+
/** 1-based line. */
|
|
64
|
+
line: number;
|
|
65
|
+
/** 1-based column, in characters. */
|
|
66
|
+
column: number;
|
|
67
|
+
/** 0-based offset in UTF-16 code units. */
|
|
68
|
+
utf16: number;
|
|
69
|
+
/** 1-based column, in UTF-16 code units. */
|
|
70
|
+
utf16Column: number;
|
|
71
|
+
}
|
|
72
|
+
export interface SourceSpan {
|
|
73
|
+
start: SourceOffset;
|
|
74
|
+
end: SourceOffset;
|
|
75
|
+
}
|
|
76
|
+
/** An offset into MPRX source, as a template records it. */
|
|
77
|
+
export interface SourceOffset {
|
|
78
|
+
byte: number;
|
|
79
|
+
utf16: number;
|
|
80
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The types of a `template-v1` document: one component's MPRX, checked
|
|
3
|
+
* clean and compiled (see the MESH repository's
|
|
4
|
+
* `docs/manual/templates.md` and `schemas/template-v1.schema.json`).
|
|
5
|
+
*
|
|
6
|
+
* A template is data to store and hand to the MESH runtime, not to
|
|
7
|
+
* interpret: nothing in this package reads one. The format may gain
|
|
8
|
+
* properties without changing `version`; readers ignore ones they don't
|
|
9
|
+
* know.
|
|
10
|
+
*/
|
|
11
|
+
/** A place in the source: UTF-8 bytes, and UTF-16 code units, from its start. */
|
|
12
|
+
export interface Offset {
|
|
13
|
+
byte: number;
|
|
14
|
+
utf16: number;
|
|
15
|
+
}
|
|
16
|
+
/** Where a construct was in the source. Nothing depends on it for meaning. */
|
|
17
|
+
export interface TemplateSpan {
|
|
18
|
+
start: Offset;
|
|
19
|
+
end: Offset;
|
|
20
|
+
}
|
|
21
|
+
export interface Template {
|
|
22
|
+
format: "mesh-template";
|
|
23
|
+
version: 1;
|
|
24
|
+
/** The component whose template this is. */
|
|
25
|
+
component: string;
|
|
26
|
+
/** `sha256:` and 64 hexadecimal digits: the model it was checked against. */
|
|
27
|
+
fingerprint: string;
|
|
28
|
+
/** The compiler version that produced it: provenance only. */
|
|
29
|
+
compiler: string;
|
|
30
|
+
root: TemplateElement;
|
|
31
|
+
}
|
|
32
|
+
export interface TemplateElement {
|
|
33
|
+
component: string;
|
|
34
|
+
props: {
|
|
35
|
+
prop: string;
|
|
36
|
+
value: TemplateExpression;
|
|
37
|
+
span: TemplateSpan;
|
|
38
|
+
}[];
|
|
39
|
+
events: {
|
|
40
|
+
event: string;
|
|
41
|
+
command: string;
|
|
42
|
+
arguments: TemplateExpression[];
|
|
43
|
+
span: TemplateSpan;
|
|
44
|
+
}[];
|
|
45
|
+
children: TemplateChild[];
|
|
46
|
+
span: TemplateSpan;
|
|
47
|
+
}
|
|
48
|
+
export type TemplateChild = {
|
|
49
|
+
kind: "text";
|
|
50
|
+
value: string;
|
|
51
|
+
span: TemplateSpan;
|
|
52
|
+
} | {
|
|
53
|
+
kind: "expression";
|
|
54
|
+
expression: TemplateExpression;
|
|
55
|
+
} | {
|
|
56
|
+
kind: "element";
|
|
57
|
+
element: TemplateElement;
|
|
58
|
+
};
|
|
59
|
+
export type TemplateExpression = {
|
|
60
|
+
kind: "literal";
|
|
61
|
+
value: string | number | boolean | null;
|
|
62
|
+
span: TemplateSpan;
|
|
63
|
+
} | {
|
|
64
|
+
kind: "scope";
|
|
65
|
+
name: string;
|
|
66
|
+
span: TemplateSpan;
|
|
67
|
+
} | {
|
|
68
|
+
kind: "member";
|
|
69
|
+
object: TemplateExpression;
|
|
70
|
+
field: string;
|
|
71
|
+
span: TemplateSpan;
|
|
72
|
+
} | {
|
|
73
|
+
kind: "unary";
|
|
74
|
+
operator: "not" | "negate";
|
|
75
|
+
operand: TemplateExpression;
|
|
76
|
+
span: TemplateSpan;
|
|
77
|
+
} | {
|
|
78
|
+
kind: "binary";
|
|
79
|
+
operator: "add" | "subtract" | "multiply" | "divide" | "remainder" | "equal" | "not-equal" | "less" | "less-equal" | "greater" | "greater-equal" | "and" | "or";
|
|
80
|
+
left: TemplateExpression;
|
|
81
|
+
right: TemplateExpression;
|
|
82
|
+
span: TemplateSpan;
|
|
83
|
+
} | {
|
|
84
|
+
kind: "conditional";
|
|
85
|
+
condition: TemplateExpression;
|
|
86
|
+
consequent: TemplateExpression;
|
|
87
|
+
alternate: TemplateExpression;
|
|
88
|
+
span: TemplateSpan;
|
|
89
|
+
} | {
|
|
90
|
+
kind: "list";
|
|
91
|
+
elements: TemplateExpression[];
|
|
92
|
+
span: TemplateSpan;
|
|
93
|
+
} | {
|
|
94
|
+
kind: "record";
|
|
95
|
+
fields: {
|
|
96
|
+
name: string;
|
|
97
|
+
value: TemplateExpression;
|
|
98
|
+
span: TemplateSpan;
|
|
99
|
+
}[];
|
|
100
|
+
span: TemplateSpan;
|
|
101
|
+
} | {
|
|
102
|
+
kind: "event";
|
|
103
|
+
span: TemplateSpan;
|
|
104
|
+
};
|
package/dist/template.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The types of a `template-v1` document: one component's MPRX, checked
|
|
3
|
+
* clean and compiled (see the MESH repository's
|
|
4
|
+
* `docs/manual/templates.md` and `schemas/template-v1.schema.json`).
|
|
5
|
+
*
|
|
6
|
+
* A template is data to store and hand to the MESH runtime, not to
|
|
7
|
+
* interpret: nothing in this package reads one. The format may gain
|
|
8
|
+
* properties without changing `version`; readers ignore ones they don't
|
|
9
|
+
* know.
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/package.json
CHANGED