Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog.d/pts-r69a.md
Original file line number Diff line number Diff line change
@@ -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.
9 changes: 9 additions & 0 deletions src/tagged.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions test/export-surface.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"DecodeResult",
"EncodeReason",
"EncodeResult",
"ProjectedEvaluation",
"TaggedEvaluateOptions",
"TaggedExecution",
"decodeTagged",
Expand Down
15 changes: 14 additions & 1 deletion test/tagged.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
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,
type EncodeReason,
encodeTagged,
evaluateTagged,
executeTagged,
type ProjectedEvaluation,
type TaggedEvaluateOptions,
type TaggedExecution,
} from "../src/tagged.js";
Expand Down Expand Up @@ -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 };
Expand Down
Loading