@mark1russell7/coeval 0.26.0 → 0.27.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/build/index.d.ts +25 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +196 -79
- package/build/index.js.map +1 -1
- package/package.json +4 -1
- package/src/errors.ts +1 -0
- package/src/evaluate.ts +113 -14
- package/src/formula.ts +7 -4
- package/src/generate.ts +4 -9
- package/src/index.ts +1 -0
- package/src/merge.ts +1 -1
- package/src/reference.ts +93 -38
- package/src/stdlib.ts +39 -14
package/build/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { mulberry32 } from "@mark1russell7/rigor-generators";
|
|
1
2
|
// src/doc.ts
|
|
2
3
|
/** The keys that an envelope can have. */
|
|
3
4
|
const ENVELOPE_KEYS = [
|
|
@@ -2409,7 +2410,7 @@ function checkHidden(m, draft) {
|
|
|
2409
2410
|
* - A runner hides the evaluator of its name. Thus one part must give both, or the merge gives a conflict.
|
|
2410
2411
|
* - The hooks `known` compose in the order of the parts. A hook does not answer for a name that a later part replaces.
|
|
2411
2412
|
* The hooks `facts` compose the same way, and the first answer that is not `undefined` wins.
|
|
2412
|
-
* - Each other field, for example `permits`, `adopt`, `roots`, `plain` or `
|
|
2413
|
+
* - Each other field, for example `permits`, `adopt`, `roots`, `plain`, `maxDepth` or `maxWork`, is one value. Two different
|
|
2413
2414
|
* values are a conflict. An absent field has no value.
|
|
2414
2415
|
*
|
|
2415
2416
|
* A conflict stops the merge, unless the later part names its path in `replaces`. A part can be a function of the
|
|
@@ -4324,6 +4325,20 @@ function placeText(place) {
|
|
|
4324
4325
|
}
|
|
4325
4326
|
return text;
|
|
4326
4327
|
}
|
|
4328
|
+
/**
|
|
4329
|
+
* The most work of one evaluation for a machine without its own `maxWork` (WORK.LIMIT, D134). One application of a
|
|
4330
|
+
* closure is one point.
|
|
4331
|
+
*/
|
|
4332
|
+
const WORK_LIMIT = 2e5;
|
|
4333
|
+
/**
|
|
4334
|
+
* This function gives the error of the limit of work. Each tier gives this error (WORK.AGREES).
|
|
4335
|
+
*
|
|
4336
|
+
* @param limit - The limit of the machine.
|
|
4337
|
+
* @returns The error.
|
|
4338
|
+
*/
|
|
4339
|
+
function workFailure(limit) {
|
|
4340
|
+
return fail("#WORK!", `The work of one evaluation is more than ${limit} points. The field maxWork of the machine sets the limit.`).error;
|
|
4341
|
+
}
|
|
4327
4342
|
function selfLabel(self) {
|
|
4328
4343
|
try {
|
|
4329
4344
|
if (isHostThing(self)) return self.label;
|
|
@@ -4457,7 +4472,12 @@ var Session = class {
|
|
|
4457
4472
|
running;
|
|
4458
4473
|
traced;
|
|
4459
4474
|
perform;
|
|
4460
|
-
|
|
4475
|
+
/**
|
|
4476
|
+
* The runtime of the root, on the runtime of an equation of a tree (WORK.EQUATION). The runtime of a root holds
|
|
4477
|
+
* itself after the end of its evaluation (WORK.AFTER, WORK.KEEPS), thus the end mark adds no field to the object.
|
|
4478
|
+
* Each runtime has this field, thus a tree and its equations have one object shape.
|
|
4479
|
+
*/
|
|
4480
|
+
top;
|
|
4461
4481
|
/**
|
|
4462
4482
|
* The record of the reads. Without it, a resolution records nothing. A nested evaluation of an equation of a tree
|
|
4463
4483
|
* shares the record of the evaluation around it (READS.EQUATION).
|
|
@@ -4479,18 +4499,38 @@ var Session = class {
|
|
|
4479
4499
|
* root scope is made at the first effect or `all`, thus an evaluation without effects makes no scope.
|
|
4480
4500
|
*/
|
|
4481
4501
|
scope;
|
|
4482
|
-
constructor(machine, epoch, running, traced, perform,
|
|
4502
|
+
constructor(machine, epoch, running, traced, perform, top, effects, reading = void 0) {
|
|
4483
4503
|
this.machine = machine;
|
|
4484
4504
|
this.epoch = epoch;
|
|
4485
4505
|
this.running = running;
|
|
4486
4506
|
this.traced = traced;
|
|
4487
4507
|
this.perform = perform;
|
|
4488
|
-
this.
|
|
4508
|
+
this.top = top;
|
|
4489
4509
|
this.reading = reading;
|
|
4490
4510
|
this.list = effects;
|
|
4491
4511
|
this.holder = traced ? holderNode() : void 0;
|
|
4492
4512
|
this.current = this.holder;
|
|
4493
4513
|
}
|
|
4514
|
+
/** This getter gives `true` for the runtime of an equation of a tree (WORK.NODE). */
|
|
4515
|
+
get nested() {
|
|
4516
|
+
const top = this.top;
|
|
4517
|
+
return top !== void 0 && top !== this;
|
|
4518
|
+
}
|
|
4519
|
+
/**
|
|
4520
|
+
* This function adds work to the count of the evaluation (WORK.LIMIT). One count is on the runtime of the root, thus
|
|
4521
|
+
* each equation of a tree adds to it. After the end of the evaluation, each entry from the host starts a new count
|
|
4522
|
+
* (WORK.AFTER).
|
|
4523
|
+
*
|
|
4524
|
+
* @param points - The work.
|
|
4525
|
+
* @throws {Failure} The error `#WORK!`, when the count is over the limit of the machine.
|
|
4526
|
+
*/
|
|
4527
|
+
spend(points) {
|
|
4528
|
+
const root = this.top ?? this;
|
|
4529
|
+
const work = (root.top === root && (this.applying ?? 0) === 0 ? 0 : root.work ?? 0) + points;
|
|
4530
|
+
root.work = work;
|
|
4531
|
+
const limit = this.machine.maxWork ?? 2e5;
|
|
4532
|
+
if (work > limit) throw new Failure(workFailure(limit));
|
|
4533
|
+
}
|
|
4494
4534
|
/** The effects of the evaluation, in their order. */
|
|
4495
4535
|
get effects() {
|
|
4496
4536
|
return this.list ??= [];
|
|
@@ -5103,6 +5143,7 @@ function compileNode(c, value, place, declared, depth, address = false) {
|
|
|
5103
5143
|
...address ? { address: true } : {}
|
|
5104
5144
|
};
|
|
5105
5145
|
if (runner !== void 0) {
|
|
5146
|
+
c.keeps = true;
|
|
5106
5147
|
let inner;
|
|
5107
5148
|
try {
|
|
5108
5149
|
inner = isCompiledRunner(runner) ? runner.compileRun(input) : interpretRun(runner, input, split.fill, kind?.caps?.some((rule) => rule.rule === "grant") === true);
|
|
@@ -5113,6 +5154,7 @@ function compileNode(c, value, place, declared, depth, address = false) {
|
|
|
5113
5154
|
const run = placedRun(guard === void 0 ? inner : guardRun(inner, guard, c.machine.domains), place, name);
|
|
5114
5155
|
return finish$2(c, meta, runnerCode(run, place, kindText), run);
|
|
5115
5156
|
}
|
|
5157
|
+
if (!isCompiledEvaluator(evaluator) || evaluator.keeps === true) c.keeps = true;
|
|
5116
5158
|
let inner;
|
|
5117
5159
|
try {
|
|
5118
5160
|
inner = isCompiledEvaluator(evaluator) ? evaluator.compile(input) : interpret(evaluator, input, split.fill);
|
|
@@ -5186,6 +5228,8 @@ var Probe = class {
|
|
|
5186
5228
|
running = false;
|
|
5187
5229
|
/** `true` after the part asked for something that a fold cannot give. */
|
|
5188
5230
|
refused = false;
|
|
5231
|
+
/** A node in a fold costs work, thus a tree stops the fold before it evaluates an equation (WORK.PREPARE). */
|
|
5232
|
+
nested = true;
|
|
5189
5233
|
/** The count of the names that the part read. */
|
|
5190
5234
|
reads = 0;
|
|
5191
5235
|
/**
|
|
@@ -5253,6 +5297,11 @@ var Probe = class {
|
|
|
5253
5297
|
keepsContext() {
|
|
5254
5298
|
this.refused = true;
|
|
5255
5299
|
}
|
|
5300
|
+
/** This function stops the fold at the first point of work, thus `prepare` does no such work (WORK.PREPARE). */
|
|
5301
|
+
spend() {
|
|
5302
|
+
this.refused = true;
|
|
5303
|
+
throw new Failure(workFailure(0));
|
|
5304
|
+
}
|
|
5256
5305
|
};
|
|
5257
5306
|
/**
|
|
5258
5307
|
* This function makes a trap for a root of the context of a fold. Each read of a field calls `refuse`. A trap of the
|
|
@@ -5584,8 +5633,8 @@ const RUNTIME = /* @__PURE__ */ Symbol("coeval.runtime");
|
|
|
5584
5633
|
/**
|
|
5585
5634
|
* This function evaluates a plan inside the evaluation of another runtime, for example an equation of a tree inside
|
|
5586
5635
|
* the evaluation of its tree (READS.EQUATION). The plan gets its own runtime, as in `plan.evaluate`. The reads of the
|
|
5587
|
-
* plan go in the record of the reads of `outer
|
|
5588
|
-
* (READS.FREE). Without
|
|
5636
|
+
* plan go in the record of the reads of `outer`, and its work goes in the count of `outer` (WORK.EQUATION). The context
|
|
5637
|
+
* at the root of `outer` tells which reads are free (READS.FREE). Without a session, the function gives `plan.evaluate(context)`.
|
|
5589
5638
|
*
|
|
5590
5639
|
* @param plan - The plan.
|
|
5591
5640
|
* @param context - The context of the plan.
|
|
@@ -5593,11 +5642,10 @@ const RUNTIME = /* @__PURE__ */ Symbol("coeval.runtime");
|
|
|
5593
5642
|
* @returns The result.
|
|
5594
5643
|
*/
|
|
5595
5644
|
function evaluateWithin(plan, context, outer) {
|
|
5596
|
-
|
|
5597
|
-
if (reading === void 0 || !(plan instanceof CompiledPlan)) return plan.evaluate(context);
|
|
5645
|
+
if (!(outer instanceof Session) || !(plan instanceof CompiledPlan)) return plan.evaluate(context);
|
|
5598
5646
|
const machine = plan.machine;
|
|
5599
5647
|
const ctx = rootContext(machine, context);
|
|
5600
|
-
return plan.code(ctx, new Session(machine, ctx.caps, false, plan.traced, void 0,
|
|
5648
|
+
return plan.code(ctx, new Session(machine, ctx.caps, false, plan.traced, void 0, outer.top ?? outer, void 0, outer.reading));
|
|
5601
5649
|
}
|
|
5602
5650
|
function interpret(fn, input, fill) {
|
|
5603
5651
|
const { kind, typePath, doc, data, place, machine } = input;
|
|
@@ -5760,7 +5808,22 @@ function prepare(machine, doc, options = {}) {
|
|
|
5760
5808
|
run: void 0
|
|
5761
5809
|
};
|
|
5762
5810
|
}
|
|
5763
|
-
return new CompiledPlan(machine, c.traced, root.code, root.run);
|
|
5811
|
+
return new CompiledPlan(machine, c.traced, c.keeps === true ? endingCode(root.code) : root.code, root.run);
|
|
5812
|
+
}
|
|
5813
|
+
/**
|
|
5814
|
+
* This function gives the code of a plan with a document that can use its runtime after the end of the evaluation. The
|
|
5815
|
+
* code marks that end (WORK.KEEPS). Each other plan has no such step, thus the count adds nothing to a read.
|
|
5816
|
+
*
|
|
5817
|
+
* @param code - The code of the root.
|
|
5818
|
+
* @returns The code that marks the end.
|
|
5819
|
+
*/
|
|
5820
|
+
function endingCode(code) {
|
|
5821
|
+
return (ctx, rt) => {
|
|
5822
|
+
const result = code(ctx, rt);
|
|
5823
|
+
const session = rt;
|
|
5824
|
+
session.top ??= session;
|
|
5825
|
+
return result;
|
|
5826
|
+
};
|
|
5764
5827
|
}
|
|
5765
5828
|
/**
|
|
5766
5829
|
* The object of a plan (PLAN.LEAN). The code of `evaluate` and `run` is on the class, thus a plan keeps only its
|
|
@@ -5795,8 +5858,10 @@ var CompiledPlan = class {
|
|
|
5795
5858
|
run(context = makeContext(), runOptions = {}) {
|
|
5796
5859
|
const machine = this.machine;
|
|
5797
5860
|
const ctx = rootContext(machine, context);
|
|
5798
|
-
const s = new Session(machine, ctx.caps, true, this.traced, runOptions.perform,
|
|
5799
|
-
return driveWaiting(this.runCode()(ctx, s), runOptions.signal)
|
|
5861
|
+
const s = new Session(machine, ctx.caps, true, this.traced, runOptions.perform, void 0, void 0, readingOf(runOptions.reads, ctx));
|
|
5862
|
+
return driveWaiting(this.runCode()(ctx, s), runOptions.signal).finally(() => {
|
|
5863
|
+
s.top = s;
|
|
5864
|
+
});
|
|
5800
5865
|
}
|
|
5801
5866
|
};
|
|
5802
5867
|
/**
|
|
@@ -5887,8 +5952,10 @@ async function run(machine, doc, context = makeContext(), options = {}) {
|
|
|
5887
5952
|
...options.verb === void 0 ? {} : { verb: options.verb }
|
|
5888
5953
|
});
|
|
5889
5954
|
const ctx = rootContext(machine, context);
|
|
5890
|
-
const s = new Session(machine, ctx.caps, true, true, options.perform,
|
|
5891
|
-
|
|
5955
|
+
const s = new Session(machine, ctx.caps, true, true, options.perform, void 0, void 0, readingOf(options.reads, ctx));
|
|
5956
|
+
const result = await driveWaiting(plan.runCode()(ctx, s), options.signal);
|
|
5957
|
+
s.top = s;
|
|
5958
|
+
return record(s, result);
|
|
5892
5959
|
}
|
|
5893
5960
|
/**
|
|
5894
5961
|
* This function finds a node of a trace by its path.
|
|
@@ -6436,9 +6503,13 @@ function allValues(results) {
|
|
|
6436
6503
|
const errors = results.filter((result) => !result.ok);
|
|
6437
6504
|
const first = errors[0];
|
|
6438
6505
|
if (first !== void 0 && errors.length === 1) return { error: first };
|
|
6439
|
-
if (errors.length > 1) return { error:
|
|
6506
|
+
if (errors.length > 1) return { error: partsFailed(errors) };
|
|
6440
6507
|
return { values: results.map((result) => result.ok ? result.value : null) };
|
|
6441
6508
|
}
|
|
6509
|
+
/** This function gives the error of more than one failed part. */
|
|
6510
|
+
function partsFailed(errors) {
|
|
6511
|
+
return errors.find((result) => !result.ok && result.error.code === "#WORK!") ?? fail("#ARGS", `${errors.length} parts failed.`);
|
|
6512
|
+
}
|
|
6442
6513
|
function numbers(values, kind) {
|
|
6443
6514
|
const bad = values.findIndex((value) => !isNumber(value));
|
|
6444
6515
|
if (bad !== -1) return fail("#VALUE!", `Part ${bad} of ${kind} is not a number.`);
|
|
@@ -6918,20 +6989,24 @@ function putField(target, key, value) {
|
|
|
6918
6989
|
* This function gives a value with the JSON of each node of a tree in it. A list or a plain record is new only when
|
|
6919
6990
|
* it holds a node. A container that holds itself stays as it is.
|
|
6920
6991
|
*/
|
|
6921
|
-
function plainOf(value, path) {
|
|
6992
|
+
function plainOf(value, path, runtime) {
|
|
6993
|
+
if (typeof value !== "object" || value === null) return ok(value);
|
|
6922
6994
|
const state = stateOf(value);
|
|
6995
|
+
const open = path.get(value);
|
|
6923
6996
|
if (state !== void 0) {
|
|
6924
|
-
if (
|
|
6997
|
+
if (open === true) return fail("#CYCLE!", `The JSON of the node ${state.type} at [${state.place.join(", ")}] holds the node itself.`);
|
|
6998
|
+
if (open === false) runtime?.spend?.(1);
|
|
6925
6999
|
return state.json(path);
|
|
6926
7000
|
}
|
|
6927
|
-
if (
|
|
7001
|
+
if (open === true || isHostThing(value)) return ok(value);
|
|
6928
7002
|
if (!Array.isArray(value) && !isRecord(value)) return ok(value);
|
|
6929
|
-
|
|
7003
|
+
if (open === false) runtime?.spend?.(1);
|
|
7004
|
+
path.set(value, true);
|
|
6930
7005
|
try {
|
|
6931
7006
|
if (Array.isArray(value)) {
|
|
6932
7007
|
let list;
|
|
6933
7008
|
for (let index = 0; index < value.length; index += 1) {
|
|
6934
|
-
const item = plainOf(value[index], path);
|
|
7009
|
+
const item = plainOf(value[index], path, runtime);
|
|
6935
7010
|
if (!item.ok) return item;
|
|
6936
7011
|
if (item.value !== value[index]) (list ??= [...value])[index] = item.value;
|
|
6937
7012
|
}
|
|
@@ -6940,7 +7015,7 @@ function plainOf(value, path) {
|
|
|
6940
7015
|
const record = value;
|
|
6941
7016
|
let out;
|
|
6942
7017
|
for (const key of Object.keys(record)) {
|
|
6943
|
-
const item = plainOf(record[key], path);
|
|
7018
|
+
const item = plainOf(record[key], path, runtime);
|
|
6944
7019
|
if (!item.ok) return item;
|
|
6945
7020
|
if (item.value === record[key]) continue;
|
|
6946
7021
|
if (out === void 0) {
|
|
@@ -6951,7 +7026,7 @@ function plainOf(value, path) {
|
|
|
6951
7026
|
}
|
|
6952
7027
|
return ok(out ?? value);
|
|
6953
7028
|
} finally {
|
|
6954
|
-
path.
|
|
7029
|
+
path.set(value, false);
|
|
6955
7030
|
}
|
|
6956
7031
|
}
|
|
6957
7032
|
/**
|
|
@@ -7403,19 +7478,19 @@ function treeThing(input, place, build, outer, host) {
|
|
|
7403
7478
|
};
|
|
7404
7479
|
},
|
|
7405
7480
|
json(path) {
|
|
7406
|
-
path.
|
|
7481
|
+
path.set(node, true);
|
|
7407
7482
|
try {
|
|
7408
7483
|
const out = {};
|
|
7409
7484
|
for (const part of parts) {
|
|
7410
7485
|
const result = read(part.key);
|
|
7411
7486
|
if (!result.ok) return result;
|
|
7412
|
-
const value = plainOf(result.value, path);
|
|
7487
|
+
const value = plainOf(result.value, path, runtime);
|
|
7413
7488
|
if (!value.ok) return value;
|
|
7414
7489
|
putField(out, part.key, value.value);
|
|
7415
7490
|
}
|
|
7416
7491
|
return ok(out);
|
|
7417
7492
|
} finally {
|
|
7418
|
-
path.
|
|
7493
|
+
path.set(node, false);
|
|
7419
7494
|
}
|
|
7420
7495
|
}
|
|
7421
7496
|
};
|
|
@@ -7438,7 +7513,7 @@ function treeThing(input, place, build, outer, host) {
|
|
|
7438
7513
|
return cell !== void 0 && !cell.busy && cell.result !== void 0;
|
|
7439
7514
|
},
|
|
7440
7515
|
toJson() {
|
|
7441
|
-
const result = state.json(/* @__PURE__ */ new
|
|
7516
|
+
const result = state.json(/* @__PURE__ */ new Map());
|
|
7442
7517
|
if (!result.ok) throw new Failure(result.error);
|
|
7443
7518
|
return result.value;
|
|
7444
7519
|
}
|
|
@@ -7478,6 +7553,8 @@ const NO_HOPS = /* @__PURE__ */ Object.freeze({ hops: false });
|
|
|
7478
7553
|
* The argument `host` gives the memo cells of the host (TREE.CELL), or `undefined` for the plain memo of each node.
|
|
7479
7554
|
*/
|
|
7480
7555
|
function treeNode(input, host) {
|
|
7556
|
+
const runtime = input[RUNTIME];
|
|
7557
|
+
if (runtime?.nested === true) runtime.spend?.(8);
|
|
7481
7558
|
const found = input.resolve(SELF_PATH, NO_HOPS);
|
|
7482
7559
|
const outer = found.ok ? found.thing : void 0;
|
|
7483
7560
|
const above = stateOf(outer);
|
|
@@ -7487,7 +7564,7 @@ function treeNode(input, host) {
|
|
|
7487
7564
|
build.open = true;
|
|
7488
7565
|
const root = treeThing(input, place, build, outer, host);
|
|
7489
7566
|
try {
|
|
7490
|
-
return stateOf(root).json(/* @__PURE__ */ new
|
|
7567
|
+
return stateOf(root).json(/* @__PURE__ */ new Map());
|
|
7491
7568
|
} finally {
|
|
7492
7569
|
build.open = false;
|
|
7493
7570
|
}
|
|
@@ -11279,8 +11356,11 @@ function setOwn$2(target, key, value) {
|
|
|
11279
11356
|
});
|
|
11280
11357
|
else target[key] = value;
|
|
11281
11358
|
}
|
|
11282
|
-
function compiled(compile) {
|
|
11283
|
-
return { compile }
|
|
11359
|
+
function compiled(compile, keeps) {
|
|
11360
|
+
return keeps === void 0 ? { compile } : {
|
|
11361
|
+
compile,
|
|
11362
|
+
keeps
|
|
11363
|
+
};
|
|
11284
11364
|
}
|
|
11285
11365
|
/** This function evaluates parts in order. It gives the value of each part, or the first error. */
|
|
11286
11366
|
function valuesOf(parts, ctx, rt) {
|
|
@@ -12008,7 +12088,7 @@ function makeEvaluators(profile) {
|
|
|
12008
12088
|
const evaluator = evaluators[name];
|
|
12009
12089
|
const type = Object.hasOwn(types, name) ? types[name] : void 0;
|
|
12010
12090
|
const made = Object.freeze(type === void 0 ? evaluator : {
|
|
12011
|
-
|
|
12091
|
+
...evaluator,
|
|
12012
12092
|
type
|
|
12013
12093
|
});
|
|
12014
12094
|
if (truth !== void 0 && TRUTH_READERS.includes(name)) truthByCode.set(made, truth);
|
|
@@ -12277,6 +12357,7 @@ function formulaCode(profile) {
|
|
|
12277
12357
|
const closure = (...args) => {
|
|
12278
12358
|
const level = (clock.applying ?? 0) + 1;
|
|
12279
12359
|
if (level > limit) throw new Failure(fail("#DEPTH!", `The applications of functions nest deeper than ${limit} levels.`).error);
|
|
12360
|
+
rt.spend?.(1);
|
|
12280
12361
|
clock.applying = level;
|
|
12281
12362
|
try {
|
|
12282
12363
|
const scope = { ...ctx.names };
|
|
@@ -12294,7 +12375,7 @@ function formulaCode(profile) {
|
|
|
12294
12375
|
Object.defineProperty(closure, CLOSURE$3, { value: { params: names } });
|
|
12295
12376
|
return ok(closure);
|
|
12296
12377
|
};
|
|
12297
|
-
}),
|
|
12378
|
+
}, true),
|
|
12298
12379
|
"formula.call": compiled(({ value }) => {
|
|
12299
12380
|
const record = partsOf$1(value);
|
|
12300
12381
|
const fnPart = record["fn"];
|
|
@@ -13080,22 +13161,35 @@ function* together(env, list, options = {}) {
|
|
|
13080
13161
|
* @returns The result.
|
|
13081
13162
|
*/
|
|
13082
13163
|
function reference(machine, doc, context = makeContext(), options = {}) {
|
|
13083
|
-
return evaluateRoot(machine, doc, context, options, void 0);
|
|
13164
|
+
return evaluateRoot(machine, doc, context, options, void 0, void 0);
|
|
13084
13165
|
}
|
|
13085
13166
|
/**
|
|
13086
|
-
* This function evaluates a document from its root. An equation of a tree gives the record of its tree
|
|
13087
|
-
*
|
|
13167
|
+
* This function evaluates a document from its root. An equation of a tree gives the record of its tree and the count
|
|
13168
|
+
* of its work. Thus its reads go in the list of the outer evaluation (REF.READS), and its work in the outer count
|
|
13169
|
+
* (WORK.EQUATION).
|
|
13088
13170
|
*/
|
|
13089
|
-
function evaluateRoot(machine, doc, context, options, outer) {
|
|
13171
|
+
function evaluateRoot(machine, doc, context, options, outer, meter) {
|
|
13090
13172
|
const at = rootAt(machine, doc, context, options);
|
|
13091
|
-
const env = envOf(machine, options, false, at.ctx, outer);
|
|
13173
|
+
const env = envOf(machine, options, false, at.ctx, outer, meter);
|
|
13092
13174
|
try {
|
|
13093
13175
|
return within(env, () => evaluateAt(env, at));
|
|
13094
13176
|
} catch (error) {
|
|
13095
13177
|
return placed(thrown(error, "the reference"), []);
|
|
13178
|
+
} finally {
|
|
13179
|
+
if (!env.nested) env.meter.ended = true;
|
|
13096
13180
|
}
|
|
13097
13181
|
}
|
|
13098
13182
|
/**
|
|
13183
|
+
* WORK.LIMIT: this function adds work to the count of an evaluation. After the end of the evaluation, each entry from
|
|
13184
|
+
* the host starts a new count (WORK.AFTER). A count over the limit throws `#WORK!`.
|
|
13185
|
+
*/
|
|
13186
|
+
function spend(env, points) {
|
|
13187
|
+
const meter = env.meter;
|
|
13188
|
+
if (meter.ended && env.applying === 0) meter.spent = 0;
|
|
13189
|
+
meter.spent += points;
|
|
13190
|
+
if (meter.spent > env.maxWork) throw new Failure(workFailure(env.maxWork));
|
|
13191
|
+
}
|
|
13192
|
+
/**
|
|
13099
13193
|
* This function starts a run of a document by the rules, without a compilation (REF.RUN). The host does each effect of a runner,
|
|
13100
13194
|
* and a step waits when the host waits (RUN.SEQ). `all` settles the waits in the order of the host, or in the order
|
|
13101
13195
|
* of the journal of a replay (RUN.REPLAY). An effect of an evaluator gives `#CALC!` (RUN.NEEDS-RUNNER). A signal that
|
|
@@ -13112,14 +13206,16 @@ function evaluateRoot(machine, doc, context, options, outer) {
|
|
|
13112
13206
|
*/
|
|
13113
13207
|
function referenceRun(machine, doc, context = makeContext(), options = {}) {
|
|
13114
13208
|
const at = rootAt(machine, doc, context, options);
|
|
13115
|
-
const env = envOf(machine, options, true, at.ctx, void 0);
|
|
13116
|
-
return driveRun(env, stepsAt(env, at), options.signal).catch((error) => placed(thrown(error, "the reference"), []))
|
|
13209
|
+
const env = envOf(machine, options, true, at.ctx, void 0, void 0);
|
|
13210
|
+
return driveRun(env, stepsAt(env, at), options.signal).catch((error) => placed(thrown(error, "the reference"), [])).finally(() => {
|
|
13211
|
+
env.meter.ended = true;
|
|
13212
|
+
});
|
|
13117
13213
|
}
|
|
13118
13214
|
/**
|
|
13119
13215
|
* This function makes the state of the reference for one evaluation or one run. The record of the reads comes from
|
|
13120
13216
|
* the evaluation around it, or from the list of the options.
|
|
13121
13217
|
*/
|
|
13122
|
-
function envOf(machine, options, running, root, outer) {
|
|
13218
|
+
function envOf(machine, options, running, root, outer, meter) {
|
|
13123
13219
|
const perform = options.perform;
|
|
13124
13220
|
return {
|
|
13125
13221
|
machine,
|
|
@@ -13137,6 +13233,12 @@ function envOf(machine, options, running, root, outer) {
|
|
|
13137
13233
|
},
|
|
13138
13234
|
held: 0,
|
|
13139
13235
|
applying: 0,
|
|
13236
|
+
maxWork: machine.maxWork ?? 2e5,
|
|
13237
|
+
meter: meter ?? {
|
|
13238
|
+
spent: 0,
|
|
13239
|
+
ended: false
|
|
13240
|
+
},
|
|
13241
|
+
nested: meter !== void 0,
|
|
13140
13242
|
reading: outer ?? (options.reads === void 0 ? void 0 : {
|
|
13141
13243
|
list: options.reads,
|
|
13142
13244
|
root
|
|
@@ -13230,7 +13332,7 @@ function equationOf(node, term, names) {
|
|
|
13230
13332
|
return evaluateRoot(env.machine, term, ctx, {
|
|
13231
13333
|
definitions: env.definitions,
|
|
13232
13334
|
...node.of === void 0 ? {} : { declaredType: node.of }
|
|
13233
|
-
}, env.reading);
|
|
13335
|
+
}, env.reading, env.meter);
|
|
13234
13336
|
}
|
|
13235
13337
|
function termIn(table, name) {
|
|
13236
13338
|
return table === void 0 || !Object.hasOwn(table, name) ? void 0 : table[name];
|
|
@@ -13580,42 +13682,55 @@ function instanceOf$1(node, attr, args) {
|
|
|
13580
13682
|
return result;
|
|
13581
13683
|
}
|
|
13582
13684
|
/** TREE.RESULT: the JSON of a node. `open` holds the nodes and the containers whose JSON is in progress. */
|
|
13583
|
-
function jsonOfNode(node, self, open) {
|
|
13584
|
-
|
|
13585
|
-
|
|
13586
|
-
const
|
|
13587
|
-
|
|
13588
|
-
|
|
13589
|
-
|
|
13590
|
-
|
|
13685
|
+
function jsonOfNode(node, self, open, seen) {
|
|
13686
|
+
try {
|
|
13687
|
+
const record = {};
|
|
13688
|
+
for (const part of node.parts) {
|
|
13689
|
+
const result = attributeOf(node, part.key);
|
|
13690
|
+
if (!result.ok) return result;
|
|
13691
|
+
const value = plainValue(node, result.value, [...open, self], seen);
|
|
13692
|
+
if (!value.ok) return value;
|
|
13693
|
+
setField$2(record, part.key, value.value);
|
|
13694
|
+
}
|
|
13695
|
+
return ok(record);
|
|
13696
|
+
} finally {
|
|
13697
|
+
seen.add(self);
|
|
13591
13698
|
}
|
|
13592
|
-
return ok(record);
|
|
13593
13699
|
}
|
|
13594
|
-
/**
|
|
13595
|
-
function
|
|
13700
|
+
/**
|
|
13701
|
+
* This function gives a copy of a value with the JSON of each node in it. The set `seen` holds each node, list and
|
|
13702
|
+
* record that the walk left. A second visit of one of them counts one point on the evaluation of `owner` (WORK.SHARED).
|
|
13703
|
+
*/
|
|
13704
|
+
function plainValue(owner, value, open, seen) {
|
|
13596
13705
|
const node = refNodeOf(value);
|
|
13597
13706
|
if (node !== void 0) {
|
|
13598
13707
|
if (open.includes(value)) return fail("#CYCLE!", `The JSON of the node ${node.kind} at [${node.place.join(", ")}] holds the node itself.`);
|
|
13599
|
-
|
|
13708
|
+
if (seen.has(value) && owner.env !== void 0) spend(owner.env, 1);
|
|
13709
|
+
return jsonOfNode(node, value, open, seen);
|
|
13600
13710
|
}
|
|
13601
13711
|
if (typeof value !== "object" || value === null || isHostThing(value) || open.includes(value)) return ok(value);
|
|
13602
|
-
if (Array.isArray(value))
|
|
13603
|
-
|
|
13604
|
-
|
|
13605
|
-
|
|
13712
|
+
if (!Array.isArray(value) && !isRecord(value)) return ok(value);
|
|
13713
|
+
if (seen.has(value) && owner.env !== void 0) spend(owner.env, 1);
|
|
13714
|
+
try {
|
|
13715
|
+
if (Array.isArray(value)) {
|
|
13716
|
+
const items = [];
|
|
13717
|
+
for (const item of value) {
|
|
13718
|
+
const plain = plainValue(owner, item, [...open, value], seen);
|
|
13719
|
+
if (!plain.ok) return plain;
|
|
13720
|
+
items.push(plain.value);
|
|
13721
|
+
}
|
|
13722
|
+
return ok(items);
|
|
13723
|
+
}
|
|
13724
|
+
const copy = {};
|
|
13725
|
+
for (const key of Object.keys(value)) {
|
|
13726
|
+
const plain = plainValue(owner, value[key], [...open, value], seen);
|
|
13606
13727
|
if (!plain.ok) return plain;
|
|
13607
|
-
|
|
13728
|
+
setField$2(copy, key, plain.value);
|
|
13608
13729
|
}
|
|
13609
|
-
return ok(
|
|
13610
|
-
}
|
|
13611
|
-
|
|
13612
|
-
const copy = {};
|
|
13613
|
-
for (const key of Object.keys(value)) {
|
|
13614
|
-
const plain = plainValue(value[key], [...open, value]);
|
|
13615
|
-
if (!plain.ok) return plain;
|
|
13616
|
-
setField$2(copy, key, plain.value);
|
|
13730
|
+
return ok(copy);
|
|
13731
|
+
} finally {
|
|
13732
|
+
seen.add(value);
|
|
13617
13733
|
}
|
|
13618
|
-
return ok(copy);
|
|
13619
13734
|
}
|
|
13620
13735
|
/**
|
|
13621
13736
|
* TREE.LAZY, TREE.PARENT, TREE.SIBLING and TREE.ERROR: a node of an open tree gives its thing, and the root of a new
|
|
@@ -13623,6 +13738,8 @@ function plainValue(value, open) {
|
|
|
13623
13738
|
* reads `self` only through `resolve` (C4, TREE.SELF).
|
|
13624
13739
|
*/
|
|
13625
13740
|
const treeDefinition = ({ parts, context, kind, place, machine, typePath, resolve: walk, doc }) => {
|
|
13741
|
+
const maker = activeEnvs[activeEnvs.length - 1];
|
|
13742
|
+
if (maker?.nested === true) spend(maker, 8);
|
|
13626
13743
|
const reached = walk(["self"]);
|
|
13627
13744
|
const parent = reached.ok ? reached.thing : void 0;
|
|
13628
13745
|
const outer = refNodeOf(parent);
|
|
@@ -13658,7 +13775,7 @@ const treeDefinition = ({ parts, context, kind, place, machine, typePath, resolv
|
|
|
13658
13775
|
},
|
|
13659
13776
|
has: (key) => key === "parent" || key === "type" || parts.some((part) => part.key === String(key)) || node.values.has(String(key)),
|
|
13660
13777
|
toJson: () => {
|
|
13661
|
-
const result = jsonOfNode(node, self, []);
|
|
13778
|
+
const result = jsonOfNode(node, self, [], /* @__PURE__ */ new Set());
|
|
13662
13779
|
if (result.ok) return result.value;
|
|
13663
13780
|
throw new Failure(result.error);
|
|
13664
13781
|
}
|
|
@@ -13668,7 +13785,7 @@ const treeDefinition = ({ parts, context, kind, place, machine, typePath, resolv
|
|
|
13668
13785
|
AT_READERS.set(self, (attr, args) => instanceOf$1(node, attr, args));
|
|
13669
13786
|
if (nested) return ok(self);
|
|
13670
13787
|
try {
|
|
13671
|
-
return jsonOfNode(node, self, []);
|
|
13788
|
+
return jsonOfNode(node, self, [], /* @__PURE__ */ new Set());
|
|
13672
13789
|
} finally {
|
|
13673
13790
|
node.tree.open = false;
|
|
13674
13791
|
}
|
|
@@ -13807,11 +13924,17 @@ function formulaDefinitions(profile = {}) {
|
|
|
13807
13924
|
const body = partNamed$1(parts, "body");
|
|
13808
13925
|
const clock = activeEnvs[activeEnvs.length - 1] ?? {
|
|
13809
13926
|
applying: 0,
|
|
13810
|
-
maxDepth: 1e3
|
|
13927
|
+
maxDepth: 1e3,
|
|
13928
|
+
maxWork: 2e5,
|
|
13929
|
+
meter: {
|
|
13930
|
+
spent: 0,
|
|
13931
|
+
ended: false
|
|
13932
|
+
}
|
|
13811
13933
|
};
|
|
13812
13934
|
const limit = Math.ceil(clock.maxDepth / 4);
|
|
13813
13935
|
const closure = (...args) => {
|
|
13814
13936
|
if (clock.applying >= limit) throw new Failure(fail("#DEPTH!", `The applications of functions nest deeper than ${limit} levels.`).error);
|
|
13937
|
+
spend(clock, 1);
|
|
13815
13938
|
clock.applying += 1;
|
|
13816
13939
|
try {
|
|
13817
13940
|
const scope = {};
|
|
@@ -18631,20 +18754,14 @@ function checkSyntax(profile) {
|
|
|
18631
18754
|
}
|
|
18632
18755
|
// src/generate.ts
|
|
18633
18756
|
/**
|
|
18634
|
-
* This function makes a source of random numbers with a seed
|
|
18757
|
+
* This function makes a source of random numbers with a seed. The numbers come from `mulberry32` of
|
|
18758
|
+
* `@mark1russell7/rigor-generators` (K248, D191). The draws `int`, `chance` and `pick` keep the rules of the core.
|
|
18635
18759
|
*
|
|
18636
18760
|
* @param seed - The seed: a whole number.
|
|
18637
18761
|
* @returns The source.
|
|
18638
18762
|
*/
|
|
18639
18763
|
function random(seed) {
|
|
18640
|
-
|
|
18641
|
-
const next = () => {
|
|
18642
|
-
state = state + 1831565813 >>> 0;
|
|
18643
|
-
let t = state;
|
|
18644
|
-
t = Math.imul(t ^ t >>> 15, t | 1);
|
|
18645
|
-
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
|
|
18646
|
-
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
18647
|
-
};
|
|
18764
|
+
const next = mulberry32(seed);
|
|
18648
18765
|
const int = (below) => Math.floor(next() * below);
|
|
18649
18766
|
return {
|
|
18650
18767
|
next,
|
|
@@ -22439,6 +22556,6 @@ function samplesAt(values, closed, depth) {
|
|
|
22439
22556
|
function typeFromSamples(values, options = {}) {
|
|
22440
22557
|
return samplesAt(values, options.closed === true, 0);
|
|
22441
22558
|
}
|
|
22442
|
-
export { ATTRIBUTE_RUNGS, CAPS_TYPE, CIRCULAR_LIMIT, CONSTRUCTS, ENVELOPE_KEYS, Failure, GENERATION_LIMIT, Held, JOURNAL, MAX_SYNTAX_ISSUES, MergeError, PARTS, PART_INFO, ROOTS, RUNGS, STD_CAPS, STD_DEFINITIONS, STD_DOMAINS, STD_EVALUATORS, STD_EXT, STD_MACHINE, STD_RUNNERS, STD_SYNTAX, STD_WALKERS, STD_WORLD, THING, WORLD_SYNTAX, agree, agreeRun, agreeSchedule, agreeTypes, argsKey, ask, atArgsOf, atRuleOf, attributeGraph, attributeTrace, attributeVertexId, boundariesOf, capKeys, check, checkCycles, checkLatent, checkStep, checkSteps, checkSyntax, checkWorld, circularOf, classify, codecLaws, collectOf, compilePath, components, compose, conforms, context, cycles, dataEdges, decodeDomain, decodeLog, decodeValue, defineLanguage, derefStep, describe, docEquals, documentKey, durable, edgesOf, effectEdges, effectsOf, effectsOfVerb, encodeLog, encodeValue, entriesAsJson, equationType, evaluate, extendDomain, factsOf, fail, failures, field, fits, flatten, formulaDefinitions, formulaEvaluators, formulaFacts, formulaKinds, formulaKnown, formulaMachine, fromJson, generate, heights, ifRunner, intersectCaps, isAlias, isAllowedOrder, isClosure, isEnvelope, isHostThing, isKey, isKind, isNamespace, isRecord, isRef, isStackOverflow, isStep, isTypeRef, join, jsTruthy, kindDocument, kindNamed, kindOf, layers, looksLikeKind, lookupKind, makeContext, mapDocs, mapRefs, member, mergeMachines, mergeWorlds, narrow, nearestWalker, necessary, nodeAt, nodeLayers, ok, parse, partCaps, partGrants, partsOf, pathMatches, permits, placeOf, placed, planner, prepare, print, printReads, random, recorder, ref, reference, referenceRun, refsOf, replayer, resolve, resolveCompiled, restrictMachine, restrictWorld, run, sameResult, sameValue, schedule, splitParts, stepLadder, stepOf, stepRank, stepper, stepperNext, stepperStart, stored, syntaxFormat, tag, thrown, toJson, treeNodeEvaluator, typeCheck, typeFromSamples, typeFromSchema, typeIssues, typeName, typePath, typeText, typed, typesOf, valueOfThing, verifyReads, walk, worldThing };
|
|
22559
|
+
export { ATTRIBUTE_RUNGS, CAPS_TYPE, CIRCULAR_LIMIT, CONSTRUCTS, ENVELOPE_KEYS, Failure, GENERATION_LIMIT, Held, JOURNAL, MAX_SYNTAX_ISSUES, MergeError, PARTS, PART_INFO, ROOTS, RUNGS, STD_CAPS, STD_DEFINITIONS, STD_DOMAINS, STD_EVALUATORS, STD_EXT, STD_MACHINE, STD_RUNNERS, STD_SYNTAX, STD_WALKERS, STD_WORLD, THING, WORK_LIMIT, WORLD_SYNTAX, agree, agreeRun, agreeSchedule, agreeTypes, argsKey, ask, atArgsOf, atRuleOf, attributeGraph, attributeTrace, attributeVertexId, boundariesOf, capKeys, check, checkCycles, checkLatent, checkStep, checkSteps, checkSyntax, checkWorld, circularOf, classify, codecLaws, collectOf, compilePath, components, compose, conforms, context, cycles, dataEdges, decodeDomain, decodeLog, decodeValue, defineLanguage, derefStep, describe, docEquals, documentKey, durable, edgesOf, effectEdges, effectsOf, effectsOfVerb, encodeLog, encodeValue, entriesAsJson, equationType, evaluate, extendDomain, factsOf, fail, failures, field, fits, flatten, formulaDefinitions, formulaEvaluators, formulaFacts, formulaKinds, formulaKnown, formulaMachine, fromJson, generate, heights, ifRunner, intersectCaps, isAlias, isAllowedOrder, isClosure, isEnvelope, isHostThing, isKey, isKind, isNamespace, isRecord, isRef, isStackOverflow, isStep, isTypeRef, join, jsTruthy, kindDocument, kindNamed, kindOf, layers, looksLikeKind, lookupKind, makeContext, mapDocs, mapRefs, member, mergeMachines, mergeWorlds, narrow, nearestWalker, necessary, nodeAt, nodeLayers, ok, parse, partCaps, partGrants, partsOf, pathMatches, permits, placeOf, placed, planner, prepare, print, printReads, random, recorder, ref, reference, referenceRun, refsOf, replayer, resolve, resolveCompiled, restrictMachine, restrictWorld, run, sameResult, sameValue, schedule, splitParts, stepLadder, stepOf, stepRank, stepper, stepperNext, stepperStart, stored, syntaxFormat, tag, thrown, toJson, treeNodeEvaluator, typeCheck, typeFromSamples, typeFromSchema, typeIssues, typeName, typePath, typeText, typed, typesOf, valueOfThing, verifyReads, walk, worldThing };
|
|
22443
22560
|
|
|
22444
22561
|
//# sourceMappingURL=index.js.map
|