diff --git a/changelog.d/pts-r69a.md b/changelog.d/pts-r69a.md new file mode 100644 index 0000000..cf4c952 --- /dev/null +++ b/changelog.d/pts-r69a.md @@ -0,0 +1,3 @@ +### Added + +- `ProjectedEvaluation` on the `./tagged` subpath names what `evaluateTagged` answers; it is the main entry point's `EvaluateResult` without the `ParseError` arm, so every value of it is also an `EvaluateResult`, and no answer changes. diff --git a/src/tagged.ts b/src/tagged.ts index a8b2872..884afea 100644 --- a/src/tagged.ts +++ b/src/tagged.ts @@ -44,6 +44,15 @@ import { isPlainMap, setKey } from "./maps.js"; import { DEPTH_LIMIT, enterContainer, type PlaceCount, visitPlace } from "./nesting.js"; import { Duration, Float, PDate, PDateTime, toHost, Undefined, type Value } from "./values.js"; +/** + * What `evaluateTagged` answers, named on this subpath so a host can write it. + * The main entry point's `EvaluateResult` is this type with a `ParseError` arm + * added, the arm a source text fails on; this entry point takes no source + * text, so it answers none, and every value of this type is also an + * `EvaluateResult`. + */ +export type { ProjectedEvaluation }; + /** * Why a text could not be decoded. `"depth_limit_exceeded"` is a text whose * brackets and braces nest past the depth limit this package declares. diff --git a/test/export-surface.json b/test/export-surface.json index 345e4d1..e39ef1f 100644 --- a/test/export-surface.json +++ b/test/export-surface.json @@ -74,6 +74,7 @@ "DecodeResult", "EncodeReason", "EncodeResult", + "ProjectedEvaluation", "TaggedEvaluateOptions", "TaggedExecution", "decodeTagged", diff --git a/test/tagged.test.ts b/test/tagged.test.ts index 668d270..db3f1ac 100644 --- a/test/tagged.test.ts +++ b/test/tagged.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest"; -import { compileProgram, type EvaluateOptions } from "../src/index.js"; +import { compileProgram, type EvaluateOptions, type EvaluateResult } from "../src/index.js"; import { type DecodeReason, decodeTagged, @@ -7,6 +7,7 @@ import { encodeTagged, evaluateTagged, executeTagged, + type ProjectedEvaluation, type TaggedEvaluateOptions, type TaggedExecution, } from "../src/tagged.js"; @@ -713,6 +714,18 @@ describe("evaluateTagged", () => { expect(outcome.error.type).toBe("UndefinedVariableError"); }); + // The answer has a name on this subpath, so a host holding one writes its + // type rather than reading it off the function, and the same value is one + // member of what the main entry point's `evaluate` answers. Sabotage: + // dropping the type's re-export from the subpath turns the export-surface + // pin red on its assertion and the typecheck stage red on this import. + it("answers the subpath's own evaluation result type", () => { + const outcome: ProjectedEvaluation = evaluateTagged([["load", "holds"]], { holds: 1 }); + expect(outcome).toEqual({ ok: true, value: 1 }); + const widened: EvaluateResult = outcome; + expect(widened).toBe(outcome); + }); + it("takes an options object written for the main entry point too", () => { const shared: EvaluateOptions = { onUnbound: "error" }; const options: TaggedEvaluateOptions = { ...shared, tagged: true };