@graffiticode/basis 1.5.18 → 1.5.19
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/package.json +3 -2
- package/spec/spec.html +7 -4
- package/spec/spec.md +12 -4
- package/src/compiler.js +8 -8
- package/src/lexicon.js +4 -2
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graffiticode/basis",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.5.
|
|
4
|
+
"version": "1.5.19",
|
|
5
5
|
"description": "The basis library for creating Graffiticode languages",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"test": "jest",
|
|
9
9
|
"build-spec": "npx spec-md ./spec/spec.md > ./spec/spec.html",
|
|
10
|
-
"watch-spec": "npx nodemon --exec 'npx spec-md > ./spec/spec.html' ./spec/spec.md"
|
|
10
|
+
"watch-spec": "npx nodemon --exec 'npx spec-md > ./spec/spec.html' ./spec/spec.md",
|
|
11
|
+
"publish-spec": "npm run build-spec && for dir in ../l0*/packages/api/public; do cp ./spec/spec.html \"$dir/graffiticode-language-spec.html\"; echo \"Copied to $dir/graffiticode-language-spec.html\"; done"
|
|
11
12
|
},
|
|
12
13
|
"engines": {
|
|
13
14
|
"node": "22.x"
|
package/spec/spec.html
CHANGED
|
@@ -174,6 +174,9 @@ end
|
|
|
174
174
|
<li><strong>Strict evaluation</strong>: arguments evaluated before function application</li>
|
|
175
175
|
<li><strong>Immutable data</strong>: all values are immutable</li>
|
|
176
176
|
</ul>
|
|
177
|
+
<p>Many built-in functions in Graffiticode follow a model-threading pattern. In this pattern, functions are defined to take one or more arguments followed by a model, which represents the current state of the program or view. The function uses the earlier arguments to compute an update to the model and returns a new model as its result.</p>
|
|
178
|
+
<p>This style enables a declarative and order-independent composition of functions. Since each function call returns a new model, multiple calls can be reordered without changing the final result, provided the functional dependencies are preserved.</p>
|
|
179
|
+
<p>This approach draws inspiration from <strong>Model-View-Update</strong> (MVU) architectures, in which the model represents the application state and functions describe pure, deterministic transformations of that state.</p>
|
|
177
180
|
</section>
|
|
178
181
|
<section id="sec-Functions" secid="4.2">
|
|
179
182
|
<h2><span class="spec-secid" title="link to this section"><a href="#sec-Functions">4.2</a></span>Functions</h2>
|
|
@@ -305,12 +308,12 @@ end
|
|
|
305
308
|
</tr>
|
|
306
309
|
<tr>
|
|
307
310
|
<td align="left"><code>get</code></td>
|
|
308
|
-
<td align="left"><code><record
|
|
311
|
+
<td align="left"><code><string record: any></code></td>
|
|
309
312
|
<td align="left">Retrieves a value from a record by key</td>
|
|
310
313
|
</tr>
|
|
311
314
|
<tr>
|
|
312
315
|
<td align="left"><code>set</code></td>
|
|
313
|
-
<td align="left"><code><
|
|
316
|
+
<td align="left"><code><string any record: record></code></td>
|
|
314
317
|
<td align="left">Returns a new record with a key set to a value</td>
|
|
315
318
|
</tr>
|
|
316
319
|
</tbody>
|
|
@@ -414,13 +417,13 @@ end
|
|
|
414
417
|
<section id="sec-get" secid="5.2.17">
|
|
415
418
|
<h3><span class="spec-secid" title="link to this section"><a href="#sec-get">5.2.17</a></span>get</h3>
|
|
416
419
|
<p>Retrieve a record field</p>
|
|
417
|
-
<pre><code>get {a: 1, b: 2}
|
|
420
|
+
<pre><code>get "b" {a: 1, b: 2} | returns 2
|
|
418
421
|
</code></pre>
|
|
419
422
|
</section>
|
|
420
423
|
<section id="sec-set" secid="5.2.18">
|
|
421
424
|
<h3><span class="spec-secid" title="link to this section"><a href="#sec-set">5.2.18</a></span>set</h3>
|
|
422
425
|
<p>Return a new record with an updated field</p>
|
|
423
|
-
<pre><code>set {a: 1}
|
|
426
|
+
<pre><code>set "a" 2 {a: 1} | returns {a: 2}
|
|
424
427
|
</code></pre>
|
|
425
428
|
</section>
|
|
426
429
|
</section>
|
package/spec/spec.md
CHANGED
|
@@ -119,6 +119,14 @@ Tags are resolved as special constants with symbolic identity. They are case-sen
|
|
|
119
119
|
- **Strict evaluation**: arguments evaluated before function application
|
|
120
120
|
- **Immutable data**: all values are immutable
|
|
121
121
|
|
|
122
|
+
Many built-in functions in Graffiticode follow a model-threading pattern. In this pattern, functions are defined to take one or more arguments followed by a model, which represents the current state of the program or view. The function uses the earlier arguments to compute an update to the model and returns a new model as its result.
|
|
123
|
+
|
|
124
|
+
This style enables a declarative and order-independent composition of functions. Since each function call returns a new model, multiple calls can be reordered without changing the final result, provided the functional dependencies are preserved.
|
|
125
|
+
|
|
126
|
+
This approach draws inspiration from **Model-View-Update** (MVU) architectures, in which the model represents the application state and functions describe pure, deterministic transformations of that state.
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
122
130
|
## Functions
|
|
123
131
|
|
|
124
132
|
- **Fixed arity**: every function has a known number of parameters
|
|
@@ -167,8 +175,8 @@ Tags are resolved as special constants with symbolic identity. They are case-sen
|
|
|
167
175
|
| `nth` | `<number list: any>` | Nth element of list |
|
|
168
176
|
| `apply` | `<function list: any>` | Applies a function to a list of arguments |
|
|
169
177
|
| `isEmpty` | `<list: bool>` | Returns true if the list is empty |
|
|
170
|
-
| `get` | `<record
|
|
171
|
-
| `set` | `<
|
|
178
|
+
| `get` | `<string record: any>` | Retrieves a value from a record by key |
|
|
179
|
+
| `set` | `<string any record: record>` | Returns a new record with a key set to a value |
|
|
172
180
|
|
|
173
181
|
### add
|
|
174
182
|
|
|
@@ -303,7 +311,7 @@ isEmpty [] | returns true
|
|
|
303
311
|
Retrieve a record field
|
|
304
312
|
|
|
305
313
|
```
|
|
306
|
-
get {a: 1, b: 2}
|
|
314
|
+
get "b" {a: 1, b: 2} | returns 2
|
|
307
315
|
```
|
|
308
316
|
|
|
309
317
|
### set
|
|
@@ -311,7 +319,7 @@ get {a: 1, b: 2} "b" | returns 2
|
|
|
311
319
|
Return a new record with an updated field
|
|
312
320
|
|
|
313
321
|
```
|
|
314
|
-
set {a: 1}
|
|
322
|
+
set "a" 2 {a: 1} | returns {a: 2}
|
|
315
323
|
```
|
|
316
324
|
|
|
317
325
|
# Program Examples
|
package/src/compiler.js
CHANGED
|
@@ -1007,9 +1007,9 @@ export class Transformer extends Visitor {
|
|
|
1007
1007
|
this.visit(node.elts[0], options, (e0, v0) => {
|
|
1008
1008
|
this.visit(node.elts[1], options, (e1, v1) => {
|
|
1009
1009
|
const err = [...e0, ...e1];
|
|
1010
|
-
assert(typeof v0 === "
|
|
1011
|
-
assert(typeof v1 === "
|
|
1012
|
-
const val = v0
|
|
1010
|
+
assert(typeof v0 === "string", "Type Error: expected v0 to be a string.");
|
|
1011
|
+
assert(typeof v1 === "object", "Type Error: expected v1 to be an object. Got " + JSON.stringify(v1));
|
|
1012
|
+
const val = v1[v0];
|
|
1013
1013
|
resume(err, val);
|
|
1014
1014
|
});
|
|
1015
1015
|
});
|
|
@@ -1018,12 +1018,12 @@ export class Transformer extends Visitor {
|
|
|
1018
1018
|
this.visit(node.elts[0], options, (e0, v0) => {
|
|
1019
1019
|
this.visit(node.elts[1], options, (e1, v1) => {
|
|
1020
1020
|
this.visit(node.elts[2], options, (e2, v2) => {
|
|
1021
|
-
const err = [...e0, ...e1];
|
|
1022
|
-
assert(typeof v0 === "
|
|
1023
|
-
assert(typeof
|
|
1021
|
+
const err = [...e0, ...e1, ...e2];
|
|
1022
|
+
assert(typeof v0 === "string", "Type Error: expected v0 to be a string.");
|
|
1023
|
+
assert(typeof v2 === "object", "Type Error: expected v2 to be an object.");
|
|
1024
1024
|
const val = {
|
|
1025
|
-
...
|
|
1026
|
-
[
|
|
1025
|
+
...v2,
|
|
1026
|
+
[v0]: v1,
|
|
1027
1027
|
};
|
|
1028
1028
|
resume(err, val);
|
|
1029
1029
|
});
|
package/src/lexicon.js
CHANGED
|
@@ -11,14 +11,16 @@ export const lexicon = {
|
|
|
11
11
|
"name": "GET",
|
|
12
12
|
"cls": "function",
|
|
13
13
|
"length": 2,
|
|
14
|
-
"arity": 2
|
|
14
|
+
"arity": 2,
|
|
15
|
+
"args": ["key", "record"]
|
|
15
16
|
},
|
|
16
17
|
"set" : {
|
|
17
18
|
"tk": 1,
|
|
18
19
|
"name": "SET",
|
|
19
20
|
"cls": "function",
|
|
20
21
|
"length": 3,
|
|
21
|
-
"arity": 3
|
|
22
|
+
"arity": 3,
|
|
23
|
+
"args": ["key", "value", "record"]
|
|
22
24
|
},
|
|
23
25
|
"nth" : {
|
|
24
26
|
"tk": 1,
|