@mark1russell7/coeval 0.3.2 → 0.3.3
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.map +1 -1
- package/build/index.js +40 -19
- package/build/index.js.map +1 -1
- package/package.json +1 -1
- package/src/evaluate.ts +57 -21
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@mark1russell7/coeval",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.3",
|
|
5
5
|
"description": "coeval: the kernel of declarative languages. Documents in envelopes, a ladder that finds the evaluator, kind contracts, compiled plans, a static kit, a formula kit and a run side with capabilities.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./build/index.js",
|
package/src/evaluate.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Envelope, type Json, type Key, type TypeRef, isEnvelope, typeName } from "./doc.ts";
|
|
2
|
-
import { splitParts } from "./parts.ts";
|
|
2
|
+
import { type Split, splitParts } from "./parts.ts";
|
|
3
3
|
import { ask, type Answer } from "./ladder.ts";
|
|
4
4
|
import { type Lookup, type Side, type World, lookupKind } from "./world.ts";
|
|
5
5
|
import { type ErrorCode, type EvalError, type Result, fail, ok, placed, thrown, describe } from "./errors.ts";
|
|
@@ -905,39 +905,70 @@ function compileNode(c: Compiler, value: unknown, place: readonly Key[], declare
|
|
|
905
905
|
parts,
|
|
906
906
|
place,
|
|
907
907
|
machine: c.machine,
|
|
908
|
-
fill: (
|
|
908
|
+
fill: fillOf(split, doc),
|
|
909
909
|
};
|
|
910
910
|
if (runner !== undefined) {
|
|
911
911
|
const inner: RunCode = isCompiledRunner(runner) ? runner.compileRun(input) : interpretRun(runner, input, split.fill);
|
|
912
|
-
const run
|
|
913
|
-
|
|
914
|
-
return placed(yield* inner(ctx, rt), place);
|
|
915
|
-
} catch (error) {
|
|
916
|
-
return placed(thrown(error, `the runner ${name}`), place);
|
|
917
|
-
}
|
|
918
|
-
};
|
|
919
|
-
const code: Code = (ctx, rt) =>
|
|
920
|
-
rt.running
|
|
921
|
-
? fail("#CALC!", `${kindText} waits for effects, and its parent cannot wait. Give the parent a runner.`, { place })
|
|
922
|
-
: drive(run(ctx, rt));
|
|
923
|
-
return finish(c, meta, code, run);
|
|
912
|
+
const run = placedRun(inner, place, name);
|
|
913
|
+
return finish(c, meta, runnerCode(run, place, kindText), run);
|
|
924
914
|
}
|
|
925
915
|
|
|
926
916
|
const inner: Code = isCompiledEvaluator(evaluator as Evaluator)
|
|
927
917
|
? (evaluator as CompiledEvaluator).compile(input)
|
|
928
918
|
: interpret(evaluator as EvalFn, input, split.fill);
|
|
929
|
-
const code
|
|
919
|
+
const code = placedCode(inner, place, name);
|
|
920
|
+
return finish(c, meta, code, runOf(code));
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
/*
|
|
924
|
+
* The helpers below make the closures that a plan keeps. Each one has its own small scope. A closure that a
|
|
925
|
+
* compilation made in its own scope keeps each variable of that scope that any closure there reads, for example
|
|
926
|
+
* the split of the value. Thus a plan with these helpers keeps only its code.
|
|
927
|
+
*/
|
|
928
|
+
|
|
929
|
+
/** This function gives the code of a document: the code of its evaluator, with the place of each error and of each exception. */
|
|
930
|
+
function placedCode(inner: Code, place: readonly Key[], name: string): Code {
|
|
931
|
+
return (ctx, rt) => {
|
|
930
932
|
try {
|
|
931
933
|
return placed(inner(ctx, rt), place);
|
|
932
934
|
} catch (error) {
|
|
933
935
|
return placed(thrown(error, `the evaluator ${name}`), place);
|
|
934
936
|
}
|
|
935
937
|
};
|
|
936
|
-
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
/** This function gives the steps of a runner, with the place of each error and of each exception. */
|
|
941
|
+
function placedRun(inner: RunCode, place: readonly Key[], name: string): RunCode {
|
|
942
|
+
return function* (ctx, rt) {
|
|
943
|
+
try {
|
|
944
|
+
return placed(yield* inner(ctx, rt), place);
|
|
945
|
+
} catch (error) {
|
|
946
|
+
return placed(thrown(error, `the runner ${name}`), place);
|
|
947
|
+
}
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
/** This function gives the code of a runner in an evaluation: its steps, which cannot wait. */
|
|
952
|
+
function runnerCode(run: RunCode, place: readonly Key[], kindText: string): Code {
|
|
953
|
+
return (ctx, rt) =>
|
|
954
|
+
rt.running
|
|
955
|
+
? fail("#CALC!", `${kindText} waits for effects, and its parent cannot wait. Give the parent a runner.`, { place })
|
|
956
|
+
: drive(run(ctx, rt));
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
/** This function gives the steps of a run of an evaluator. The code runs at the first step, and it does not wait. */
|
|
960
|
+
function runOf(code: Code): RunCode {
|
|
961
|
+
return function* (ctx, rt) {
|
|
937
962
|
return code(ctx, rt);
|
|
938
|
-
}
|
|
963
|
+
};
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/** This function gives the fill of a compile input: the value with an item in the place of each part. */
|
|
967
|
+
function fillOf(split: Extract<Split, { readonly ok: true }>, doc: Envelope): <P>(items: readonly P[]) => unknown {
|
|
968
|
+
return (items) => (split.parts.length === 0 ? doc.value : split.fill(items));
|
|
939
969
|
}
|
|
940
970
|
|
|
971
|
+
|
|
941
972
|
function interpret(fn: EvalFn, input: CompileInput, fill: <P>(handles: readonly P[]) => unknown): Code {
|
|
942
973
|
const { kind, typePath, doc, data, place } = input;
|
|
943
974
|
const compiled = input.parts;
|
|
@@ -1021,16 +1052,21 @@ export function prepare(machine: Machine, doc: unknown, options: PrepareOptions
|
|
|
1021
1052
|
};
|
|
1022
1053
|
}
|
|
1023
1054
|
const compiled: CompiledPart = { key: "", path: [], code: root.code, run: root.run };
|
|
1055
|
+
return planOf(machine, c.traced, compiled);
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
/** This function makes the object of a plan. Its closures keep only the machine and the compiled root. */
|
|
1059
|
+
function planOf(machine: Machine, traced: boolean, root: CompiledPart): Plan {
|
|
1024
1060
|
return {
|
|
1025
1061
|
machine,
|
|
1026
|
-
traced
|
|
1027
|
-
root
|
|
1062
|
+
traced,
|
|
1063
|
+
root,
|
|
1028
1064
|
evaluate(context: Context = makeContext(), evalOptions?: EvalOptions): Result {
|
|
1029
|
-
const s = new Session(machine, false,
|
|
1065
|
+
const s = new Session(machine, false, traced, undefined, undefined, evalOptions?.effects);
|
|
1030
1066
|
return root.code(rootContext(machine, context), s);
|
|
1031
1067
|
},
|
|
1032
1068
|
run(context: Context = makeContext(), runOptions: RunOptions = {}): Promise<Result> {
|
|
1033
|
-
const s = new Session(machine, true,
|
|
1069
|
+
const s = new Session(machine, true, traced, runOptions.perform, runOptions.signal, undefined);
|
|
1034
1070
|
return driveWaiting(root.run(rootContext(machine, context), s), runOptions.signal);
|
|
1035
1071
|
},
|
|
1036
1072
|
};
|