squiggle/packages/squiggle-lang/src/js/index.ts

150 lines
4.3 KiB
TypeScript
Raw Normal View History

import * as _ from "lodash";
import {
samplingParams,
2022-04-29 13:50:57 +00:00
evaluateUsingExternalBindings,
evaluatePartialUsingExternalBindings,
externalBindings,
expressionValue,
errorValue,
} from "../rescript/TypescriptInterface.gen";
export {
makeSampleSetDist,
errorValueToString,
distributionErrorToString,
} from "../rescript/TypescriptInterface.gen";
2022-04-29 19:02:43 +00:00
export type {
samplingParams,
errorValue,
externalBindings as bindings,
parameters,
};
import {
jsValueToBinding,
jsValue,
rescriptExport,
squiggleExpression,
convertRawToTypescript,
} from "./rescript_interop";
import { result, resultMap, tag, tagged } from "./types";
import { Distribution } from "./distribution";
export { Distribution, squiggleExpression, result };
2022-04-11 03:16:31 +00:00
export let defaultSamplingInputs: samplingParams = {
sampleCount: 10000,
xyPointLength: 10000,
};
2022-04-11 03:16:31 +00:00
export function run(
squiggleString: string,
2022-04-29 13:50:57 +00:00
bindings?: externalBindings,
2022-04-29 18:46:44 +00:00
samplingInputs?: samplingParams,
parameters?: parameters
2022-04-11 03:16:31 +00:00
): result<squiggleExpression, errorValue> {
2022-04-29 19:02:43 +00:00
let b = bindings ? bindings : defaultBindings;
let p = parameters ? parameters : defaultParameters;
2022-04-11 03:16:31 +00:00
let si: samplingParams = samplingInputs
? samplingInputs
: defaultSamplingInputs;
2022-04-29 13:50:57 +00:00
let result: result<expressionValue, errorValue> =
2022-04-29 18:46:44 +00:00
evaluateUsingExternalBindings(squiggleString, mergeParameters(b, p));
return resultMap(result, (x) => createTsExport(x, si));
2022-04-11 03:16:31 +00:00
}
2022-04-29 13:50:57 +00:00
// Run Partial. A partial is a block of code that doesn't return a value
export function runPartial(
squiggleString: string,
2022-04-29 18:46:44 +00:00
bindings?: externalBindings,
_samplingInputs?: samplingParams,
parameters?: parameters
2022-04-29 13:50:57 +00:00
): result<externalBindings, errorValue> {
2022-04-29 19:02:43 +00:00
let b = bindings ? bindings : defaultBindings;
let p = parameters ? parameters : defaultParameters;
2022-04-29 18:46:44 +00:00
return evaluatePartialUsingExternalBindings(
squiggleString,
mergeParameters(b, p)
);
}
function mergeParameters(
bindings: externalBindings,
parameters: parameters
): externalBindings {
let transformedParameters = Object.fromEntries(
2022-04-29 18:46:44 +00:00
Object.entries(parameters).map(([key, value]) => [
"$" + key,
jsValueToBinding(value),
])
);
return _.merge(bindings, transformedParameters);
2022-04-29 18:46:44 +00:00
}
type parameters = { [key: string]: jsValue };
2022-04-29 19:02:43 +00:00
export let defaultParameters: parameters = {};
export let defaultBindings: externalBindings = {};
function createTsExport(
x: expressionValue,
sampEnv: samplingParams
): squiggleExpression {
switch (x.tag) {
case "EvArray":
// genType doesn't convert anything more than 2 layers down into {tag: x, value: x}
// format, leaving it as the raw values. This converts the raw values
// directly into typescript values.
//
// The casting here is because genType is about the types of the returned
// values, claiming they are fully recursive when that's not actually the
// case
return tag(
"array",
x.value.map((arrayItem): squiggleExpression => {
switch (arrayItem.tag) {
case "EvRecord":
return tag(
"record",
_.mapValues(arrayItem.value, (recordValue: unknown) =>
convertRawToTypescript(recordValue as rescriptExport, sampEnv)
)
);
case "EvArray":
let y = arrayItem.value as unknown as rescriptExport[];
return tag(
"array",
y.map((childArrayItem) =>
convertRawToTypescript(childArrayItem, sampEnv)
)
);
default:
return createTsExport(arrayItem, sampEnv);
}
})
);
case "EvBool":
return tag("boolean", x.value);
case "EvCall":
return tag("call", x.value);
case "EvDistribution":
return tag("distribution", new Distribution(x.value, sampEnv));
case "EvNumber":
return tag("number", x.value);
case "EvRecord":
// genType doesn't support records, so we have to do the raw conversion ourself
let result: tagged<"record", { [key: string]: squiggleExpression }> = tag(
"record",
_.mapValues(x.value, (x: unknown) =>
convertRawToTypescript(x as rescriptExport, sampEnv)
)
);
return result;
case "EvString":
return tag("string", x.value);
case "EvSymbol":
return tag("symbol", x.value);
}
}