diff --git a/packages/components/src/lib/plotParser.ts b/packages/components/src/lib/plotParser.ts
index 5b7ca31d..033ac2a3 100644
--- a/packages/components/src/lib/plotParser.ts
+++ b/packages/components/src/lib/plotParser.ts
@@ -1,5 +1,5 @@
+import * as yup from "yup";
import { Distribution, result, squiggleExpression } from "@quri/squiggle-lang";
-import { flattenResult, resultBind } from "./utility";
export type LabeledDistribution = { name: string; distribution: Distribution };
@@ -15,76 +15,47 @@ function ok(x: a): result {
return { tag: "Ok", value: x };
}
-function parseString(expr: squiggleExpression): result {
- if (expr.tag === "string") {
- return ok(expr.value);
- } else {
- return error("Expression was not string");
- }
-}
-
-function parseRecord(
- expr: squiggleExpression
-): result<{ [key: string]: squiggleExpression }, string> {
- if (expr.tag === "record") {
- return ok(expr.value);
- } else {
- return error("Expression was not a record");
- }
-}
-
-function parseDistribution(
- expr: squiggleExpression
-): result {
- if (expr.tag === "distribution") {
- return ok(expr.value);
- } else {
- return error("Expression was not a distribution");
- }
-}
-
-function parseArray(
- expr: squiggleExpression
-): result {
- if (expr.tag === "array") {
- return ok(expr.value);
- } else {
- return error("Expression was not a distribution");
- }
-}
-
-function parseField(
- record: { [key: string]: squiggleExpression },
- field: string,
- parser: (expr: squiggleExpression) => result
-): result {
- if (record[field]) {
- return parser(record[field]);
- } else {
- return error("record does not have field " + field);
- }
-}
-
-function parseLabeledDistribution(
- x: squiggleExpression
-): result {
- return resultBind(parseRecord(x), (record) =>
- resultBind(parseField(record, "name", parseString), (name) =>
- resultBind(
- parseField(record, "distribution", parseDistribution),
- (distribution) => ok({ name, distribution })
- )
- )
- );
-}
+const schema = yup
+ .object()
+ .strict()
+ .noUnknown()
+ .shape({
+ distributions: yup.object().shape({
+ tag: yup.mixed().oneOf(["array"]),
+ value: yup
+ .array()
+ .of(
+ yup.object().shape({
+ tag: yup.mixed().oneOf(["record"]),
+ value: yup.object().shape({
+ name: yup.object().shape({
+ tag: yup.mixed().oneOf(["string"]),
+ value: yup.string().required(),
+ }),
+ distribution: yup.object().shape({
+ tag: yup.mixed().oneOf(["distribution"]),
+ value: yup.mixed(),
+ }),
+ }),
+ })
+ )
+ .required(),
+ }),
+ });
export function parsePlot(record: {
[key: string]: squiggleExpression;
}): result {
- return resultBind(parseField(record, "distributions", parseArray), (array) =>
- resultBind(
- flattenResult(array.map(parseLabeledDistribution)),
- (distributions) => ok({ distributions })
- )
- );
+ try {
+ const plotRecord = schema.validateSync(record);
+ return ok({
+ distributions: plotRecord.distributions.value.map((x) => ({
+ name: x.value.name.value,
+ distribution: x.value.distribution.value,
+ })),
+ });
+ } catch (e) {
+ const message = e instanceof Error ? e.message : "Unknown error";
+ return error(message);
+ }
}