forma-dsl 0.1.5 → 0.2.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 +1 -1
- package/package.json +1 -1
- package/src/lang/builtins.js +15 -3
- package/src/lang/evaluate.js +19 -1
package/README.md
CHANGED
|
@@ -99,7 +99,7 @@ Hand-written TypeScript declarations ship with it, so the API is typed from eith
|
|
|
99
99
|
|
|
100
100
|
**[The full reference](https://kalpak44.github.io/forma-dsl/docs/)** — every declaration,
|
|
101
101
|
block, function and error, each with usage and troubleshooting. The
|
|
102
|
-
**[editor](https://kalpak44.github.io/forma-dsl/)** runs the whole thing in the browser:
|
|
102
|
+
**[editor](https://kalpak44.github.io/forma-dsl/editor/)** runs the whole thing in the browser:
|
|
103
103
|
type, and the solid updates.
|
|
104
104
|
|
|
105
105
|
## How it works
|
package/package.json
CHANGED
package/src/lang/builtins.js
CHANGED
|
@@ -177,10 +177,17 @@ export class Args {
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
/**
|
|
180
|
-
* Rejects anything the block did not read.
|
|
180
|
+
* Rejects anything the block did not read, and says what it would have read instead.
|
|
181
181
|
*
|
|
182
182
|
* A misspelled attribute is otherwise silent, and the model renders subtly wrong with
|
|
183
|
-
* nothing to point at.
|
|
183
|
+
* nothing to point at. Naming the alternatives matters as much as the refusal: the reader
|
|
184
|
+
* is often a program with no copy of the manual, and an error that says only what is wrong
|
|
185
|
+
* leaves it guessing at spellings. What it read is tracked already, so the list costs
|
|
186
|
+
* nothing to produce.
|
|
187
|
+
*
|
|
188
|
+
* A block that branches on which of two spellings it was given — `radius` against
|
|
189
|
+
* `diameter` — only reads one of them, so the list is what this call would accept and not
|
|
190
|
+
* always the whole set.
|
|
184
191
|
*
|
|
185
192
|
* @returns {void}
|
|
186
193
|
* @throws {FormaError} If any attribute went unread.
|
|
@@ -189,7 +196,12 @@ export class Args {
|
|
|
189
196
|
const extra = Object.keys(this.values).filter((k) => !this.used.has(k));
|
|
190
197
|
if (extra.length) {
|
|
191
198
|
const plural = extra.length > 1 ? 's' : '';
|
|
192
|
-
|
|
199
|
+
const reads = [...this.used].sort((a, z) => a.localeCompare(z));
|
|
200
|
+
const instead = reads.length ? ` — ${this.type} reads ${quoteAll(reads)}` : '';
|
|
201
|
+
throw new FormaError(
|
|
202
|
+
`${this.type}: unknown attribute${plural} ${quoteAll(extra)}${instead}`,
|
|
203
|
+
this.loc,
|
|
204
|
+
);
|
|
193
205
|
}
|
|
194
206
|
}
|
|
195
207
|
}
|
package/src/lang/evaluate.js
CHANGED
|
@@ -7,6 +7,12 @@ import { BLOCKS, FUNCTIONS, CONSTANTS, TYPE_NAMES, Args, quoteAll } from './buil
|
|
|
7
7
|
import { GeometryNode } from '../core/node.js';
|
|
8
8
|
import { Transform } from '../values/transform.js';
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* The blocks handled before the registry is consulted, so they are missing from `BLOCKS` and
|
|
12
|
+
* would otherwise be absent from the list an unknown block is measured against.
|
|
13
|
+
*/
|
|
14
|
+
const SPECIAL_FORMS = ['align', 'for', 'if', 'part'];
|
|
15
|
+
|
|
10
16
|
/**
|
|
11
17
|
* What a body produces: geometry to hand upwards, and any scene parts declared inside it.
|
|
12
18
|
*
|
|
@@ -447,7 +453,19 @@ export class Evaluator {
|
|
|
447
453
|
|
|
448
454
|
const definition = BLOCKS[block.type];
|
|
449
455
|
if (!definition) {
|
|
450
|
-
|
|
456
|
+
// The whole vocabulary, because the reader is often a program with no copy of the
|
|
457
|
+
// manual: a misspelling it cannot correct from the error costs a round trip it has no
|
|
458
|
+
// way to end. Declared components come first — they are the names this document itself
|
|
459
|
+
// introduced, and the likeliest thing a near miss was reaching for.
|
|
460
|
+
const known = [
|
|
461
|
+
...[...this.program.components.keys()].sort((a, z) => a.localeCompare(z)),
|
|
462
|
+
...SPECIAL_FORMS,
|
|
463
|
+
...Object.keys(BLOCKS).sort((a, z) => a.localeCompare(z)),
|
|
464
|
+
];
|
|
465
|
+
throw new FormaError(
|
|
466
|
+
`unknown block "${block.type}" — the blocks are ${quoteAll(known)}`,
|
|
467
|
+
block.loc,
|
|
468
|
+
);
|
|
451
469
|
}
|
|
452
470
|
if (block.labels.length) {
|
|
453
471
|
throw new FormaError(`"${block.type}" does not take a label`, block.loc);
|