@mark1russell7/coeval 0.19.0 → 0.20.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/README.md +2 -1
- package/build/index.d.ts +151 -5
- package/build/index.d.ts.map +1 -1
- package/build/index.js +689 -34
- package/build/index.js.map +1 -1
- package/package.json +3 -1
- package/src/index.ts +5 -0
- package/src/instances.ts +33 -5
- package/src/reference.ts +142 -12
- package/src/static.ts +8 -2
- package/src/stdlib.ts +367 -23
- package/src/steps.ts +181 -0
- package/src/world.ts +59 -0
package/src/world.ts
CHANGED
|
@@ -134,11 +134,70 @@ export interface KindFacts {
|
|
|
134
134
|
* Then the term `combine` adds the attribute of each node in the list `children`, one at a time (TREE.FOLD).
|
|
135
135
|
* `combine` sees the names `acc` and `item`.
|
|
136
136
|
* - `default`: the term that gives the value when no rung before it answers and the declaration has no fold.
|
|
137
|
+
* - `circular`: a cycle of this attribute gives its fixed point, not `#CYCLE!` (TREE.CIRCULAR, D113). Only a cycle
|
|
138
|
+
* whose attributes each declare `circular` gives a fixed point.
|
|
137
139
|
*/
|
|
138
140
|
export interface AttributeDeclaration {
|
|
139
141
|
readonly copy?: boolean;
|
|
140
142
|
readonly fold?: { readonly unit: Json; readonly combine: Json };
|
|
141
143
|
readonly default?: Json;
|
|
144
|
+
readonly circular?: CircularDeclaration;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* The declaration `circular` of an attribute (TREE.CIRCULAR, D113). The attribute that a cycle reaches first leads it.
|
|
149
|
+
* The leader evaluates again until no value of the cycle changes.
|
|
150
|
+
*
|
|
151
|
+
* - `start`: the value of the attribute before its first round, as JSON data. The kit does not evaluate it.
|
|
152
|
+
* - `limit`: the most rounds of the leader, a whole number of 1 or more. The default is `CIRCULAR_LIMIT`. A cycle that
|
|
153
|
+
* is not stable after the last round gives `#CYCLE!` (TREE.CIRCULAR-LIMIT).
|
|
154
|
+
*/
|
|
155
|
+
export interface CircularDeclaration {
|
|
156
|
+
readonly start: Json;
|
|
157
|
+
readonly limit?: number;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** The most rounds of a circular attribute without its own `limit` (TREE.CIRCULAR-LIMIT, D113). */
|
|
161
|
+
export const CIRCULAR_LIMIT = 100;
|
|
162
|
+
|
|
163
|
+
/** A declaration `circular` that the kit can use: its start value and its limit, or the reason of a bad declaration. */
|
|
164
|
+
export type CircularRule = { readonly ok: true; readonly start: Json; readonly limit: number } | { readonly ok: false; readonly reason: string };
|
|
165
|
+
|
|
166
|
+
/** This function tells if a value is JSON data: `null`, a truth value, a finite number, a text, or a container of them. */
|
|
167
|
+
function isJsonData(value: unknown): boolean {
|
|
168
|
+
const stack: unknown[] = [value];
|
|
169
|
+
const seen = new Set<object>();
|
|
170
|
+
while (stack.length > 0) {
|
|
171
|
+
const item = stack.pop();
|
|
172
|
+
if (item === null || typeof item === "string" || typeof item === "boolean") continue;
|
|
173
|
+
if (typeof item === "number") {
|
|
174
|
+
if (!Number.isFinite(item)) return false;
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
if (!Array.isArray(item) && !isRecord(item)) return false;
|
|
178
|
+
if (seen.has(item)) continue;
|
|
179
|
+
seen.add(item);
|
|
180
|
+
for (const inner of Object.values(item)) stack.push(inner);
|
|
181
|
+
}
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* This function reads the declaration `circular` of an attribute (D113). The tree kit, the reference, `check` and the
|
|
187
|
+
* graph of attribute instances read it with this one function.
|
|
188
|
+
*
|
|
189
|
+
* @param declared - The value of the field `circular`.
|
|
190
|
+
* @returns The start value and the limit, or the reason when the declaration has no correct form.
|
|
191
|
+
*/
|
|
192
|
+
export function circularOf(declared: unknown): CircularRule {
|
|
193
|
+
if (!isRecord(declared) || !Object.hasOwn(declared, "start")) return { ok: false, reason: "The declaration circular needs a record with the field start." };
|
|
194
|
+
const start = field(declared, "start");
|
|
195
|
+
if (!isJsonData(start)) return { ok: false, reason: "The start value of the declaration circular must be JSON data." };
|
|
196
|
+
const limit: unknown = Object.hasOwn(declared, "limit") ? field(declared, "limit") : CIRCULAR_LIMIT;
|
|
197
|
+
if (typeof limit !== "number" || !Number.isSafeInteger(limit) || limit < 1) {
|
|
198
|
+
return { ok: false, reason: "The limit of the declaration circular must be a whole number of 1 or more." };
|
|
199
|
+
}
|
|
200
|
+
return { ok: true, start: start as Json, limit };
|
|
142
201
|
}
|
|
143
202
|
|
|
144
203
|
/**
|