reimplement parsePlot with yup
This commit is contained in:
parent
61051ffe5f
commit
7866203ac4
|
@ -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<a, b>(x: a): result<a, b> {
|
|||
return { tag: "Ok", value: x };
|
||||
}
|
||||
|
||||
function parseString(expr: squiggleExpression): result<string, string> {
|
||||
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<Distribution, string> {
|
||||
if (expr.tag === "distribution") {
|
||||
return ok(expr.value);
|
||||
} else {
|
||||
return error("Expression was not a distribution");
|
||||
}
|
||||
}
|
||||
|
||||
function parseArray(
|
||||
expr: squiggleExpression
|
||||
): result<squiggleExpression[], string> {
|
||||
if (expr.tag === "array") {
|
||||
return ok(expr.value);
|
||||
} else {
|
||||
return error("Expression was not a distribution");
|
||||
}
|
||||
}
|
||||
|
||||
function parseField<a>(
|
||||
record: { [key: string]: squiggleExpression },
|
||||
field: string,
|
||||
parser: (expr: squiggleExpression) => result<a, string>
|
||||
): result<a, string> {
|
||||
if (record[field]) {
|
||||
return parser(record[field]);
|
||||
} else {
|
||||
return error("record does not have field " + field);
|
||||
}
|
||||
}
|
||||
|
||||
function parseLabeledDistribution(
|
||||
x: squiggleExpression
|
||||
): result<LabeledDistribution, string> {
|
||||
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<Plot, string> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user