Merge branch 'epic-reducer-project' of github.com:quantified-uncertainty/squiggle into epic-reducer-project
This commit is contained in:
commit
1fe0aefd6b
|
@ -1,11 +1,11 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import {
|
import {
|
||||||
Distribution,
|
SqDistribution,
|
||||||
result,
|
result,
|
||||||
distributionError,
|
SqDistributionError,
|
||||||
distributionErrorToString,
|
|
||||||
squiggleExpression,
|
|
||||||
resultMap,
|
resultMap,
|
||||||
|
SqRecord,
|
||||||
|
environment,
|
||||||
} from "@quri/squiggle-lang";
|
} from "@quri/squiggle-lang";
|
||||||
import { Vega } from "react-vega";
|
import { Vega } from "react-vega";
|
||||||
import { ErrorAlert } from "./Alert";
|
import { ErrorAlert } from "./Alert";
|
||||||
|
@ -28,17 +28,16 @@ export type DistributionPlottingSettings = {
|
||||||
|
|
||||||
export type DistributionChartProps = {
|
export type DistributionChartProps = {
|
||||||
plot: Plot;
|
plot: Plot;
|
||||||
|
environment: environment;
|
||||||
width?: number;
|
width?: number;
|
||||||
height: number;
|
height: number;
|
||||||
} & DistributionPlottingSettings;
|
} & DistributionPlottingSettings;
|
||||||
|
|
||||||
export function defaultPlot(distribution: Distribution): Plot {
|
export function defaultPlot(distribution: SqDistribution): Plot {
|
||||||
return { distributions: [{ name: "default", distribution }] };
|
return { distributions: [{ name: "default", distribution }] };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makePlot(record: {
|
export function makePlot(record: SqRecord): Plot | void {
|
||||||
[key: string]: squiggleExpression;
|
|
||||||
}): Plot | void {
|
|
||||||
const plotResult = parsePlot(record);
|
const plotResult = parsePlot(record);
|
||||||
if (plotResult.tag === "Ok") {
|
if (plotResult.tag === "Ok") {
|
||||||
return plotResult.value;
|
return plotResult.value;
|
||||||
|
@ -46,22 +45,29 @@ export function makePlot(record: {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DistributionChart: React.FC<DistributionChartProps> = (props) => {
|
export const DistributionChart: React.FC<DistributionChartProps> = (props) => {
|
||||||
const { plot, height, showSummary, width, logX, actions = false } = props;
|
const {
|
||||||
|
plot,
|
||||||
|
environment,
|
||||||
|
height,
|
||||||
|
showSummary,
|
||||||
|
width,
|
||||||
|
logX,
|
||||||
|
actions = false,
|
||||||
|
} = props;
|
||||||
const [sized] = useSize((size) => {
|
const [sized] = useSize((size) => {
|
||||||
let shapes = flattenResult(
|
const shapes = flattenResult(
|
||||||
plot.distributions.map((x) =>
|
plot.distributions.map((x) => {
|
||||||
resultMap(x.distribution.pointSet(), (shape) => ({
|
return resultMap(x.distribution.pointSet(environment), (pointSet) => ({
|
||||||
|
...pointSet.asShape(),
|
||||||
name: x.name,
|
name: x.name,
|
||||||
// color: x.color, // not supported yet
|
// color: x.color, // not supported yet
|
||||||
continuous: shape.continuous,
|
}));
|
||||||
discrete: shape.discrete,
|
})
|
||||||
}))
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
if (shapes.tag === "Error") {
|
if (shapes.tag === "Error") {
|
||||||
return (
|
return (
|
||||||
<ErrorAlert heading="Distribution Error">
|
<ErrorAlert heading="Distribution Error">
|
||||||
{distributionErrorToString(shapes.value)}
|
{shapes.value.toString()}
|
||||||
</ErrorAlert>
|
</ErrorAlert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -96,7 +102,10 @@ export const DistributionChart: React.FC<DistributionChartProps> = (props) => {
|
||||||
)}
|
)}
|
||||||
<div className="flex justify-center">
|
<div className="flex justify-center">
|
||||||
{showSummary && plot.distributions.length === 1 && (
|
{showSummary && plot.distributions.length === 1 && (
|
||||||
<SummaryTable distribution={plot.distributions[0].distribution} />
|
<SummaryTable
|
||||||
|
distribution={plot.distributions[0].distribution}
|
||||||
|
environment={environment}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -120,32 +129,36 @@ const Cell: React.FC<{ children: React.ReactNode }> = ({ children }) => (
|
||||||
);
|
);
|
||||||
|
|
||||||
type SummaryTableProps = {
|
type SummaryTableProps = {
|
||||||
distribution: Distribution;
|
distribution: SqDistribution;
|
||||||
|
environment: environment;
|
||||||
};
|
};
|
||||||
|
|
||||||
const SummaryTable: React.FC<SummaryTableProps> = ({ distribution }) => {
|
const SummaryTable: React.FC<SummaryTableProps> = ({
|
||||||
const mean = distribution.mean();
|
distribution,
|
||||||
const stdev = distribution.stdev();
|
environment,
|
||||||
const p5 = distribution.inv(0.05);
|
}) => {
|
||||||
const p10 = distribution.inv(0.1);
|
const mean = distribution.mean(environment);
|
||||||
const p25 = distribution.inv(0.25);
|
const stdev = distribution.stdev(environment);
|
||||||
const p50 = distribution.inv(0.5);
|
const p5 = distribution.inv(environment, 0.05);
|
||||||
const p75 = distribution.inv(0.75);
|
const p10 = distribution.inv(environment, 0.1);
|
||||||
const p90 = distribution.inv(0.9);
|
const p25 = distribution.inv(environment, 0.25);
|
||||||
const p95 = distribution.inv(0.95);
|
const p50 = distribution.inv(environment, 0.5);
|
||||||
|
const p75 = distribution.inv(environment, 0.75);
|
||||||
|
const p90 = distribution.inv(environment, 0.9);
|
||||||
|
const p95 = distribution.inv(environment, 0.95);
|
||||||
|
|
||||||
const hasResult = (x: result<number, distributionError>): boolean =>
|
const hasResult = (x: result<number, SqDistributionError>): boolean =>
|
||||||
x.tag === "Ok";
|
x.tag === "Ok";
|
||||||
|
|
||||||
const unwrapResult = (
|
const unwrapResult = (
|
||||||
x: result<number, distributionError>
|
x: result<number, SqDistributionError>
|
||||||
): React.ReactNode => {
|
): React.ReactNode => {
|
||||||
if (x.tag === "Ok") {
|
if (x.tag === "Ok") {
|
||||||
return <NumberShower number={x.value} />;
|
return <NumberShower number={x.value} />;
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<ErrorAlert heading="Distribution Error">
|
<ErrorAlert heading="Distribution Error">
|
||||||
{distributionErrorToString(x.value)}
|
{x.value.toString()}
|
||||||
</ErrorAlert>
|
</ErrorAlert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import {
|
import { SqLambda, environment, SqValueTag } from "@quri/squiggle-lang";
|
||||||
lambdaValue,
|
|
||||||
environment,
|
|
||||||
runForeign,
|
|
||||||
errorValueToString,
|
|
||||||
} from "@quri/squiggle-lang";
|
|
||||||
import { FunctionChart1Dist } from "./FunctionChart1Dist";
|
import { FunctionChart1Dist } from "./FunctionChart1Dist";
|
||||||
import { FunctionChart1Number } from "./FunctionChart1Number";
|
import { FunctionChart1Number } from "./FunctionChart1Number";
|
||||||
import { DistributionPlottingSettings } from "./DistributionChart";
|
import { DistributionPlottingSettings } from "./DistributionChart";
|
||||||
|
@ -17,7 +12,7 @@ export type FunctionChartSettings = {
|
||||||
};
|
};
|
||||||
|
|
||||||
interface FunctionChartProps {
|
interface FunctionChartProps {
|
||||||
fn: lambdaValue;
|
fn: SqLambda;
|
||||||
chartSettings: FunctionChartSettings;
|
chartSettings: FunctionChartSettings;
|
||||||
distributionPlotSettings: DistributionPlottingSettings;
|
distributionPlotSettings: DistributionPlottingSettings;
|
||||||
environment: environment;
|
environment: environment;
|
||||||
|
@ -38,8 +33,8 @@ export const FunctionChart: React.FC<FunctionChartProps> = ({
|
||||||
</MessageAlert>
|
</MessageAlert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const result1 = runForeign(fn, [chartSettings.start], environment);
|
const result1 = fn.call([chartSettings.start]);
|
||||||
const result2 = runForeign(fn, [chartSettings.stop], environment);
|
const result2 = fn.call([chartSettings.stop]);
|
||||||
const getValidResult = () => {
|
const getValidResult = () => {
|
||||||
if (result1.tag === "Ok") {
|
if (result1.tag === "Ok") {
|
||||||
return result1;
|
return result1;
|
||||||
|
@ -53,14 +48,12 @@ export const FunctionChart: React.FC<FunctionChartProps> = ({
|
||||||
|
|
||||||
if (validResult.tag === "Error") {
|
if (validResult.tag === "Error") {
|
||||||
return (
|
return (
|
||||||
<ErrorAlert heading="Error">
|
<ErrorAlert heading="Error">{validResult.value.toString()}</ErrorAlert>
|
||||||
{errorValueToString(validResult.value)}
|
|
||||||
</ErrorAlert>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (validResult.value.tag) {
|
switch (validResult.value.tag) {
|
||||||
case "distribution":
|
case SqValueTag.Distribution:
|
||||||
return (
|
return (
|
||||||
<FunctionChart1Dist
|
<FunctionChart1Dist
|
||||||
fn={fn}
|
fn={fn}
|
||||||
|
@ -70,7 +63,7 @@ export const FunctionChart: React.FC<FunctionChartProps> = ({
|
||||||
distributionPlotSettings={distributionPlotSettings}
|
distributionPlotSettings={distributionPlotSettings}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case "number":
|
case SqValueTag.Number:
|
||||||
return (
|
return (
|
||||||
<FunctionChart1Number
|
<FunctionChart1Number
|
||||||
fn={fn}
|
fn={fn}
|
||||||
|
|
|
@ -2,14 +2,13 @@ import * as React from "react";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import type { Spec } from "vega";
|
import type { Spec } from "vega";
|
||||||
import {
|
import {
|
||||||
Distribution,
|
SqDistribution,
|
||||||
result,
|
result,
|
||||||
lambdaValue,
|
SqLambda,
|
||||||
environment,
|
environment,
|
||||||
runForeign,
|
SqError,
|
||||||
squiggleExpression,
|
SqValue,
|
||||||
errorValue,
|
SqValueTag,
|
||||||
errorValueToString,
|
|
||||||
} from "@quri/squiggle-lang";
|
} from "@quri/squiggle-lang";
|
||||||
import { createClassFromSpec } from "react-vega";
|
import { createClassFromSpec } from "react-vega";
|
||||||
import * as percentilesSpec from "../vega-specs/spec-percentiles.json";
|
import * as percentilesSpec from "../vega-specs/spec-percentiles.json";
|
||||||
|
@ -46,7 +45,7 @@ export type FunctionChartSettings = {
|
||||||
};
|
};
|
||||||
|
|
||||||
interface FunctionChart1DistProps {
|
interface FunctionChart1DistProps {
|
||||||
fn: lambdaValue;
|
fn: SqLambda;
|
||||||
chartSettings: FunctionChartSettings;
|
chartSettings: FunctionChartSettings;
|
||||||
distributionPlotSettings: DistributionPlottingSettings;
|
distributionPlotSettings: DistributionPlottingSettings;
|
||||||
environment: environment;
|
environment: environment;
|
||||||
|
@ -77,9 +76,17 @@ type errors = _.Dictionary<
|
||||||
}[]
|
}[]
|
||||||
>;
|
>;
|
||||||
|
|
||||||
type point = { x: number; value: result<Distribution, string> };
|
type point = { x: number; value: result<SqDistribution, string> };
|
||||||
|
|
||||||
let getPercentiles = ({ chartSettings, fn, environment }) => {
|
let getPercentiles = ({
|
||||||
|
chartSettings,
|
||||||
|
fn,
|
||||||
|
environment,
|
||||||
|
}: {
|
||||||
|
chartSettings: FunctionChartSettings;
|
||||||
|
fn: SqLambda;
|
||||||
|
environment: environment;
|
||||||
|
}) => {
|
||||||
let chartPointsToRender = _rangeByCount(
|
let chartPointsToRender = _rangeByCount(
|
||||||
chartSettings.start,
|
chartSettings.start,
|
||||||
chartSettings.stop,
|
chartSettings.stop,
|
||||||
|
@ -87,9 +94,9 @@ let getPercentiles = ({ chartSettings, fn, environment }) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
let chartPointsData: point[] = chartPointsToRender.map((x) => {
|
let chartPointsData: point[] = chartPointsToRender.map((x) => {
|
||||||
let result = runForeign(fn, [x], environment);
|
let result = fn.call([x]);
|
||||||
if (result.tag === "Ok") {
|
if (result.tag === "Ok") {
|
||||||
if (result.value.tag === "distribution") {
|
if (result.value.tag === SqValueTag.Distribution) {
|
||||||
return { x, value: { tag: "Ok", value: result.value.value } };
|
return { x, value: { tag: "Ok", value: result.value.value } };
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
|
@ -104,13 +111,13 @@ let getPercentiles = ({ chartSettings, fn, environment }) => {
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
x,
|
x,
|
||||||
value: { tag: "Error", value: errorValueToString(result.value) },
|
value: { tag: "Error", value: result.value.toString() },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let initialPartition: [
|
let initialPartition: [
|
||||||
{ x: number; value: Distribution }[],
|
{ x: number; value: SqDistribution }[],
|
||||||
{ x: number; value: string }[]
|
{ x: number; value: string }[]
|
||||||
] = [[], []];
|
] = [[], []];
|
||||||
|
|
||||||
|
@ -129,22 +136,22 @@ let getPercentiles = ({ chartSettings, fn, environment }) => {
|
||||||
// We convert it to to a pointSet distribution first, so that in case its a sample set
|
// We convert it to to a pointSet distribution first, so that in case its a sample set
|
||||||
// distribution, it doesn't internally convert it to a pointSet distribution for every
|
// distribution, it doesn't internally convert it to a pointSet distribution for every
|
||||||
// single inv() call.
|
// single inv() call.
|
||||||
let toPointSet: Distribution = unwrap(value.toPointSet());
|
let toPointSet = unwrap(value.pointSet(environment)).asDistribution();
|
||||||
return {
|
return {
|
||||||
x: x,
|
x: x,
|
||||||
p1: unwrap(toPointSet.inv(0.01)),
|
p1: unwrap(toPointSet.inv(environment, 0.01)),
|
||||||
p5: unwrap(toPointSet.inv(0.05)),
|
p5: unwrap(toPointSet.inv(environment, 0.05)),
|
||||||
p10: unwrap(toPointSet.inv(0.1)),
|
p10: unwrap(toPointSet.inv(environment, 0.1)),
|
||||||
p20: unwrap(toPointSet.inv(0.2)),
|
p20: unwrap(toPointSet.inv(environment, 0.2)),
|
||||||
p30: unwrap(toPointSet.inv(0.3)),
|
p30: unwrap(toPointSet.inv(environment, 0.3)),
|
||||||
p40: unwrap(toPointSet.inv(0.4)),
|
p40: unwrap(toPointSet.inv(environment, 0.4)),
|
||||||
p50: unwrap(toPointSet.inv(0.5)),
|
p50: unwrap(toPointSet.inv(environment, 0.5)),
|
||||||
p60: unwrap(toPointSet.inv(0.6)),
|
p60: unwrap(toPointSet.inv(environment, 0.6)),
|
||||||
p70: unwrap(toPointSet.inv(0.7)),
|
p70: unwrap(toPointSet.inv(environment, 0.7)),
|
||||||
p80: unwrap(toPointSet.inv(0.8)),
|
p80: unwrap(toPointSet.inv(environment, 0.8)),
|
||||||
p90: unwrap(toPointSet.inv(0.9)),
|
p90: unwrap(toPointSet.inv(environment, 0.9)),
|
||||||
p95: unwrap(toPointSet.inv(0.95)),
|
p95: unwrap(toPointSet.inv(environment, 0.95)),
|
||||||
p99: unwrap(toPointSet.inv(0.99)),
|
p99: unwrap(toPointSet.inv(environment, 0.99)),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -168,19 +175,20 @@ export const FunctionChart1Dist: React.FC<FunctionChart1DistProps> = ({
|
||||||
const signalListeners = { mousemove: handleHover, mouseout: handleOut };
|
const signalListeners = { mousemove: handleHover, mouseout: handleOut };
|
||||||
|
|
||||||
//TODO: This custom error handling is a bit hacky and should be improved.
|
//TODO: This custom error handling is a bit hacky and should be improved.
|
||||||
let mouseItem: result<squiggleExpression, errorValue> = !!mouseOverlay
|
let mouseItem: result<SqValue, SqError> = !!mouseOverlay
|
||||||
? runForeign(fn, [mouseOverlay], environment)
|
? fn.call([mouseOverlay])
|
||||||
: {
|
: {
|
||||||
tag: "Error",
|
tag: "Error",
|
||||||
value: {
|
value: SqError.createOtherError(
|
||||||
tag: "RETodo",
|
"Hover x-coordinate returned NaN. Expected a number."
|
||||||
value: "Hover x-coordinate returned NaN. Expected a number.",
|
),
|
||||||
},
|
|
||||||
};
|
};
|
||||||
let showChart =
|
let showChart =
|
||||||
mouseItem.tag === "Ok" && mouseItem.value.tag === "distribution" ? (
|
mouseItem.tag === "Ok" &&
|
||||||
|
mouseItem.value.tag === SqValueTag.Distribution ? (
|
||||||
<DistributionChart
|
<DistributionChart
|
||||||
plot={defaultPlot(mouseItem.value.value)}
|
plot={defaultPlot(mouseItem.value.value)}
|
||||||
|
environment={environment}
|
||||||
width={400}
|
width={400}
|
||||||
height={50}
|
height={50}
|
||||||
{...distributionPlotSettings}
|
{...distributionPlotSettings}
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import type { Spec } from "vega";
|
import type { Spec } from "vega";
|
||||||
import {
|
import { result, SqLambda, environment, SqValueTag } from "@quri/squiggle-lang";
|
||||||
result,
|
|
||||||
lambdaValue,
|
|
||||||
environment,
|
|
||||||
runForeign,
|
|
||||||
errorValueToString,
|
|
||||||
} from "@quri/squiggle-lang";
|
|
||||||
import { createClassFromSpec } from "react-vega";
|
import { createClassFromSpec } from "react-vega";
|
||||||
import * as lineChartSpec from "../vega-specs/spec-line-chart.json";
|
import * as lineChartSpec from "../vega-specs/spec-line-chart.json";
|
||||||
import { ErrorAlert } from "./Alert";
|
import { ErrorAlert } from "./Alert";
|
||||||
|
import { squiggleValueTag } from "@quri/squiggle-lang/src/rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_tag";
|
||||||
|
|
||||||
let SquiggleLineChart = createClassFromSpec({
|
let SquiggleLineChart = createClassFromSpec({
|
||||||
spec: lineChartSpec as Spec,
|
spec: lineChartSpec as Spec,
|
||||||
|
@ -30,7 +25,7 @@ export type FunctionChartSettings = {
|
||||||
};
|
};
|
||||||
|
|
||||||
interface FunctionChart1NumberProps {
|
interface FunctionChart1NumberProps {
|
||||||
fn: lambdaValue;
|
fn: SqLambda;
|
||||||
chartSettings: FunctionChartSettings;
|
chartSettings: FunctionChartSettings;
|
||||||
environment: environment;
|
environment: environment;
|
||||||
height: number;
|
height: number;
|
||||||
|
@ -38,7 +33,15 @@ interface FunctionChart1NumberProps {
|
||||||
|
|
||||||
type point = { x: number; value: result<number, string> };
|
type point = { x: number; value: result<number, string> };
|
||||||
|
|
||||||
let getFunctionImage = ({ chartSettings, fn, environment }) => {
|
let getFunctionImage = ({
|
||||||
|
chartSettings,
|
||||||
|
fn,
|
||||||
|
environment,
|
||||||
|
}: {
|
||||||
|
chartSettings: FunctionChartSettings;
|
||||||
|
fn: SqLambda;
|
||||||
|
environment: environment;
|
||||||
|
}) => {
|
||||||
let chartPointsToRender = _rangeByCount(
|
let chartPointsToRender = _rangeByCount(
|
||||||
chartSettings.start,
|
chartSettings.start,
|
||||||
chartSettings.stop,
|
chartSettings.stop,
|
||||||
|
@ -46,9 +49,9 @@ let getFunctionImage = ({ chartSettings, fn, environment }) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
let chartPointsData: point[] = chartPointsToRender.map((x) => {
|
let chartPointsData: point[] = chartPointsToRender.map((x) => {
|
||||||
let result = runForeign(fn, [x], environment);
|
let result = fn.call([x]);
|
||||||
if (result.tag === "Ok") {
|
if (result.tag === "Ok") {
|
||||||
if (result.value.tag == "number") {
|
if (result.value.tag === SqValueTag.Number) {
|
||||||
return { x, value: { tag: "Ok", value: result.value.value } };
|
return { x, value: { tag: "Ok", value: result.value.value } };
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
|
@ -62,7 +65,7 @@ let getFunctionImage = ({ chartSettings, fn, environment }) => {
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
x,
|
x,
|
||||||
value: { tag: "Error", value: errorValueToString(result.value) },
|
value: { tag: "Error", value: result.value.toString() },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import {
|
import {
|
||||||
squiggleExpression,
|
SqValue,
|
||||||
bindings,
|
|
||||||
environment,
|
environment,
|
||||||
jsImports,
|
|
||||||
defaultImports,
|
|
||||||
defaultBindings,
|
|
||||||
defaultEnvironment,
|
defaultEnvironment,
|
||||||
|
resultMap,
|
||||||
|
SqValueLocation,
|
||||||
|
SqValueTag,
|
||||||
} from "@quri/squiggle-lang";
|
} from "@quri/squiggle-lang";
|
||||||
import { useSquiggle } from "../lib/hooks";
|
import { useSquiggle } from "../lib/hooks";
|
||||||
import { SquiggleViewer } from "./SquiggleViewer";
|
import { SquiggleViewer } from "./SquiggleViewer";
|
||||||
|
@ -27,14 +26,12 @@ export interface SquiggleChartProps {
|
||||||
/** If the result is a function, the amount of stops sampled */
|
/** If the result is a function, the amount of stops sampled */
|
||||||
diagramCount?: number;
|
diagramCount?: number;
|
||||||
/** When the squiggle code gets reevaluated */
|
/** When the squiggle code gets reevaluated */
|
||||||
onChange?(expr: squiggleExpression | undefined): void;
|
onChange?(expr: SqValue | undefined): void;
|
||||||
/** CSS width of the element */
|
/** CSS width of the element */
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number;
|
height?: number;
|
||||||
/** Bindings of previous variables declared */
|
|
||||||
bindings?: bindings;
|
|
||||||
/** JS imported parameters */
|
/** JS imported parameters */
|
||||||
jsImports?: jsImports;
|
// jsImports?: jsImports;
|
||||||
/** Whether to show a summary of the distribution */
|
/** Whether to show a summary of the distribution */
|
||||||
showSummary?: boolean;
|
showSummary?: boolean;
|
||||||
/** Set the x scale to be logarithmic by deault */
|
/** Set the x scale to be logarithmic by deault */
|
||||||
|
@ -65,8 +62,7 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = React.memo(
|
||||||
environment,
|
environment,
|
||||||
onChange = defaultOnChange, // defaultOnChange must be constant, don't move its definition here
|
onChange = defaultOnChange, // defaultOnChange must be constant, don't move its definition here
|
||||||
height = 200,
|
height = 200,
|
||||||
bindings = defaultBindings,
|
// jsImports = defaultImports,
|
||||||
jsImports = defaultImports,
|
|
||||||
showSummary = false,
|
showSummary = false,
|
||||||
width,
|
width,
|
||||||
logX = false,
|
logX = false,
|
||||||
|
@ -82,11 +78,10 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = React.memo(
|
||||||
distributionChartActions,
|
distributionChartActions,
|
||||||
enableLocalSettings = false,
|
enableLocalSettings = false,
|
||||||
}) => {
|
}) => {
|
||||||
const result = useSquiggle({
|
const { result, bindings } = useSquiggle({
|
||||||
code,
|
code,
|
||||||
bindings,
|
|
||||||
environment,
|
environment,
|
||||||
jsImports,
|
// jsImports,
|
||||||
onChange,
|
onChange,
|
||||||
executionId,
|
executionId,
|
||||||
});
|
});
|
||||||
|
@ -109,9 +104,13 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = React.memo(
|
||||||
count: diagramCount,
|
count: diagramCount,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const resultToRender = resultMap(result, (value) =>
|
||||||
|
value.tag === SqValueTag.Void ? bindings.asValue() : value
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SquiggleViewer
|
<SquiggleViewer
|
||||||
result={result}
|
result={resultToRender}
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
distributionPlotSettings={distributionPlotSettings}
|
distributionPlotSettings={distributionPlotSettings}
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { CodeEditor } from "./CodeEditor";
|
import { CodeEditor } from "./CodeEditor";
|
||||||
import { environment, bindings, jsImports } from "@quri/squiggle-lang";
|
|
||||||
import { defaultImports, defaultBindings } from "@quri/squiggle-lang";
|
|
||||||
import { SquiggleContainer } from "./SquiggleContainer";
|
import { SquiggleContainer } from "./SquiggleContainer";
|
||||||
import { SquiggleChart, SquiggleChartProps } from "./SquiggleChart";
|
import { SquiggleChart, SquiggleChartProps } from "./SquiggleChart";
|
||||||
import { useSquigglePartial, useMaybeControlledValue } from "../lib/hooks";
|
import { useMaybeControlledValue } from "../lib/hooks";
|
||||||
import { SquiggleErrorAlert } from "./SquiggleErrorAlert";
|
|
||||||
|
|
||||||
const WrappedCodeEditor: React.FC<{
|
const WrappedCodeEditor: React.FC<{
|
||||||
code: string;
|
code: string;
|
||||||
|
@ -42,51 +39,3 @@ export const SquiggleEditor: React.FC<SquiggleEditorProps> = (props) => {
|
||||||
</SquiggleContainer>
|
</SquiggleContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface SquigglePartialProps {
|
|
||||||
/** The text inside the input (controlled) */
|
|
||||||
code?: string;
|
|
||||||
/** The default text inside the input (unControlled) */
|
|
||||||
defaultCode?: string;
|
|
||||||
/** when the environment changes. Used again for notebook magic*/
|
|
||||||
onChange?(expr: bindings | undefined): void;
|
|
||||||
/** When the code changes */
|
|
||||||
onCodeChange?(code: string): void;
|
|
||||||
/** Previously declared variables */
|
|
||||||
bindings?: bindings;
|
|
||||||
/** If the output requires monte carlo sampling, the amount of samples */
|
|
||||||
environment?: environment;
|
|
||||||
/** Variables imported from js */
|
|
||||||
jsImports?: jsImports;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SquigglePartial: React.FC<SquigglePartialProps> = ({
|
|
||||||
code: controlledCode,
|
|
||||||
defaultCode = "",
|
|
||||||
onChange,
|
|
||||||
onCodeChange,
|
|
||||||
bindings = defaultBindings,
|
|
||||||
environment,
|
|
||||||
jsImports = defaultImports,
|
|
||||||
}: SquigglePartialProps) => {
|
|
||||||
const [code, setCode] = useMaybeControlledValue<string>({
|
|
||||||
value: controlledCode,
|
|
||||||
defaultValue: defaultCode,
|
|
||||||
onChange: onCodeChange,
|
|
||||||
});
|
|
||||||
|
|
||||||
const result = useSquigglePartial({
|
|
||||||
code,
|
|
||||||
bindings,
|
|
||||||
environment,
|
|
||||||
jsImports,
|
|
||||||
onChange,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SquiggleContainer>
|
|
||||||
<WrappedCodeEditor code={code} setCode={setCode} />
|
|
||||||
{result.tag !== "Ok" ? <SquiggleErrorAlert error={result.value} /> : null}
|
|
||||||
</SquiggleContainer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
import React from "react";
|
|
||||||
import { SquiggleEditor } from "./SquiggleEditor";
|
|
||||||
import type { SquiggleEditorProps } from "./SquiggleEditor";
|
|
||||||
import { runPartial, defaultBindings } from "@quri/squiggle-lang";
|
|
||||||
import type {
|
|
||||||
result,
|
|
||||||
errorValue,
|
|
||||||
bindings as bindingsType,
|
|
||||||
} from "@quri/squiggle-lang";
|
|
||||||
|
|
||||||
function resultDefault(x: result<bindingsType, errorValue>): bindingsType {
|
|
||||||
switch (x.tag) {
|
|
||||||
case "Ok":
|
|
||||||
return x.value;
|
|
||||||
case "Error":
|
|
||||||
return defaultBindings;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SquiggleEditorWithImportedBindingsProps = SquiggleEditorProps & {
|
|
||||||
bindingsImportUrl: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SquiggleEditorWithImportedBindings: React.FC<
|
|
||||||
SquiggleEditorWithImportedBindingsProps
|
|
||||||
> = (props) => {
|
|
||||||
const { bindingsImportUrl, ...editorProps } = props;
|
|
||||||
const [bindingsResult, setBindingsResult] = React.useState({
|
|
||||||
tag: "Ok",
|
|
||||||
value: defaultBindings,
|
|
||||||
} as result<bindingsType, errorValue>);
|
|
||||||
React.useEffect(() => {
|
|
||||||
async function retrieveBindings(fileName: string) {
|
|
||||||
let contents = await fetch(fileName).then((response) => {
|
|
||||||
return response.text();
|
|
||||||
});
|
|
||||||
setBindingsResult(
|
|
||||||
runPartial(
|
|
||||||
contents,
|
|
||||||
editorProps.bindings,
|
|
||||||
editorProps.environment,
|
|
||||||
editorProps.jsImports
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
retrieveBindings(bindingsImportUrl);
|
|
||||||
}, [bindingsImportUrl]);
|
|
||||||
const deliveredBindings = resultDefault(bindingsResult);
|
|
||||||
return (
|
|
||||||
<SquiggleEditor {...{ ...editorProps, bindings: deliveredBindings }} />
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { errorValue, errorValueToString } from "@quri/squiggle-lang";
|
import { SqError } from "@quri/squiggle-lang";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { ErrorAlert } from "./Alert";
|
import { ErrorAlert } from "./Alert";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
error: errorValue;
|
error: SqError;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SquiggleErrorAlert: React.FC<Props> = ({ error }) => {
|
export const SquiggleErrorAlert: React.FC<Props> = ({ error }) => {
|
||||||
return <ErrorAlert heading="Error">{errorValueToString(error)}</ErrorAlert>;
|
return <ErrorAlert heading="Error">{error.toString()}</ErrorAlert>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,7 +24,7 @@ import {
|
||||||
} from "@heroicons/react/solid";
|
} from "@heroicons/react/solid";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
import { defaultBindings, environment } from "@quri/squiggle-lang";
|
import { environment } from "@quri/squiggle-lang";
|
||||||
|
|
||||||
import { SquiggleChart, SquiggleChartProps } from "./SquiggleChart";
|
import { SquiggleChart, SquiggleChartProps } from "./SquiggleChart";
|
||||||
import { CodeEditor } from "./CodeEditor";
|
import { CodeEditor } from "./CodeEditor";
|
||||||
|
@ -309,8 +309,7 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
executionId={executionId}
|
executionId={executionId}
|
||||||
environment={env}
|
environment={env}
|
||||||
{...vars}
|
{...vars}
|
||||||
bindings={defaultBindings}
|
// jsImports={imports}
|
||||||
jsImports={imports}
|
|
||||||
enableLocalSettings={true}
|
enableLocalSettings={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from "react";
|
import React, { useContext } from "react";
|
||||||
import { squiggleExpression, declaration } from "@quri/squiggle-lang";
|
import { SqDistributionTag, SqValue, SqValueTag } from "@quri/squiggle-lang";
|
||||||
import { NumberShower } from "../NumberShower";
|
import { NumberShower } from "../NumberShower";
|
||||||
import { DistributionChart, defaultPlot, makePlot } from "../DistributionChart";
|
import { DistributionChart, defaultPlot, makePlot } from "../DistributionChart";
|
||||||
import { FunctionChart, FunctionChartSettings } from "../FunctionChart";
|
import { FunctionChart, FunctionChartSettings } from "../FunctionChart";
|
||||||
|
@ -8,7 +8,10 @@ import { VariableBox } from "./VariableBox";
|
||||||
import { ItemSettingsMenu } from "./ItemSettingsMenu";
|
import { ItemSettingsMenu } from "./ItemSettingsMenu";
|
||||||
import { hasMassBelowZero } from "../../lib/distributionUtils";
|
import { hasMassBelowZero } from "../../lib/distributionUtils";
|
||||||
import { MergedItemSettings } from "./utils";
|
import { MergedItemSettings } from "./utils";
|
||||||
|
import { ViewerContext } from "./ViewerContext";
|
||||||
|
|
||||||
|
/*
|
||||||
|
// DISABLED FOR 0.4 branch, for now
|
||||||
function getRange<a>(x: declaration<a>) {
|
function getRange<a>(x: declaration<a>) {
|
||||||
const first = x.args[0];
|
const first = x.args[0];
|
||||||
switch (first.tag) {
|
switch (first.tag) {
|
||||||
|
@ -31,15 +34,21 @@ function getChartSettings<a>(x: declaration<a>): FunctionChartSettings {
|
||||||
count: 20,
|
count: 20,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
const VariableList: React.FC<{
|
const VariableList: React.FC<{
|
||||||
path: string[];
|
value: SqValue;
|
||||||
heading: string;
|
heading: string;
|
||||||
children: (settings: MergedItemSettings) => React.ReactNode;
|
children: (settings: MergedItemSettings) => React.ReactNode;
|
||||||
}> = ({ path, heading, children }) => (
|
}> = ({ value, heading, children }) => (
|
||||||
<VariableBox path={path} heading={heading}>
|
<VariableBox value={value} heading={heading}>
|
||||||
{(settings) => (
|
{(settings) => (
|
||||||
<div className={clsx("space-y-3", path.length ? "pt-1 mt-1" : null)}>
|
<div
|
||||||
|
className={clsx(
|
||||||
|
"space-y-3",
|
||||||
|
value.location.path.items.length ? "pt-1 mt-1" : null
|
||||||
|
)}
|
||||||
|
>
|
||||||
{children(settings)}
|
{children(settings)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -48,51 +57,44 @@ const VariableList: React.FC<{
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
/** The output of squiggle's run */
|
/** The output of squiggle's run */
|
||||||
expression: squiggleExpression;
|
value: SqValue;
|
||||||
/** Path to the current item, e.g. `['foo', 'bar', '3']` for `foo.bar[3]`; can be empty on the top-level item. */
|
|
||||||
path: string[];
|
|
||||||
width?: number;
|
width?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ExpressionViewer: React.FC<Props> = ({
|
export const ExpressionViewer: React.FC<Props> = ({ value, width }) => {
|
||||||
path,
|
const { getMergedSettings } = useContext(ViewerContext);
|
||||||
expression,
|
|
||||||
width,
|
switch (value.tag) {
|
||||||
}) => {
|
case SqValueTag.Number:
|
||||||
if (typeof expression !== "object") {
|
|
||||||
return (
|
return (
|
||||||
<VariableList path={path} heading="Error">
|
<VariableBox value={value} heading="Number">
|
||||||
{() => `Unknown expression: ${expression}`}
|
|
||||||
</VariableList>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
switch (expression.tag) {
|
|
||||||
case "number":
|
|
||||||
return (
|
|
||||||
<VariableBox path={path} heading="Number">
|
|
||||||
{() => (
|
{() => (
|
||||||
<div className="font-semibold text-slate-600">
|
<div className="font-semibold text-slate-600">
|
||||||
<NumberShower precision={3} number={expression.value} />
|
<NumberShower precision={3} number={value.value} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
case "distribution": {
|
case SqValueTag.Distribution: {
|
||||||
const distType = expression.value.type();
|
const distType = value.value.tag;
|
||||||
return (
|
return (
|
||||||
<VariableBox
|
<VariableBox
|
||||||
path={path}
|
value={value}
|
||||||
heading={`Distribution (${distType})\n${
|
heading={`Distribution (${distType})\n${
|
||||||
distType === "Symbolic" ? expression.value.toString() : ""
|
distType === SqDistributionTag.Symbolic
|
||||||
|
? value.value.toString()
|
||||||
|
: ""
|
||||||
}`}
|
}`}
|
||||||
renderSettingsMenu={({ onChange }) => {
|
renderSettingsMenu={({ onChange }) => {
|
||||||
const shape = expression.value.pointSet();
|
const shape = value.value.pointSet(
|
||||||
|
getMergedSettings(value.location).environment
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<ItemSettingsMenu
|
<ItemSettingsMenu
|
||||||
path={path}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
disableLogX={
|
disableLogX={
|
||||||
shape.tag === "Ok" && hasMassBelowZero(shape.value)
|
shape.tag === "Ok" && hasMassBelowZero(shape.value.asShape())
|
||||||
}
|
}
|
||||||
withFunctionSettings={false}
|
withFunctionSettings={false}
|
||||||
/>
|
/>
|
||||||
|
@ -102,7 +104,8 @@ export const ExpressionViewer: React.FC<Props> = ({
|
||||||
{(settings) => {
|
{(settings) => {
|
||||||
return (
|
return (
|
||||||
<DistributionChart
|
<DistributionChart
|
||||||
plot={defaultPlot(expression.value)}
|
plot={defaultPlot(value.value)}
|
||||||
|
environment={settings.environment}
|
||||||
{...settings.distributionPlotSettings}
|
{...settings.distributionPlotSettings}
|
||||||
height={settings.height}
|
height={settings.height}
|
||||||
width={width}
|
width={width}
|
||||||
|
@ -112,77 +115,77 @@ export const ExpressionViewer: React.FC<Props> = ({
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case "string":
|
case SqValueTag.String:
|
||||||
return (
|
return (
|
||||||
<VariableBox path={path} heading="String">
|
<VariableBox value={value} heading="String">
|
||||||
{() => (
|
{() => (
|
||||||
<>
|
<>
|
||||||
<span className="text-slate-400">"</span>
|
<span className="text-slate-400">"</span>
|
||||||
<span className="text-slate-600 font-semibold font-mono">
|
<span className="text-slate-600 font-semibold font-mono">
|
||||||
{expression.value}
|
{value.value}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-slate-400">"</span>
|
<span className="text-slate-400">"</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
case "boolean":
|
case SqValueTag.Bool:
|
||||||
return (
|
return (
|
||||||
<VariableBox path={path} heading="Boolean">
|
<VariableBox value={value} heading="Boolean">
|
||||||
{() => expression.value.toString()}
|
{() => value.value.toString()}
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
case "symbol":
|
case SqValueTag.Symbol:
|
||||||
return (
|
return (
|
||||||
<VariableBox path={path} heading="Symbol">
|
<VariableBox value={value} heading="Symbol">
|
||||||
{() => (
|
{() => (
|
||||||
<>
|
<>
|
||||||
<span className="text-slate-500 mr-2">Undefined Symbol:</span>
|
<span className="text-slate-500 mr-2">Undefined Symbol:</span>
|
||||||
<span className="text-slate-600">{expression.value}</span>
|
<span className="text-slate-600">{value.value}</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
case "call":
|
case SqValueTag.Call:
|
||||||
return (
|
return (
|
||||||
<VariableBox path={path} heading="Call">
|
<VariableBox value={value} heading="Call">
|
||||||
{() => expression.value}
|
{() => value.value}
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
case "arraystring":
|
case SqValueTag.ArrayString:
|
||||||
return (
|
return (
|
||||||
<VariableBox path={path} heading="Array String">
|
<VariableBox value={value} heading="Array String">
|
||||||
{() => expression.value.map((r) => `"${r}"`).join(", ")}
|
{() => value.value.map((r) => `"${r}"`).join(", ")}
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
case "date":
|
case SqValueTag.Date:
|
||||||
return (
|
return (
|
||||||
<VariableBox path={path} heading="Date">
|
<VariableBox value={value} heading="Date">
|
||||||
{() => expression.value.toDateString()}
|
{() => value.value.toDateString()}
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
case "void":
|
case SqValueTag.Void:
|
||||||
return (
|
return (
|
||||||
<VariableBox path={path} heading="Void">
|
<VariableBox value={value} heading="Void">
|
||||||
{() => "Void"}
|
{() => "Void"}
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
case "timeDuration": {
|
case SqValueTag.TimeDuration: {
|
||||||
return (
|
return (
|
||||||
<VariableBox path={path} heading="Time Duration">
|
<VariableBox value={value} heading="Time Duration">
|
||||||
{() => <NumberShower precision={3} number={expression.value} />}
|
{() => <NumberShower precision={3} number={value.value} />}
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case "lambda":
|
case SqValueTag.Lambda:
|
||||||
return (
|
return (
|
||||||
<VariableBox
|
<VariableBox
|
||||||
path={path}
|
value={value}
|
||||||
heading="Function"
|
heading="Function"
|
||||||
renderSettingsMenu={({ onChange }) => {
|
renderSettingsMenu={({ onChange }) => {
|
||||||
return (
|
return (
|
||||||
<ItemSettingsMenu
|
<ItemSettingsMenu
|
||||||
path={path}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
withFunctionSettings={true}
|
withFunctionSettings={true}
|
||||||
/>
|
/>
|
||||||
|
@ -191,11 +194,11 @@ export const ExpressionViewer: React.FC<Props> = ({
|
||||||
>
|
>
|
||||||
{(settings) => (
|
{(settings) => (
|
||||||
<>
|
<>
|
||||||
<div className="text-amber-700 bg-amber-100 rounded-md font-mono p-1 pl-2 mb-3 mt-1 text-sm">{`function(${expression.value.parameters.join(
|
<div className="text-amber-700 bg-amber-100 rounded-md font-mono p-1 pl-2 mb-3 mt-1 text-sm">{`function(${value.value
|
||||||
","
|
.parameters()
|
||||||
)})`}</div>
|
.join(",")})`}</div>
|
||||||
<FunctionChart
|
<FunctionChart
|
||||||
fn={expression.value}
|
fn={value.value}
|
||||||
chartSettings={settings.chartSettings}
|
chartSettings={settings.chartSettings}
|
||||||
distributionPlotSettings={settings.distributionPlotSettings}
|
distributionPlotSettings={settings.distributionPlotSettings}
|
||||||
height={settings.height}
|
height={settings.height}
|
||||||
|
@ -208,47 +211,48 @@ export const ExpressionViewer: React.FC<Props> = ({
|
||||||
)}
|
)}
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
case "lambdaDeclaration": {
|
case SqValueTag.Declaration: {
|
||||||
return (
|
return (
|
||||||
<VariableBox
|
<VariableBox
|
||||||
path={path}
|
value={value}
|
||||||
heading="Function Declaration"
|
heading="Function Declaration"
|
||||||
renderSettingsMenu={({ onChange }) => {
|
renderSettingsMenu={({ onChange }) => {
|
||||||
return (
|
return (
|
||||||
<ItemSettingsMenu
|
<ItemSettingsMenu
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
path={path}
|
value={value}
|
||||||
withFunctionSettings={true}
|
withFunctionSettings={true}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{(settings) => (
|
{(settings) => (
|
||||||
<FunctionChart
|
<div>NOT IMPLEMENTED IN 0.4 YET</div>
|
||||||
fn={expression.value.fn}
|
// <FunctionChart
|
||||||
chartSettings={getChartSettings(expression.value)}
|
// fn={expression.value.fn}
|
||||||
distributionPlotSettings={settings.distributionPlotSettings}
|
// chartSettings={getChartSettings(expression.value)}
|
||||||
height={settings.height}
|
// distributionPlotSettings={settings.distributionPlotSettings}
|
||||||
environment={{
|
// height={settings.height}
|
||||||
sampleCount: settings.environment.sampleCount / 10,
|
// environment={{
|
||||||
xyPointLength: settings.environment.xyPointLength / 10,
|
// sampleCount: settings.environment.sampleCount / 10,
|
||||||
}}
|
// xyPointLength: settings.environment.xyPointLength / 10,
|
||||||
/>
|
// }}
|
||||||
|
// />
|
||||||
)}
|
)}
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case "module": {
|
case SqValueTag.Module: {
|
||||||
return (
|
return (
|
||||||
<VariableList path={path} heading="Module">
|
<VariableList value={value} heading="Module">
|
||||||
{(_) =>
|
{(_) =>
|
||||||
Object.entries(expression.value)
|
value.value
|
||||||
|
.entries()
|
||||||
.filter(([key, _]) => !key.match(/^(Math|System)\./))
|
.filter(([key, _]) => !key.match(/^(Math|System)\./))
|
||||||
.map(([key, r]) => (
|
.map(([key, r]) => (
|
||||||
<ExpressionViewer
|
<ExpressionViewer
|
||||||
key={key}
|
key={key}
|
||||||
path={[...path, key]}
|
value={r}
|
||||||
expression={r}
|
|
||||||
width={width !== undefined ? width - 20 : width}
|
width={width !== undefined ? width - 20 : width}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
|
@ -256,23 +260,26 @@ export const ExpressionViewer: React.FC<Props> = ({
|
||||||
</VariableList>
|
</VariableList>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case "record":
|
case SqValueTag.Record:
|
||||||
const plot = makePlot(expression.value);
|
const plot = makePlot(value.value);
|
||||||
if (plot) {
|
if (plot) {
|
||||||
return (
|
return (
|
||||||
<VariableBox
|
<VariableBox
|
||||||
path={path}
|
value={value}
|
||||||
heading={"Plot"}
|
heading="Plot"
|
||||||
renderSettingsMenu={({ onChange }) => {
|
renderSettingsMenu={({ onChange }) => {
|
||||||
let disableLogX = plot.distributions.some((x) => {
|
let disableLogX = plot.distributions.some((x) => {
|
||||||
let pointSet = x.distribution.pointSet();
|
let pointSet = x.distribution.pointSet(
|
||||||
|
getMergedSettings(value.location).environment
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
pointSet.tag === "Ok" && hasMassBelowZero(pointSet.value)
|
pointSet.tag === "Ok" &&
|
||||||
|
hasMassBelowZero(pointSet.value.asShape())
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<ItemSettingsMenu
|
<ItemSettingsMenu
|
||||||
path={path}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
disableLogX={disableLogX}
|
disableLogX={disableLogX}
|
||||||
withFunctionSettings={false}
|
withFunctionSettings={false}
|
||||||
|
@ -284,6 +291,7 @@ export const ExpressionViewer: React.FC<Props> = ({
|
||||||
return (
|
return (
|
||||||
<DistributionChart
|
<DistributionChart
|
||||||
plot={plot}
|
plot={plot}
|
||||||
|
environment={settings.environment}
|
||||||
{...settings.distributionPlotSettings}
|
{...settings.distributionPlotSettings}
|
||||||
height={settings.height}
|
height={settings.height}
|
||||||
width={width}
|
width={width}
|
||||||
|
@ -294,13 +302,14 @@ export const ExpressionViewer: React.FC<Props> = ({
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<VariableList path={path} heading="Record">
|
<VariableList value={value} heading="Record">
|
||||||
{(_) =>
|
{(_) =>
|
||||||
Object.entries(expression.value).map(([key, r]) => (
|
value.value
|
||||||
|
.entries()
|
||||||
|
.map(([key, r]) => (
|
||||||
<ExpressionViewer
|
<ExpressionViewer
|
||||||
key={key}
|
key={key}
|
||||||
path={[...path, key]}
|
value={r}
|
||||||
expression={r}
|
|
||||||
width={width !== undefined ? width - 20 : width}
|
width={width !== undefined ? width - 20 : width}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
|
@ -308,15 +317,16 @@ export const ExpressionViewer: React.FC<Props> = ({
|
||||||
</VariableList>
|
</VariableList>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
case "array":
|
case SqValueTag.Array:
|
||||||
return (
|
return (
|
||||||
<VariableList path={path} heading="Array">
|
<VariableList value={value} heading="Array">
|
||||||
{(_) =>
|
{(_) =>
|
||||||
expression.value.map((r, i) => (
|
value.value
|
||||||
|
.getValues()
|
||||||
|
.map((r, i) => (
|
||||||
<ExpressionViewer
|
<ExpressionViewer
|
||||||
key={i}
|
key={i}
|
||||||
path={[...path, String(i)]}
|
value={r}
|
||||||
expression={r}
|
|
||||||
width={width !== undefined ? width - 20 : width}
|
width={width !== undefined ? width - 20 : width}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
|
@ -325,13 +335,11 @@ export const ExpressionViewer: React.FC<Props> = ({
|
||||||
);
|
);
|
||||||
default: {
|
default: {
|
||||||
return (
|
return (
|
||||||
<VariableList path={path} heading="Error">
|
<VariableList value={value} heading="Error">
|
||||||
{() => (
|
{() => (
|
||||||
<div>
|
<div>
|
||||||
<span>No display for type: </span>{" "}
|
<span>No display for type: </span>{" "}
|
||||||
<span className="font-semibold text-slate-600">
|
<span className="font-semibold text-slate-600">{value.tag}</span>
|
||||||
{expression.tag}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</VariableList>
|
</VariableList>
|
||||||
|
|
|
@ -4,13 +4,14 @@ import { useForm } from "react-hook-form";
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import { Modal } from "../ui/Modal";
|
import { Modal } from "../ui/Modal";
|
||||||
import { ViewSettings, viewSettingsSchema } from "../ViewSettings";
|
import { ViewSettings, viewSettingsSchema } from "../ViewSettings";
|
||||||
import { Path, pathAsString } from "./utils";
|
|
||||||
import { ViewerContext } from "./ViewerContext";
|
import { ViewerContext } from "./ViewerContext";
|
||||||
import { defaultTickFormat } from "../../lib/distributionSpecBuilder";
|
import { defaultTickFormat } from "../../lib/distributionSpecBuilder";
|
||||||
import { PlaygroundContext } from "../SquigglePlayground";
|
import { PlaygroundContext } from "../SquigglePlayground";
|
||||||
|
import { SqValue } from "@quri/squiggle-lang";
|
||||||
|
import { locationAsString } from "./utils";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
path: Path;
|
value: SqValue;
|
||||||
onChange: () => void;
|
onChange: () => void;
|
||||||
disableLogX?: boolean;
|
disableLogX?: boolean;
|
||||||
withFunctionSettings: boolean;
|
withFunctionSettings: boolean;
|
||||||
|
@ -19,7 +20,7 @@ type Props = {
|
||||||
const ItemSettingsModal: React.FC<
|
const ItemSettingsModal: React.FC<
|
||||||
Props & { close: () => void; resetScroll: () => void }
|
Props & { close: () => void; resetScroll: () => void }
|
||||||
> = ({
|
> = ({
|
||||||
path,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
disableLogX,
|
disableLogX,
|
||||||
withFunctionSettings,
|
withFunctionSettings,
|
||||||
|
@ -29,7 +30,7 @@ const ItemSettingsModal: React.FC<
|
||||||
const { setSettings, getSettings, getMergedSettings } =
|
const { setSettings, getSettings, getMergedSettings } =
|
||||||
useContext(ViewerContext);
|
useContext(ViewerContext);
|
||||||
|
|
||||||
const mergedSettings = getMergedSettings(path);
|
const mergedSettings = getMergedSettings(value.location);
|
||||||
|
|
||||||
const { register, watch } = useForm({
|
const { register, watch } = useForm({
|
||||||
resolver: yupResolver(viewSettingsSchema),
|
resolver: yupResolver(viewSettingsSchema),
|
||||||
|
@ -53,8 +54,8 @@ const ItemSettingsModal: React.FC<
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const subscription = watch((vars) => {
|
const subscription = watch((vars) => {
|
||||||
const settings = getSettings(path); // get the latest version
|
const settings = getSettings(value.location); // get the latest version
|
||||||
setSettings(path, {
|
setSettings(value.location, {
|
||||||
...settings,
|
...settings,
|
||||||
distributionPlotSettings: {
|
distributionPlotSettings: {
|
||||||
showSummary: vars.showSummary,
|
showSummary: vars.showSummary,
|
||||||
|
@ -75,7 +76,7 @@ const ItemSettingsModal: React.FC<
|
||||||
onChange();
|
onChange();
|
||||||
});
|
});
|
||||||
return () => subscription.unsubscribe();
|
return () => subscription.unsubscribe();
|
||||||
}, [getSettings, setSettings, onChange, path, watch]);
|
}, [getSettings, setSettings, onChange, value.location, watch]);
|
||||||
|
|
||||||
const { getLeftPanelElement } = useContext(PlaygroundContext);
|
const { getLeftPanelElement } = useContext(PlaygroundContext);
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ const ItemSettingsModal: React.FC<
|
||||||
<Modal container={getLeftPanelElement()} close={close}>
|
<Modal container={getLeftPanelElement()} close={close}>
|
||||||
<Modal.Header>
|
<Modal.Header>
|
||||||
Chart settings
|
Chart settings
|
||||||
{path.length ? (
|
{value.location.path.items.length ? (
|
||||||
<>
|
<>
|
||||||
{" for "}
|
{" for "}
|
||||||
<span
|
<span
|
||||||
|
@ -91,7 +92,7 @@ const ItemSettingsModal: React.FC<
|
||||||
className="cursor-pointer"
|
className="cursor-pointer"
|
||||||
onClick={resetScroll}
|
onClick={resetScroll}
|
||||||
>
|
>
|
||||||
{pathAsString(path)}
|
{locationAsString(value.location)}
|
||||||
</span>{" "}
|
</span>{" "}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
@ -120,7 +121,7 @@ export const ItemSettingsMenu: React.FC<Props> = (props) => {
|
||||||
if (!enableLocalSettings) {
|
if (!enableLocalSettings) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const settings = getSettings(props.path);
|
const settings = getSettings(props.value.location);
|
||||||
|
|
||||||
const resetScroll = () => {
|
const resetScroll = () => {
|
||||||
if (!ref.current) return;
|
if (!ref.current) return;
|
||||||
|
@ -139,7 +140,7 @@ export const ItemSettingsMenu: React.FC<Props> = (props) => {
|
||||||
{settings.distributionPlotSettings || settings.chartSettings ? (
|
{settings.distributionPlotSettings || settings.chartSettings ? (
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSettings(props.path, {
|
setSettings(props.value.location, {
|
||||||
...settings,
|
...settings,
|
||||||
distributionPlotSettings: undefined,
|
distributionPlotSettings: undefined,
|
||||||
chartSettings: undefined,
|
chartSettings: undefined,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { SqValue, SqValueLocation } from "@quri/squiggle-lang";
|
||||||
import React, { useContext, useReducer } from "react";
|
import React, { useContext, useReducer } from "react";
|
||||||
import { Tooltip } from "../ui/Tooltip";
|
import { Tooltip } from "../ui/Tooltip";
|
||||||
import { LocalItemSettings, MergedItemSettings } from "./utils";
|
import { LocalItemSettings, MergedItemSettings } from "./utils";
|
||||||
|
@ -8,14 +9,14 @@ type SettingsMenuParams = {
|
||||||
};
|
};
|
||||||
|
|
||||||
type VariableBoxProps = {
|
type VariableBoxProps = {
|
||||||
path: string[];
|
value: SqValue;
|
||||||
heading: string;
|
heading: string;
|
||||||
renderSettingsMenu?: (params: SettingsMenuParams) => React.ReactNode;
|
renderSettingsMenu?: (params: SettingsMenuParams) => React.ReactNode;
|
||||||
children: (settings: MergedItemSettings) => React.ReactNode;
|
children: (settings: MergedItemSettings) => React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const VariableBox: React.FC<VariableBoxProps> = ({
|
export const VariableBox: React.FC<VariableBoxProps> = ({
|
||||||
path,
|
value: { location },
|
||||||
heading = "Error",
|
heading = "Error",
|
||||||
renderSettingsMenu,
|
renderSettingsMenu,
|
||||||
children,
|
children,
|
||||||
|
@ -27,10 +28,10 @@ export const VariableBox: React.FC<VariableBoxProps> = ({
|
||||||
// So we use `forceUpdate` to force rerendering.
|
// So we use `forceUpdate` to force rerendering.
|
||||||
const [_, forceUpdate] = useReducer((x) => x + 1, 0);
|
const [_, forceUpdate] = useReducer((x) => x + 1, 0);
|
||||||
|
|
||||||
const settings = getSettings(path);
|
const settings = getSettings(location);
|
||||||
|
|
||||||
const setSettingsAndUpdate = (newSettings: LocalItemSettings) => {
|
const setSettingsAndUpdate = (newSettings: LocalItemSettings) => {
|
||||||
setSettings(path, newSettings);
|
setSettings(location, newSettings);
|
||||||
forceUpdate();
|
forceUpdate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,8 +39,10 @@ export const VariableBox: React.FC<VariableBoxProps> = ({
|
||||||
setSettingsAndUpdate({ ...settings, collapsed: !settings.collapsed });
|
setSettingsAndUpdate({ ...settings, collapsed: !settings.collapsed });
|
||||||
};
|
};
|
||||||
|
|
||||||
const isTopLevel = path.length === 0;
|
const isTopLevel = location.path.items.length === 0;
|
||||||
const name = isTopLevel ? "Result" : path[path.length - 1];
|
const name = isTopLevel
|
||||||
|
? { result: "Result", bindings: "Bindings" }[location.path.root]
|
||||||
|
: location.path.items[location.path.items.length - 1];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -65,13 +68,13 @@ export const VariableBox: React.FC<VariableBoxProps> = ({
|
||||||
</header>
|
</header>
|
||||||
{settings.collapsed ? null : (
|
{settings.collapsed ? null : (
|
||||||
<div className="flex w-full">
|
<div className="flex w-full">
|
||||||
{path.length ? (
|
{location.path.items.length ? (
|
||||||
<div
|
<div
|
||||||
className="border-l-2 border-slate-200 hover:border-indigo-600 w-4 cursor-pointer"
|
className="border-l-2 border-slate-200 hover:border-indigo-600 w-4 cursor-pointer"
|
||||||
onClick={toggleCollapsed}
|
onClick={toggleCollapsed}
|
||||||
></div>
|
></div>
|
||||||
) : null}
|
) : null}
|
||||||
<div className="grow">{children(getMergedSettings(path))}</div>
|
<div className="grow">{children(getMergedSettings(location))}</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import { defaultEnvironment } from "@quri/squiggle-lang";
|
import { defaultEnvironment, SqValueLocation } from "@quri/squiggle-lang";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { LocalItemSettings, MergedItemSettings, Path } from "./utils";
|
import { LocalItemSettings, MergedItemSettings } from "./utils";
|
||||||
|
|
||||||
type ViewerContextShape = {
|
type ViewerContextShape = {
|
||||||
// Note that we don't store settings themselves in the context (that would cause rerenders of the entire tree on each settings update).
|
// Note that we don't store settings themselves in the context (that would cause rerenders of the entire tree on each settings update).
|
||||||
// Instead, we keep settings in local state and notify the global context via setSettings to pass them down the component tree again if it got rebuilt from scratch.
|
// Instead, we keep settings in local state and notify the global context via setSettings to pass them down the component tree again if it got rebuilt from scratch.
|
||||||
// See ./SquiggleViewer.tsx and ./VariableBox.tsx for other implementation details on this.
|
// See ./SquiggleViewer.tsx and ./VariableBox.tsx for other implementation details on this.
|
||||||
getSettings(path: Path): LocalItemSettings;
|
getSettings(location: SqValueLocation): LocalItemSettings;
|
||||||
getMergedSettings(path: Path): MergedItemSettings;
|
getMergedSettings(location: SqValueLocation): MergedItemSettings;
|
||||||
setSettings(path: Path, value: LocalItemSettings): void;
|
setSettings(location: SqValueLocation, value: LocalItemSettings): void;
|
||||||
enableLocalSettings: boolean; // show local settings icon in the UI
|
enableLocalSettings: boolean; // show local settings icon in the UI
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,20 @@
|
||||||
import React, { useCallback, useRef } from "react";
|
import React, { useCallback, useRef } from "react";
|
||||||
import { environment } from "@quri/squiggle-lang";
|
import { environment, SqValueLocation } from "@quri/squiggle-lang";
|
||||||
import { DistributionPlottingSettings } from "../DistributionChart";
|
import { DistributionPlottingSettings } from "../DistributionChart";
|
||||||
import { FunctionChartSettings } from "../FunctionChart";
|
import { FunctionChartSettings } from "../FunctionChart";
|
||||||
import { ExpressionViewer } from "./ExpressionViewer";
|
import { ExpressionViewer } from "./ExpressionViewer";
|
||||||
import { ViewerContext } from "./ViewerContext";
|
import { ViewerContext } from "./ViewerContext";
|
||||||
import {
|
import {
|
||||||
LocalItemSettings,
|
LocalItemSettings,
|
||||||
|
locationAsString,
|
||||||
MergedItemSettings,
|
MergedItemSettings,
|
||||||
Path,
|
|
||||||
pathAsString,
|
|
||||||
} from "./utils";
|
} from "./utils";
|
||||||
import { useSquiggle } from "../../lib/hooks";
|
import { useSquiggle } from "../../lib/hooks";
|
||||||
import { SquiggleErrorAlert } from "../SquiggleErrorAlert";
|
import { SquiggleErrorAlert } from "../SquiggleErrorAlert";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
/** The output of squiggle's run */
|
/** The output of squiggle's run */
|
||||||
result: ReturnType<typeof useSquiggle>;
|
result: ReturnType<typeof useSquiggle>["result"];
|
||||||
width?: number;
|
width?: number;
|
||||||
height: number;
|
height: number;
|
||||||
distributionPlotSettings: DistributionPlottingSettings;
|
distributionPlotSettings: DistributionPlottingSettings;
|
||||||
|
@ -45,22 +44,22 @@ export const SquiggleViewer: React.FC<Props> = ({
|
||||||
const settingsRef = useRef<Settings>({});
|
const settingsRef = useRef<Settings>({});
|
||||||
|
|
||||||
const getSettings = useCallback(
|
const getSettings = useCallback(
|
||||||
(path: Path) => {
|
(location: SqValueLocation) => {
|
||||||
return settingsRef.current[pathAsString(path)] || defaultSettings;
|
return settingsRef.current[locationAsString(location)] || defaultSettings;
|
||||||
},
|
},
|
||||||
[settingsRef]
|
[settingsRef]
|
||||||
);
|
);
|
||||||
|
|
||||||
const setSettings = useCallback(
|
const setSettings = useCallback(
|
||||||
(path: Path, value: LocalItemSettings) => {
|
(location: SqValueLocation, value: LocalItemSettings) => {
|
||||||
settingsRef.current[pathAsString(path)] = value;
|
settingsRef.current[locationAsString(location)] = value;
|
||||||
},
|
},
|
||||||
[settingsRef]
|
[settingsRef]
|
||||||
);
|
);
|
||||||
|
|
||||||
const getMergedSettings = useCallback(
|
const getMergedSettings = useCallback(
|
||||||
(path: Path) => {
|
(location: SqValueLocation) => {
|
||||||
const localSettings = getSettings(path);
|
const localSettings = getSettings(location);
|
||||||
const result: MergedItemSettings = {
|
const result: MergedItemSettings = {
|
||||||
distributionPlotSettings: {
|
distributionPlotSettings: {
|
||||||
...distributionPlotSettings,
|
...distributionPlotSettings,
|
||||||
|
@ -91,7 +90,7 @@ export const SquiggleViewer: React.FC<Props> = ({
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{result.tag === "Ok" ? (
|
{result.tag === "Ok" ? (
|
||||||
<ExpressionViewer path={[]} expression={result.value} width={width} />
|
<ExpressionViewer value={result.value} width={width} />
|
||||||
) : (
|
) : (
|
||||||
<SquiggleErrorAlert error={result.value} />
|
<SquiggleErrorAlert error={result.value} />
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { DistributionPlottingSettings } from "../DistributionChart";
|
import { DistributionPlottingSettings } from "../DistributionChart";
|
||||||
import { FunctionChartSettings } from "../FunctionChart";
|
import { FunctionChartSettings } from "../FunctionChart";
|
||||||
import { environment } from "@quri/squiggle-lang";
|
import { environment, SqValueLocation } from "@quri/squiggle-lang";
|
||||||
|
|
||||||
export type LocalItemSettings = {
|
export type LocalItemSettings = {
|
||||||
collapsed: boolean;
|
collapsed: boolean;
|
||||||
|
@ -17,6 +17,5 @@ export type MergedItemSettings = {
|
||||||
environment: environment;
|
environment: environment;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Path = string[];
|
export const locationAsString = (location: SqValueLocation) =>
|
||||||
|
location.path.items.join(".");
|
||||||
export const pathAsString = (path: Path) => path.join(".");
|
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
export { SquiggleChart } from "./components/SquiggleChart";
|
export { SquiggleChart } from "./components/SquiggleChart";
|
||||||
export { SquiggleEditor, SquigglePartial } from "./components/SquiggleEditor";
|
export { SquiggleEditor } from "./components/SquiggleEditor";
|
||||||
export { SquigglePlayground } from "./components/SquigglePlayground";
|
export { SquigglePlayground } from "./components/SquigglePlayground";
|
||||||
export { SquiggleContainer } from "./components/SquiggleContainer";
|
export { SquiggleContainer } from "./components/SquiggleContainer";
|
||||||
export { SquiggleEditorWithImportedBindings } from "./components/SquiggleEditorWithImportedBindings";
|
|
||||||
|
|
||||||
export { mergeBindings } from "@quri/squiggle-lang";
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { shape } from "@quri/squiggle-lang";
|
import { SqShape } from "@quri/squiggle-lang";
|
||||||
|
|
||||||
export const hasMassBelowZero = (shape: shape) =>
|
export const hasMassBelowZero = (shape: SqShape) =>
|
||||||
shape.continuous.some((x) => x.x <= 0) ||
|
shape.continuous.some((x) => x.x <= 0) ||
|
||||||
shape.discrete.some((x) => x.x <= 0);
|
shape.discrete.some((x) => x.x <= 0);
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
export { useMaybeControlledValue } from "./useMaybeControlledValue";
|
export { useMaybeControlledValue } from "./useMaybeControlledValue";
|
||||||
export { useSquiggle, useSquigglePartial } from "./useSquiggle";
|
export { useSquiggle } from "./useSquiggle";
|
||||||
export { useRunnerState } from "./useRunnerState";
|
export { useRunnerState } from "./useRunnerState";
|
||||||
|
|
|
@ -1,34 +1,27 @@
|
||||||
import {
|
import { environment, run, SqValue } from "@quri/squiggle-lang";
|
||||||
bindings,
|
|
||||||
environment,
|
|
||||||
jsImports,
|
|
||||||
run,
|
|
||||||
runPartial,
|
|
||||||
} from "@quri/squiggle-lang";
|
|
||||||
import { useEffect, useMemo } from "react";
|
import { useEffect, useMemo } from "react";
|
||||||
|
|
||||||
type SquiggleArgs<T extends ReturnType<typeof run | typeof runPartial>> = {
|
type SquiggleArgs = {
|
||||||
code: string;
|
code: string;
|
||||||
executionId?: number;
|
executionId?: number;
|
||||||
bindings?: bindings;
|
// jsImports?: jsImports;
|
||||||
jsImports?: jsImports;
|
|
||||||
environment?: environment;
|
environment?: environment;
|
||||||
onChange?: (expr: Extract<T, { tag: "Ok" }>["value"] | undefined) => void;
|
onChange?: (expr: SqValue | undefined) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const useSquiggleAny = <T extends ReturnType<typeof run | typeof runPartial>>(
|
export const useSquiggle = (args: SquiggleArgs) => {
|
||||||
args: SquiggleArgs<T>,
|
const result = useMemo(
|
||||||
f: (...args: Parameters<typeof run>) => T
|
() => {
|
||||||
) => {
|
const result = run(args.code, {
|
||||||
const result: T = useMemo<T>(
|
environment: args.environment,
|
||||||
() => f(args.code, args.bindings, args.environment, args.jsImports),
|
});
|
||||||
|
return result;
|
||||||
|
},
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
[
|
[
|
||||||
f,
|
|
||||||
args.code,
|
args.code,
|
||||||
args.bindings,
|
|
||||||
args.environment,
|
args.environment,
|
||||||
args.jsImports,
|
// args.jsImports,
|
||||||
args.executionId,
|
args.executionId,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
@ -36,18 +29,8 @@ const useSquiggleAny = <T extends ReturnType<typeof run | typeof runPartial>>(
|
||||||
const { onChange } = args;
|
const { onChange } = args;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onChange?.(result.tag === "Ok" ? result.value : undefined);
|
onChange?.(result.result.tag === "Ok" ? result.result.value : undefined);
|
||||||
}, [result, onChange]);
|
}, [result, onChange]);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSquigglePartial = (
|
|
||||||
args: SquiggleArgs<ReturnType<typeof runPartial>>
|
|
||||||
) => {
|
|
||||||
return useSquiggleAny(args, runPartial);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useSquiggle = (args: SquiggleArgs<ReturnType<typeof run>>) => {
|
|
||||||
return useSquiggleAny(args, run);
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
import { Distribution, result, squiggleExpression } from "@quri/squiggle-lang";
|
import { SqDistribution, result, SqRecord } from "@quri/squiggle-lang";
|
||||||
|
|
||||||
export type LabeledDistribution = {
|
export type LabeledDistribution = {
|
||||||
name: string;
|
name: string;
|
||||||
distribution: Distribution;
|
distribution: SqDistribution;
|
||||||
color?: string;
|
color?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,9 +53,7 @@ const schema = yup
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export function parsePlot(record: {
|
export function parsePlot(record: SqRecord): result<Plot, string> {
|
||||||
[key: string]: squiggleExpression;
|
|
||||||
}): result<Plot, string> {
|
|
||||||
try {
|
try {
|
||||||
const plotRecord = schema.validateSync(record);
|
const plotRecord = schema.validateSync(record);
|
||||||
return ok({
|
return ok({
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
import {
|
import { run, SqProject, SqValue, SqValueTag } from "../../src/js";
|
||||||
Distribution,
|
import { testRun } from "./TestHelpers";
|
||||||
resultMap,
|
|
||||||
defaultBindings,
|
|
||||||
mergeBindings,
|
|
||||||
} from "../../src/js/index";
|
|
||||||
import { testRun, testRunPartial } from "./TestHelpers";
|
|
||||||
|
|
||||||
function Ok<b>(x: b) {
|
function Ok<b>(x: b) {
|
||||||
return { tag: "Ok", value: x };
|
return { tag: "Ok", value: x };
|
||||||
|
@ -12,97 +7,57 @@ function Ok<b>(x: b) {
|
||||||
|
|
||||||
describe("Simple calculations and results", () => {
|
describe("Simple calculations and results", () => {
|
||||||
test("mean(normal(5,2))", () => {
|
test("mean(normal(5,2))", () => {
|
||||||
expect(testRun("mean(normal(5,2))")).toEqual({
|
const result = testRun("mean(normal(5,2))"); // FIXME
|
||||||
tag: "number",
|
expect(result.toString()).toEqual("5");
|
||||||
value: 5,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
test("10+10", () => {
|
test("10+10", () => {
|
||||||
let foo = testRun("10 + 10");
|
let result = testRun("10 + 10");
|
||||||
expect(foo).toEqual({ tag: "number", value: 20 });
|
expect(result.toString()).toEqual("20");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe("Log function", () => {
|
describe("Log function", () => {
|
||||||
test("log(1) = 0", () => {
|
test("log(1) = 0", () => {
|
||||||
let foo = testRun("log(1)");
|
let foo = testRun("log(1)");
|
||||||
expect(foo).toEqual({ tag: "number", value: 0 });
|
expect(foo.toString()).toEqual("0");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Array", () => {
|
describe("Array", () => {
|
||||||
test("nested Array", () => {
|
test("nested Array", () => {
|
||||||
expect(testRun("[[1]]")).toEqual({
|
expect(testRun("[[ 1 ]]").toString()).toEqual("[[1]]");
|
||||||
tag: "array",
|
|
||||||
value: [
|
|
||||||
{
|
|
||||||
tag: "array",
|
|
||||||
value: [
|
|
||||||
{
|
|
||||||
tag: "number",
|
|
||||||
value: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Record", () => {
|
describe("Record", () => {
|
||||||
test("Return record", () => {
|
test("Return record", () => {
|
||||||
expect(testRun("{a: 1}")).toEqual({
|
expect(testRun("{a:1}").toString()).toEqual("{a: 1}");
|
||||||
tag: "record",
|
|
||||||
value: {
|
|
||||||
a: {
|
|
||||||
tag: "number",
|
|
||||||
value: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Partials", () => {
|
describe("Continues", () => {
|
||||||
test("Can pass variables between partials and cells", () => {
|
test("Bindings from continues are accessible", () => {
|
||||||
let bindings = testRunPartial(`x = 5`);
|
const project = SqProject.create();
|
||||||
let bindings2 = testRunPartial(`y = x + 2`, bindings);
|
project.setSource("p1", "x = 5");
|
||||||
expect(testRun(`y + 3`, bindings2)).toEqual({
|
project.setSource("p2", "y = x + 2");
|
||||||
tag: "number",
|
project.setSource("main", "y + 3");
|
||||||
value: 10,
|
project.setContinues("main", ["p2"]);
|
||||||
});
|
project.setContinues("p2", ["p1"]);
|
||||||
|
project.run("main");
|
||||||
|
const result = project.getResult("main");
|
||||||
|
expect(result.tag).toEqual("Ok");
|
||||||
|
expect(result.value.toString()).toEqual("10");
|
||||||
});
|
});
|
||||||
test("Can merge bindings from three partials", () => {
|
test("Can merge bindings from three partials", () => {
|
||||||
let bindings1 = testRunPartial(`x = 1`);
|
const project = SqProject.create();
|
||||||
let bindings2 = testRunPartial(`y = 2`);
|
project.setSource("p1", "x = 1");
|
||||||
let bindings3 = testRunPartial(`z = 3`);
|
project.setSource("p2", "y = 2");
|
||||||
expect(
|
project.setSource("p3", "z = 3");
|
||||||
testRun(`x + y + z`, mergeBindings([bindings1, bindings2, bindings3]))
|
project.setSource("main", "x + y + z");
|
||||||
).toEqual({
|
project.setContinues("main", ["p1", "p2", "p3"]);
|
||||||
tag: "number",
|
project.run("main");
|
||||||
value: 6,
|
const result = project.getResult("main");
|
||||||
});
|
expect(result.tag).toEqual("Ok");
|
||||||
});
|
expect(result.value.toString()).toEqual("6");
|
||||||
});
|
|
||||||
|
|
||||||
describe("JS Imports", () => {
|
|
||||||
test("Can pass parameters into partials and cells", () => {
|
|
||||||
let bindings = testRunPartial(`y = $x + 2`, defaultBindings, { x: 1 });
|
|
||||||
let bindings2 = testRunPartial(`z = y + $a`, bindings, { a: 3 });
|
|
||||||
expect(testRun(`z`, bindings2)).toEqual({
|
|
||||||
tag: "number",
|
|
||||||
value: 6,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
test("Complicated deep parameters", () => {
|
|
||||||
expect(
|
|
||||||
testRun(`$x.y[0][0].w + $x.z + $u.v`, defaultBindings, {
|
|
||||||
x: { y: [[{ w: 1 }]], z: 2 },
|
|
||||||
u: { v: 3 },
|
|
||||||
})
|
|
||||||
).toEqual({
|
|
||||||
tag: "number",
|
|
||||||
value: 6,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -112,50 +67,62 @@ describe("Distribution", () => {
|
||||||
let env = { sampleCount: 8, xyPointLength: 100 };
|
let env = { sampleCount: 8, xyPointLength: 100 };
|
||||||
let dist1Samples = [3, 4, 5, 6, 6, 7, 10, 15, 30];
|
let dist1Samples = [3, 4, 5, 6, 6, 7, 10, 15, 30];
|
||||||
let dist1SampleCount = dist1Samples.length;
|
let dist1SampleCount = dist1Samples.length;
|
||||||
let dist = new Distribution(
|
|
||||||
{ tag: "SampleSet", value: [3, 4, 5, 6, 6, 7, 10, 15, 30] },
|
const buildDist = (samples: number[]) => {
|
||||||
env
|
const src = `SampleSet.fromList([${samples.join(",")}])`;
|
||||||
);
|
const { result } = run(src, {
|
||||||
let dist2 = new Distribution(
|
environment: env,
|
||||||
{ tag: "SampleSet", value: [20, 22, 24, 29, 30, 35, 38, 44, 52] },
|
});
|
||||||
env
|
if (result.tag !== "Ok") {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to build SampleSet: from ${src}: ${result.value}`
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
const dist = result.value;
|
||||||
|
if (dist.tag !== SqValueTag.Distribution) {
|
||||||
|
throw new Error("Expected Distribution");
|
||||||
|
}
|
||||||
|
return dist.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const dist = buildDist(dist1Samples);
|
||||||
|
const dist2 = buildDist([20, 22, 24, 29, 30, 35, 38, 44, 52]);
|
||||||
|
|
||||||
test("mean", () => {
|
test("mean", () => {
|
||||||
expect(dist.mean().value).toBeCloseTo(9.5555555);
|
expect(dist.mean(env).value).toBeCloseTo(9.5555555);
|
||||||
});
|
});
|
||||||
test("pdf", () => {
|
test("pdf", () => {
|
||||||
expect(dist.pdf(5.0).value).toBeCloseTo(0.10499097598222966, 1);
|
expect(dist.pdf(env, 5.0).value).toBeCloseTo(0.10499097598222966, 1);
|
||||||
});
|
});
|
||||||
test("cdf", () => {
|
test("cdf", () => {
|
||||||
expect(dist.cdf(5.0).value).toBeCloseTo(
|
expect(dist.cdf(env, 5.0).value).toBeCloseTo(
|
||||||
dist1Samples.filter((x) => x <= 5).length / dist1SampleCount,
|
dist1Samples.filter((x) => x <= 5).length / dist1SampleCount,
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
test("inv", () => {
|
test("inv", () => {
|
||||||
expect(dist.inv(0.5).value).toBeCloseTo(6);
|
expect(dist.inv(env, 0.5).value).toBeCloseTo(6);
|
||||||
});
|
|
||||||
test("toPointSet", () => {
|
|
||||||
expect(
|
|
||||||
resultMap(dist.toPointSet(), (r: Distribution) => r.toString())
|
|
||||||
).toEqual(Ok("Point Set Distribution"));
|
|
||||||
});
|
|
||||||
test("toSparkline", () => {
|
|
||||||
expect(dist.toSparkline(20).value).toEqual("▁▁▃▇█▇▄▂▂▂▁▁▁▁▁▂▂▁▁▁");
|
|
||||||
});
|
|
||||||
test("algebraicAdd", () => {
|
|
||||||
expect(
|
|
||||||
resultMap(dist.algebraicAdd(dist2), (r: Distribution) =>
|
|
||||||
r.toSparkline(20)
|
|
||||||
).value
|
|
||||||
).toEqual(Ok("▁▁▂▄▆████▇▆▄▄▃▃▃▂▁▁▁"));
|
|
||||||
});
|
|
||||||
test("pointwiseAdd", () => {
|
|
||||||
expect(
|
|
||||||
resultMap(dist.pointwiseAdd(dist2), (r: Distribution) =>
|
|
||||||
r.toSparkline(20)
|
|
||||||
).value
|
|
||||||
).toEqual(Ok("▁▂██▃▃▃▃▄▅▄▃▃▂▂▂▁▁▁▁"));
|
|
||||||
});
|
});
|
||||||
|
// test("toPointSet", () => {
|
||||||
|
// expect(
|
||||||
|
// resultMap(dist.toPointSet(), (r: Distribution) => r.toString())
|
||||||
|
// ).toEqual(Ok("Point Set Distribution"));
|
||||||
|
// });
|
||||||
|
// test("toSparkline", () => {
|
||||||
|
// expect(dist.toSparkline(20).value).toEqual("▁▁▃▇█▇▄▂▂▂▁▁▁▁▁▂▂▁▁▁");
|
||||||
|
// });
|
||||||
|
// test("algebraicAdd", () => {
|
||||||
|
// expect(
|
||||||
|
// resultMap(dist.algebraicAdd(dist2), (r: Distribution) =>
|
||||||
|
// r.toSparkline(20)
|
||||||
|
// ).value
|
||||||
|
// ).toEqual(Ok("▁▁▂▄▆████▇▆▄▄▃▃▃▂▁▁▁"));
|
||||||
|
// });
|
||||||
|
// test("pointwiseAdd", () => {
|
||||||
|
// expect(
|
||||||
|
// resultMap(dist.pointwiseAdd(dist2), (r: Distribution) =>
|
||||||
|
// r.toSparkline(20)
|
||||||
|
// ).value
|
||||||
|
// ).toEqual(Ok("▁▂██▃▃▃▃▄▅▄▃▃▂▂▂▁▁▁▁"));
|
||||||
|
// });
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
// import { errorValueToString } from "../../src/js/index";
|
|
||||||
import * as fc from "fast-check";
|
import * as fc from "fast-check";
|
||||||
import { testRun } from "./TestHelpers";
|
import { testRun } from "./TestHelpers";
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,3 @@
|
||||||
import {
|
|
||||||
run,
|
|
||||||
squiggleExpression,
|
|
||||||
errorValue,
|
|
||||||
result,
|
|
||||||
} from "../../src/js/index";
|
|
||||||
import { testRun } from "./TestHelpers";
|
import { testRun } from "./TestHelpers";
|
||||||
import * as fc from "fast-check";
|
import * as fc from "fast-check";
|
||||||
|
|
||||||
|
@ -42,9 +36,9 @@ describe("Squiggle's parser is whitespace insensitive", () => {
|
||||||
whitespaceGen(),
|
whitespaceGen(),
|
||||||
whitespaceGen(),
|
whitespaceGen(),
|
||||||
(a, b, c, d, e, f, g, h) => {
|
(a, b, c, d, e, f, g, h) => {
|
||||||
expect(testRun(squiggleString(a, b, c, d, e, f, g, h))).toEqual(
|
expect(
|
||||||
squiggleOutput
|
testRun(squiggleString(a, b, c, d, e, f, g, h))
|
||||||
);
|
).toEqualSqValue(squiggleOutput);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// import { errorValueToString } from "../../src/js/index";
|
import { testRun, expectErrorToBeBounded, SqValueTag } from "./TestHelpers";
|
||||||
import { testRun, expectErrorToBeBounded } from "./TestHelpers";
|
|
||||||
import * as fc from "fast-check";
|
import * as fc from "fast-check";
|
||||||
|
|
||||||
describe("Mean of mixture is weighted average of means", () => {
|
describe("Mean of mixture is weighted average of means", () => {
|
||||||
|
@ -20,7 +19,7 @@ describe("Mean of mixture is weighted average of means", () => {
|
||||||
let lognormalWeight = y / weightDenom;
|
let lognormalWeight = y / weightDenom;
|
||||||
let betaMean = 1 / (1 + b / a);
|
let betaMean = 1 / (1 + b / a);
|
||||||
let lognormalMean = m + s ** 2 / 2;
|
let lognormalMean = m + s ** 2 / 2;
|
||||||
if (res.tag == "number") {
|
if (res.tag === SqValueTag.Number) {
|
||||||
expectErrorToBeBounded(
|
expectErrorToBeBounded(
|
||||||
res.value,
|
res.value,
|
||||||
betaWeight * betaMean + lognormalWeight * lognormalMean,
|
betaWeight * betaMean + lognormalWeight * lognormalMean,
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import { Distribution } from "../../src/js/index";
|
import { expectErrorToBeBounded, testRun, SqValueTag } from "./TestHelpers";
|
||||||
import { expectErrorToBeBounded, failDefault, testRun } from "./TestHelpers";
|
|
||||||
import * as fc from "fast-check";
|
import * as fc from "fast-check";
|
||||||
|
|
||||||
// Beware: float64Array makes it appear in an infinite loop.
|
// Beware: float64Array makes it appear in an infinite loop.
|
||||||
let arrayGen = () =>
|
let arrayGen = () =>
|
||||||
fc
|
fc
|
||||||
.float32Array({
|
.float64Array({
|
||||||
minLength: 10,
|
minLength: 10,
|
||||||
|
max: 999999999999999,
|
||||||
|
min: -999999999999999,
|
||||||
maxLength: 10000,
|
maxLength: 10000,
|
||||||
noDefaultInfinity: true,
|
noDefaultInfinity: true,
|
||||||
noNaN: true,
|
noNaN: true,
|
||||||
|
@ -14,36 +15,41 @@ let arrayGen = () =>
|
||||||
.filter(
|
.filter(
|
||||||
(xs_) => Math.min(...Array.from(xs_)) != Math.max(...Array.from(xs_))
|
(xs_) => Math.min(...Array.from(xs_)) != Math.max(...Array.from(xs_))
|
||||||
);
|
);
|
||||||
describe("cumulative density function", () => {
|
|
||||||
let n = 10000;
|
|
||||||
|
|
||||||
|
let makeSampleSet = (samples: number[]) => {
|
||||||
|
let sampleList = samples.map((x) => x.toFixed(20)).join(",");
|
||||||
|
let result = testRun(`SampleSet.fromList([${sampleList}])`);
|
||||||
|
if (result.tag === SqValueTag.Distribution) {
|
||||||
|
return result.value;
|
||||||
|
} else {
|
||||||
|
fail("Expected to be distribution");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const env = { sampleCount: 10000, xyPointLength: 100 };
|
||||||
|
|
||||||
|
describe("cumulative density function", () => {
|
||||||
// We should fix this.
|
// We should fix this.
|
||||||
test.skip("'s codomain is bounded above", () => {
|
test.skip("'s codomain is bounded above", () => {
|
||||||
fc.assert(
|
fc.assert(
|
||||||
fc.property(arrayGen(), fc.float(), (xs_, x) => {
|
fc.property(arrayGen(), fc.float(), (xs_, x) => {
|
||||||
let xs = Array.from(xs_);
|
let xs = Array.from(xs_);
|
||||||
// Should compute with squiggle strings once interpreter has `sample`
|
// Should compute with squiggle strings once interpreter has `sample`
|
||||||
let dist = new Distribution(
|
let result = makeSampleSet(xs);
|
||||||
{ tag: "SampleSet", value: xs },
|
let cdfValue = result.cdf(env, x).value;
|
||||||
{ sampleCount: n, xyPointLength: 100 }
|
|
||||||
);
|
|
||||||
let cdfValue = dist.cdf(x).value;
|
|
||||||
let epsilon = 5e-7;
|
let epsilon = 5e-7;
|
||||||
expect(cdfValue).toBeLessThanOrEqual(1 + epsilon);
|
expect(cdfValue).toBeLessThanOrEqual(1 + epsilon);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("'s codomain is bounded below", () => {
|
test.skip("'s codomain is bounded below", () => {
|
||||||
fc.assert(
|
fc.assert(
|
||||||
fc.property(arrayGen(), fc.float(), (xs_, x) => {
|
fc.property(arrayGen(), fc.float(), (xs_, x) => {
|
||||||
let xs = Array.from(xs_);
|
let xs = Array.from(xs_);
|
||||||
// Should compute with squiggle strings once interpreter has `sample`
|
// Should compute with squiggle strings once interpreter has `sample`
|
||||||
let dist = new Distribution(
|
let result = makeSampleSet(xs);
|
||||||
{ tag: "SampleSet", value: xs },
|
let cdfValue = result.cdf(env, x).value;
|
||||||
{ sampleCount: n, xyPointLength: 100 }
|
|
||||||
);
|
|
||||||
let cdfValue = dist.cdf(x).value;
|
|
||||||
expect(cdfValue).toBeGreaterThanOrEqual(0);
|
expect(cdfValue).toBeGreaterThanOrEqual(0);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -57,11 +63,8 @@ describe("cumulative density function", () => {
|
||||||
let xs = Array.from(xs_);
|
let xs = Array.from(xs_);
|
||||||
let max = Math.max(...xs);
|
let max = Math.max(...xs);
|
||||||
// Should compute with squiggle strings once interpreter has `sample`
|
// Should compute with squiggle strings once interpreter has `sample`
|
||||||
let dist = new Distribution(
|
let result = makeSampleSet(xs);
|
||||||
{ tag: "SampleSet", value: xs },
|
let cdfValue = result.cdf(env, max).value;
|
||||||
{ sampleCount: n, xyPointLength: 100 }
|
|
||||||
);
|
|
||||||
let cdfValue = dist.cdf(max).value;
|
|
||||||
expect(cdfValue).toBeCloseTo(1.0, 2);
|
expect(cdfValue).toBeCloseTo(1.0, 2);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -74,11 +77,8 @@ describe("cumulative density function", () => {
|
||||||
let xs = Array.from(xs_);
|
let xs = Array.from(xs_);
|
||||||
let min = Math.min(...xs);
|
let min = Math.min(...xs);
|
||||||
// Should compute with squiggle strings once interpreter has `sample`
|
// Should compute with squiggle strings once interpreter has `sample`
|
||||||
let dist = new Distribution(
|
let result = makeSampleSet(xs);
|
||||||
{ tag: "SampleSet", value: xs },
|
let cdfValue = result.cdf(env, min).value;
|
||||||
{ sampleCount: n, xyPointLength: 100 }
|
|
||||||
);
|
|
||||||
let cdfValue = dist.cdf(min).value;
|
|
||||||
let max = Math.max(...xs);
|
let max = Math.max(...xs);
|
||||||
let epsilon = 5e-3;
|
let epsilon = 5e-3;
|
||||||
if (max - min < epsilon) {
|
if (max - min < epsilon) {
|
||||||
|
@ -95,11 +95,8 @@ describe("cumulative density function", () => {
|
||||||
fc.assert(
|
fc.assert(
|
||||||
fc.property(arrayGen(), fc.float(), (xs_, x) => {
|
fc.property(arrayGen(), fc.float(), (xs_, x) => {
|
||||||
let xs = Array.from(xs_);
|
let xs = Array.from(xs_);
|
||||||
let dist = new Distribution(
|
let dist = makeSampleSet(xs);
|
||||||
{ tag: "SampleSet", value: xs },
|
let cdfValue = dist.cdf(env, x).value;
|
||||||
{ sampleCount: n, xyPointLength: 100 }
|
|
||||||
);
|
|
||||||
let cdfValue = dist.cdf(x).value;
|
|
||||||
let max = Math.max(...xs);
|
let max = Math.max(...xs);
|
||||||
if (x > max) {
|
if (x > max) {
|
||||||
let epsilon = (x - max) / x;
|
let epsilon = (x - max) / x;
|
||||||
|
@ -107,21 +104,18 @@ describe("cumulative density function", () => {
|
||||||
} else if (typeof cdfValue == "number") {
|
} else if (typeof cdfValue == "number") {
|
||||||
expect(Math.round(1e5 * cdfValue) / 1e5).toBeLessThanOrEqual(1);
|
expect(Math.round(1e5 * cdfValue) / 1e5).toBeLessThanOrEqual(1);
|
||||||
} else {
|
} else {
|
||||||
failDefault();
|
fail();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("is non-negative everywhere with zero when x is lower than the min", () => {
|
test.skip("is non-negative everywhere with zero when x is lower than the min", () => {
|
||||||
fc.assert(
|
fc.assert(
|
||||||
fc.property(arrayGen(), fc.float(), (xs_, x) => {
|
fc.property(arrayGen(), fc.float(), (xs_, x) => {
|
||||||
let xs = Array.from(xs_);
|
let xs = Array.from(xs_);
|
||||||
let dist = new Distribution(
|
let dist = makeSampleSet(xs);
|
||||||
{ tag: "SampleSet", value: xs },
|
let cdfValue = dist.cdf(env, x).value;
|
||||||
{ sampleCount: n, xyPointLength: 100 }
|
|
||||||
);
|
|
||||||
let cdfValue = dist.cdf(x).value;
|
|
||||||
expect(cdfValue).toBeGreaterThanOrEqual(0);
|
expect(cdfValue).toBeGreaterThanOrEqual(0);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -130,7 +124,7 @@ describe("cumulative density function", () => {
|
||||||
|
|
||||||
// I no longer believe this is true.
|
// I no longer believe this is true.
|
||||||
describe("probability density function", () => {
|
describe("probability density function", () => {
|
||||||
let n = 1000;
|
const env = { sampleCount: 1000, xyPointLength: 100 };
|
||||||
|
|
||||||
test.skip("assigns to the max at most the weight of the mean", () => {
|
test.skip("assigns to the max at most the weight of the mean", () => {
|
||||||
fc.assert(
|
fc.assert(
|
||||||
|
@ -139,12 +133,9 @@ describe("probability density function", () => {
|
||||||
let max = Math.max(...xs);
|
let max = Math.max(...xs);
|
||||||
let mean = xs.reduce((a, b) => a + b, 0.0) / xs.length;
|
let mean = xs.reduce((a, b) => a + b, 0.0) / xs.length;
|
||||||
// Should be from squiggleString once interpreter exposes sampleset
|
// Should be from squiggleString once interpreter exposes sampleset
|
||||||
let dist = new Distribution(
|
let dist = makeSampleSet(xs);
|
||||||
{ tag: "SampleSet", value: xs },
|
let pdfValueMean = dist.pdf(env, mean).value;
|
||||||
{ sampleCount: n, xyPointLength: 100 }
|
let pdfValueMax = dist.pdf(env, max).value;
|
||||||
);
|
|
||||||
let pdfValueMean = dist.pdf(mean).value;
|
|
||||||
let pdfValueMax = dist.pdf(max).value;
|
|
||||||
if (typeof pdfValueMean == "number" && typeof pdfValueMax == "number") {
|
if (typeof pdfValueMean == "number" && typeof pdfValueMax == "number") {
|
||||||
expect(pdfValueMax).toBeLessThanOrEqual(pdfValueMean);
|
expect(pdfValueMax).toBeLessThanOrEqual(pdfValueMean);
|
||||||
} else {
|
} else {
|
||||||
|
@ -164,11 +155,9 @@ describe("mean is mean", () => {
|
||||||
(xs_) => {
|
(xs_) => {
|
||||||
let xs = Array.from(xs_);
|
let xs = Array.from(xs_);
|
||||||
let n = xs.length;
|
let n = xs.length;
|
||||||
let dist = new Distribution(
|
let dist = makeSampleSet(xs);
|
||||||
{ tag: "SampleSet", value: xs },
|
let myEnv = { sampleCount: 2 * n, xyPointLength: 4 * n };
|
||||||
{ sampleCount: 2 * n, xyPointLength: 4 * n }
|
let mean = dist.mean(myEnv);
|
||||||
);
|
|
||||||
let mean = dist.mean();
|
|
||||||
if (typeof mean.value == "number") {
|
if (typeof mean.value == "number") {
|
||||||
expectErrorToBeBounded(
|
expectErrorToBeBounded(
|
||||||
mean.value,
|
mean.value,
|
||||||
|
@ -177,7 +166,7 @@ describe("mean is mean", () => {
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
failDefault();
|
fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -191,11 +180,9 @@ describe("mean is mean", () => {
|
||||||
(xs_) => {
|
(xs_) => {
|
||||||
let xs = Array.from(xs_);
|
let xs = Array.from(xs_);
|
||||||
let n = xs.length;
|
let n = xs.length;
|
||||||
let dist = new Distribution(
|
let dist = makeSampleSet(xs);
|
||||||
{ tag: "SampleSet", value: xs },
|
let myEnv = { sampleCount: Math.floor(n / 2), xyPointLength: 4 * n };
|
||||||
{ sampleCount: Math.floor(n / 2), xyPointLength: 4 * n }
|
let mean = dist.mean(myEnv);
|
||||||
);
|
|
||||||
let mean = dist.mean();
|
|
||||||
if (typeof mean.value == "number") {
|
if (typeof mean.value == "number") {
|
||||||
expectErrorToBeBounded(
|
expectErrorToBeBounded(
|
||||||
mean.value,
|
mean.value,
|
||||||
|
@ -204,7 +191,7 @@ describe("mean is mean", () => {
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
failDefault();
|
fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,7 +5,7 @@ import * as fc from "fast-check";
|
||||||
describe("Scalar manipulation is well-modeled by javascript math", () => {
|
describe("Scalar manipulation is well-modeled by javascript math", () => {
|
||||||
test("in the case of natural logarithms", () => {
|
test("in the case of natural logarithms", () => {
|
||||||
fc.assert(
|
fc.assert(
|
||||||
fc.property(fc.integer(), (x) => {
|
fc.property(fc.nat(), (x) => {
|
||||||
let squiggleString = `log(${x})`;
|
let squiggleString = `log(${x})`;
|
||||||
let squiggleResult = testRun(squiggleString);
|
let squiggleResult = testRun(squiggleString);
|
||||||
if (x == 0) {
|
if (x == 0) {
|
||||||
|
|
|
@ -1,68 +1,31 @@
|
||||||
import {
|
import { run, SqValueTag } from "../../src/js";
|
||||||
run,
|
export { SqValueTag };
|
||||||
runPartial,
|
|
||||||
bindings,
|
|
||||||
squiggleExpression,
|
|
||||||
errorValueToString,
|
|
||||||
defaultImports,
|
|
||||||
defaultBindings,
|
|
||||||
jsImports,
|
|
||||||
} from "../../src/js/index";
|
|
||||||
|
|
||||||
export function testRun(
|
expect.extend({
|
||||||
x: string,
|
toEqualSqValue(x, y) {
|
||||||
bindings: bindings = defaultBindings,
|
// hack via https://github.com/facebook/jest/issues/10329#issuecomment-820656061
|
||||||
imports: jsImports = defaultImports
|
const { getMatchers } = require("expect/build/jestMatchersObject");
|
||||||
): squiggleExpression {
|
return getMatchers().toEqual.call(this, x.toString(), y.toString());
|
||||||
let squiggleResult = run(
|
},
|
||||||
x,
|
});
|
||||||
bindings,
|
|
||||||
{
|
export function testRun(x: string) {
|
||||||
|
const { result, bindings } = run(x, {
|
||||||
|
environment: {
|
||||||
sampleCount: 1000,
|
sampleCount: 1000,
|
||||||
xyPointLength: 100,
|
xyPointLength: 100,
|
||||||
},
|
},
|
||||||
imports
|
});
|
||||||
);
|
|
||||||
if (squiggleResult.tag === "Ok") {
|
if (result.tag === "Ok") {
|
||||||
return squiggleResult.value;
|
return result.value;
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Expected squiggle expression to evaluate but got error: ${errorValueToString(
|
`Expected squiggle expression to evaluate but got error: ${result.value}`
|
||||||
squiggleResult.value
|
|
||||||
)}`
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function testRunPartial(
|
|
||||||
x: string,
|
|
||||||
bindings: bindings = defaultBindings,
|
|
||||||
imports: jsImports = defaultImports
|
|
||||||
): bindings {
|
|
||||||
let squiggleResult = runPartial(
|
|
||||||
x,
|
|
||||||
bindings,
|
|
||||||
{
|
|
||||||
sampleCount: 1000,
|
|
||||||
xyPointLength: 100,
|
|
||||||
},
|
|
||||||
imports
|
|
||||||
);
|
|
||||||
if (squiggleResult.tag === "Ok") {
|
|
||||||
return squiggleResult.value;
|
|
||||||
} else {
|
|
||||||
throw new Error(
|
|
||||||
`Expected squiggle expression to evaluate but got error: ${errorValueToString(
|
|
||||||
squiggleResult.value
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function failDefault() {
|
|
||||||
expect("be reached").toBe("codepath should never");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This appears also in `TestHelpers.res`. According to https://www.math.net/percent-error, it computes
|
* This appears also in `TestHelpers.res`. According to https://www.math.net/percent-error, it computes
|
||||||
* absolute error when numerical stability concerns make me not want to compute relative error.
|
* absolute error when numerical stability concerns make me not want to compute relative error.
|
||||||
|
|
15
packages/squiggle-lang/src/js/SqArray.ts
Normal file
15
packages/squiggle-lang/src/js/SqArray.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import * as RSArray from "../rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_Array.gen";
|
||||||
|
import { wrapValue } from "./SqValue";
|
||||||
|
import { SqValueLocation } from "./SqValueLocation";
|
||||||
|
|
||||||
|
type T = RSArray.squiggleValue_Array;
|
||||||
|
|
||||||
|
export class SqArray {
|
||||||
|
constructor(private _value: T, public location: SqValueLocation) {}
|
||||||
|
|
||||||
|
getValues() {
|
||||||
|
return RSArray.getValues(this._value).map((v, i) =>
|
||||||
|
wrapValue(v, this.location.extend(i))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
115
packages/squiggle-lang/src/js/SqDistribution.ts
Normal file
115
packages/squiggle-lang/src/js/SqDistribution.ts
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
import * as RSDistribution from "../rescript/ForTS/ForTS_Distribution/ForTS_Distribution.gen";
|
||||||
|
import { distributionTag as Tag } from "../rescript/ForTS/ForTS_Distribution/ForTS_Distribution_tag";
|
||||||
|
import { environment } from "../rescript/ForTS/ForTS__Types.gen";
|
||||||
|
import { SqDistributionError } from "./SqDistributionError";
|
||||||
|
import { wrapPointSetDist } from "./SqPointSetDist";
|
||||||
|
import { resultMap2 } from "./types";
|
||||||
|
|
||||||
|
type T = RSDistribution.distribution;
|
||||||
|
export { Tag as SqDistributionTag };
|
||||||
|
|
||||||
|
export const wrapDistribution = (value: T): SqDistribution => {
|
||||||
|
const tag = RSDistribution.getTag(value);
|
||||||
|
|
||||||
|
return new tagToClass[tag](value);
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract class SqAbstractDistribution {
|
||||||
|
abstract tag: Tag;
|
||||||
|
|
||||||
|
constructor(private _value: T) {}
|
||||||
|
|
||||||
|
protected valueMethod = <IR>(rsMethod: (v: T) => IR | null | undefined) => {
|
||||||
|
const value = rsMethod(this._value);
|
||||||
|
if (!value) throw new Error("Internal casting error");
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
pointSet(env: environment) {
|
||||||
|
const innerResult = RSDistribution.toPointSet(this._value, env);
|
||||||
|
return resultMap2(
|
||||||
|
innerResult,
|
||||||
|
wrapPointSetDist,
|
||||||
|
(v: RSDistribution.distributionError) => new SqDistributionError(v)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
RSDistribution.toString(this._value);
|
||||||
|
}
|
||||||
|
|
||||||
|
mean(env: environment) {
|
||||||
|
return resultMap2(
|
||||||
|
RSDistribution.mean({ env }, this._value),
|
||||||
|
(v: number) => v,
|
||||||
|
(e: RSDistribution.distributionError) => new SqDistributionError(e)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pdf(env: environment, n: number) {
|
||||||
|
return resultMap2(
|
||||||
|
RSDistribution.pdf({ env }, this._value, n),
|
||||||
|
(v: number) => v,
|
||||||
|
(e: RSDistribution.distributionError) => new SqDistributionError(e)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
cdf(env: environment, n: number) {
|
||||||
|
return resultMap2(
|
||||||
|
RSDistribution.cdf({ env }, this._value, n),
|
||||||
|
(v: number) => v,
|
||||||
|
(e: RSDistribution.distributionError) => new SqDistributionError(e)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inv(env: environment, n: number) {
|
||||||
|
return resultMap2(
|
||||||
|
RSDistribution.inv({ env }, this._value, n),
|
||||||
|
(v: number) => v,
|
||||||
|
(e: RSDistribution.distributionError) => new SqDistributionError(e)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
stdev(env: environment) {
|
||||||
|
return resultMap2(
|
||||||
|
RSDistribution.stdev({ env }, this._value),
|
||||||
|
(v: number) => v,
|
||||||
|
(e: RSDistribution.distributionError) => new SqDistributionError(e)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqPointSetDistribution extends SqAbstractDistribution {
|
||||||
|
tag = Tag.PointSet;
|
||||||
|
|
||||||
|
value() {
|
||||||
|
return this.valueMethod(RSDistribution.getPointSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqSampleSetDistribution extends SqAbstractDistribution {
|
||||||
|
tag = Tag.SampleSet;
|
||||||
|
|
||||||
|
value() {
|
||||||
|
return this.valueMethod(RSDistribution.getSampleSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqSymbolicDistribution extends SqAbstractDistribution {
|
||||||
|
tag = Tag.Symbolic;
|
||||||
|
|
||||||
|
value() {
|
||||||
|
return this.valueMethod(RSDistribution.getSymbolic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagToClass = {
|
||||||
|
[Tag.PointSet]: SqPointSetDistribution,
|
||||||
|
[Tag.SampleSet]: SqSampleSetDistribution,
|
||||||
|
[Tag.Symbolic]: SqSymbolicDistribution,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type SqDistribution =
|
||||||
|
| SqPointSetDistribution
|
||||||
|
| SqSampleSetDistribution
|
||||||
|
| SqSymbolicDistribution;
|
11
packages/squiggle-lang/src/js/SqDistributionError.ts
Normal file
11
packages/squiggle-lang/src/js/SqDistributionError.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import * as RSDistributionError from "../rescript/ForTS/ForTS_Distribution/ForTS_Distribution_Error.gen";
|
||||||
|
|
||||||
|
type T = RSDistributionError.distributionError;
|
||||||
|
|
||||||
|
export class SqDistributionError {
|
||||||
|
constructor(private _value: T) {}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return RSDistributionError.toString(this._value);
|
||||||
|
}
|
||||||
|
}
|
17
packages/squiggle-lang/src/js/SqError.ts
Normal file
17
packages/squiggle-lang/src/js/SqError.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import * as RSErrorValue from "../rescript/ForTS/ForTS_Reducer_ErrorValue.gen";
|
||||||
|
|
||||||
|
export class SqError {
|
||||||
|
constructor(private _value: RSErrorValue.reducerErrorValue) {}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return RSErrorValue.toString(this._value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static createTodoError(v: string) {
|
||||||
|
return new SqError(RSErrorValue.createTodoError(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
static createOtherError(v: string) {
|
||||||
|
return new SqError(RSErrorValue.createOtherError(v));
|
||||||
|
}
|
||||||
|
}
|
43
packages/squiggle-lang/src/js/SqLambda.ts
Normal file
43
packages/squiggle-lang/src/js/SqLambda.ts
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import * as RSLambda from "../rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_Lambda.gen";
|
||||||
|
import { SqError } from "./SqError";
|
||||||
|
import { SqValue } from "./SqValue";
|
||||||
|
import { SqValueLocation } from "./SqValueLocation";
|
||||||
|
import { result } from "./types";
|
||||||
|
|
||||||
|
type T = RSLambda.squiggleValue_Lambda;
|
||||||
|
|
||||||
|
export class SqLambda {
|
||||||
|
constructor(private _value: T, public location: SqValueLocation) {}
|
||||||
|
|
||||||
|
parameters() {
|
||||||
|
return RSLambda.parameters(this._value);
|
||||||
|
}
|
||||||
|
|
||||||
|
call(args: (number | string)[]): result<SqValue, SqError> {
|
||||||
|
const { project, sourceId } = this.location;
|
||||||
|
// Might be good to use uuid instead, but there's no way to remove sources from projects.
|
||||||
|
// So this is not thread-safe.
|
||||||
|
const callId = "__lambda__";
|
||||||
|
if (this.location.path.root !== "bindings") {
|
||||||
|
return {
|
||||||
|
tag: "Error",
|
||||||
|
value: SqError.createTodoError("Only bindings lambdas can be rendered"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const quote = (arg: string) =>
|
||||||
|
`"${arg.replace(new RegExp('"', "g"), '\\"')}"`;
|
||||||
|
const argsSource = args
|
||||||
|
.map((arg) => (typeof arg === "number" ? arg : quote(arg)))
|
||||||
|
.join(",");
|
||||||
|
const functionNameSource = this.location.path.items
|
||||||
|
.map((item, i) =>
|
||||||
|
typeof item === "string" ? (i ? "." + item : item) : `[${item}]`
|
||||||
|
)
|
||||||
|
.join("");
|
||||||
|
const source = `${functionNameSource}(${argsSource})`;
|
||||||
|
project.setSource(callId, source);
|
||||||
|
project.setContinues(callId, [sourceId]);
|
||||||
|
project.run(callId);
|
||||||
|
return project.getResult(callId);
|
||||||
|
}
|
||||||
|
}
|
7
packages/squiggle-lang/src/js/SqLambdaDeclaration.ts
Normal file
7
packages/squiggle-lang/src/js/SqLambdaDeclaration.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import * as RSDeclaration from "../rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_Declaration.gen";
|
||||||
|
|
||||||
|
type T = RSDeclaration.squiggleValue_Declaration;
|
||||||
|
|
||||||
|
export class SqLambdaDeclaration {
|
||||||
|
constructor(private _value: T) {}
|
||||||
|
}
|
30
packages/squiggle-lang/src/js/SqModule.ts
Normal file
30
packages/squiggle-lang/src/js/SqModule.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import * as RSModuleValue from "../rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_Module.gen";
|
||||||
|
import { SqModuleValue, wrapValue } from "./SqValue";
|
||||||
|
import { SqValueLocation } from "./SqValueLocation";
|
||||||
|
|
||||||
|
export class SqModule {
|
||||||
|
constructor(
|
||||||
|
private _value: RSModuleValue.squiggleValue_Module,
|
||||||
|
public location: SqValueLocation
|
||||||
|
) {}
|
||||||
|
|
||||||
|
entries() {
|
||||||
|
return RSModuleValue.getKeyValuePairs(this._value).map(
|
||||||
|
([k, v]) => [k, wrapValue(v, this.location.extend(k))] as const
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
asValue() {
|
||||||
|
return new SqModuleValue(
|
||||||
|
RSModuleValue.toSquiggleValue(this._value),
|
||||||
|
this.location
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get(k: string) {
|
||||||
|
const v = RSModuleValue.get(this._value, k);
|
||||||
|
return v === undefined || v === null
|
||||||
|
? undefined
|
||||||
|
: wrapValue(v, this.location.extend(k));
|
||||||
|
}
|
||||||
|
}
|
101
packages/squiggle-lang/src/js/SqPointSetDist.ts
Normal file
101
packages/squiggle-lang/src/js/SqPointSetDist.ts
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
import * as _ from "lodash";
|
||||||
|
import { wrapDistribution } from "./SqDistribution";
|
||||||
|
import * as RSPointSetDist from "../rescript/ForTS/ForTS_Distribution/ForTS_Distribution_PointSetDistribution.gen";
|
||||||
|
import { pointSetDistributionTag as Tag } from "../rescript/ForTS/ForTS_Distribution/ForTS_Distribution_PointSetDistribution_tag";
|
||||||
|
|
||||||
|
type T = RSPointSetDist.pointSetDistribution;
|
||||||
|
|
||||||
|
export type SqPoint = { x: number; y: number };
|
||||||
|
export type SqShape = {
|
||||||
|
continuous: SqPoint[];
|
||||||
|
discrete: SqPoint[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const shapePoints = (
|
||||||
|
x: RSPointSetDist.continuousShape | RSPointSetDist.discreteShape
|
||||||
|
): SqPoint[] => {
|
||||||
|
let xs = x.xyShape.xs;
|
||||||
|
let ys = x.xyShape.ys;
|
||||||
|
return _.zipWith(xs, ys, (x, y) => ({ x, y }));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const wrapPointSetDist = (value: T) => {
|
||||||
|
const tag = RSPointSetDist.getTag(value);
|
||||||
|
|
||||||
|
return new tagToClass[tag](value);
|
||||||
|
};
|
||||||
|
|
||||||
|
abstract class SqAbstractPointSetDist {
|
||||||
|
constructor(private _value: T) {}
|
||||||
|
|
||||||
|
abstract asShape(): SqShape;
|
||||||
|
|
||||||
|
protected valueMethod = <IR>(rsMethod: (v: T) => IR | null | undefined) => {
|
||||||
|
const value = rsMethod(this._value);
|
||||||
|
if (!value) throw new Error("Internal casting error");
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
asDistribution() {
|
||||||
|
return wrapDistribution(RSPointSetDist.toDistribution(this._value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqMixedPointSetDist extends SqAbstractPointSetDist {
|
||||||
|
tag = Tag.Mixed as const;
|
||||||
|
|
||||||
|
get value(): RSPointSetDist.mixedShape {
|
||||||
|
return this.valueMethod(RSPointSetDist.getMixed);
|
||||||
|
}
|
||||||
|
|
||||||
|
asShape() {
|
||||||
|
const v = this.value;
|
||||||
|
return {
|
||||||
|
discrete: shapePoints(v.discrete),
|
||||||
|
continuous: shapePoints(v.continuous),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqDiscretePointSetDist extends SqAbstractPointSetDist {
|
||||||
|
tag = Tag.Discrete as const;
|
||||||
|
|
||||||
|
get value(): RSPointSetDist.discreteShape {
|
||||||
|
return this.valueMethod(RSPointSetDist.getDiscrete);
|
||||||
|
}
|
||||||
|
|
||||||
|
asShape() {
|
||||||
|
const v = this.value;
|
||||||
|
return {
|
||||||
|
discrete: shapePoints(v),
|
||||||
|
continuous: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqContinuousPointSetDist extends SqAbstractPointSetDist {
|
||||||
|
tag = Tag.Continuous as const;
|
||||||
|
|
||||||
|
get value(): RSPointSetDist.continuousShape {
|
||||||
|
return this.valueMethod(RSPointSetDist.getContinues);
|
||||||
|
}
|
||||||
|
|
||||||
|
asShape() {
|
||||||
|
const v = this.value;
|
||||||
|
return {
|
||||||
|
discrete: [],
|
||||||
|
continuous: shapePoints(v),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagToClass = {
|
||||||
|
[Tag.Mixed]: SqMixedPointSetDist,
|
||||||
|
[Tag.Discrete]: SqDiscretePointSetDist,
|
||||||
|
[Tag.Continuous]: SqContinuousPointSetDist,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type SqPointSetDist =
|
||||||
|
| SqMixedPointSetDist
|
||||||
|
| SqDiscretePointSetDist
|
||||||
|
| SqContinuousPointSetDist;
|
122
packages/squiggle-lang/src/js/SqProject.ts
Normal file
122
packages/squiggle-lang/src/js/SqProject.ts
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
import * as RSProject from "../rescript/ForTS/ForTS_ReducerProject.gen";
|
||||||
|
import { reducerErrorValue } from "../rescript/ForTS/ForTS_Reducer_ErrorValue.gen";
|
||||||
|
import { environment } from "../rescript/ForTS/ForTS_Distribution/ForTS_Distribution_Environment.gen";
|
||||||
|
import { SqError } from "./SqError";
|
||||||
|
import { SqModule } from "./SqModule";
|
||||||
|
import { wrapValue } from "./SqValue";
|
||||||
|
import { resultMap2 } from "./types";
|
||||||
|
import { SqValueLocation } from "./SqValueLocation";
|
||||||
|
|
||||||
|
export class SqProject {
|
||||||
|
constructor(private _value: RSProject.reducerProject) {}
|
||||||
|
|
||||||
|
static create() {
|
||||||
|
return new SqProject(RSProject.createProject());
|
||||||
|
}
|
||||||
|
|
||||||
|
getSourceIds() {
|
||||||
|
return RSProject.getSourceIds(this._value);
|
||||||
|
}
|
||||||
|
|
||||||
|
setSource(sourceId: string, value: string) {
|
||||||
|
return RSProject.setSource(this._value, sourceId, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSource(sourceId: string) {
|
||||||
|
return RSProject.getSource(this._value, sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
touchSource(sourceId: string) {
|
||||||
|
return RSProject.touchSource(this._value, sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
clean(sourceId: string) {
|
||||||
|
return RSProject.clean(this._value, sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanAll() {
|
||||||
|
return RSProject.cleanAll(this._value);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanResults(sourceId: string) {
|
||||||
|
return RSProject.cleanResults(this._value, sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanAllResults() {
|
||||||
|
return RSProject.cleanAllResults(this._value);
|
||||||
|
}
|
||||||
|
|
||||||
|
getIncludes(sourceId: string) {
|
||||||
|
return resultMap2(
|
||||||
|
RSProject.getIncludes(this._value, sourceId),
|
||||||
|
(a) => a,
|
||||||
|
(v: reducerErrorValue) => new SqError(v)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getContinues(sourceId: string) {
|
||||||
|
return RSProject.getContinues(this._value, sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
setContinues(sourceId: string, continues: string[]) {
|
||||||
|
return RSProject.setContinues(this._value, sourceId, continues);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDependencies(sourceId: string) {
|
||||||
|
return RSProject.getDependencies(this._value, sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDependents(sourceId: string) {
|
||||||
|
return RSProject.getDependents(this._value, sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
getRunOrder() {
|
||||||
|
return RSProject.getRunOrder(this._value);
|
||||||
|
}
|
||||||
|
|
||||||
|
getRunOrderFor(sourceId: string) {
|
||||||
|
return RSProject.getRunOrderFor(this._value, sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
parseIncludes(sourceId: string) {
|
||||||
|
return RSProject.parseIncludes(this._value, sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
run(sourceId: string) {
|
||||||
|
return RSProject.run(this._value, sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
runAll() {
|
||||||
|
return RSProject.runAll(this._value);
|
||||||
|
}
|
||||||
|
|
||||||
|
getBindings(sourceId: string) {
|
||||||
|
return new SqModule(
|
||||||
|
RSProject.getBindings(this._value, sourceId),
|
||||||
|
new SqValueLocation(this, sourceId, {
|
||||||
|
root: "bindings",
|
||||||
|
items: [],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getResult(sourceId: string) {
|
||||||
|
const innerResult = RSProject.getResult(this._value, sourceId);
|
||||||
|
return resultMap2(
|
||||||
|
innerResult,
|
||||||
|
(v) =>
|
||||||
|
wrapValue(
|
||||||
|
v,
|
||||||
|
new SqValueLocation(this, sourceId, {
|
||||||
|
root: "result",
|
||||||
|
items: [],
|
||||||
|
})
|
||||||
|
),
|
||||||
|
(v: reducerErrorValue) => new SqError(v)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
setEnvironment(environment: environment) {
|
||||||
|
RSProject.setEnvironment(this._value, environment);
|
||||||
|
}
|
||||||
|
}
|
15
packages/squiggle-lang/src/js/SqRecord.ts
Normal file
15
packages/squiggle-lang/src/js/SqRecord.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import * as RSRecord from "../rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_Record.gen";
|
||||||
|
import { wrapValue } from "./SqValue";
|
||||||
|
import { SqValueLocation } from "./SqValueLocation";
|
||||||
|
|
||||||
|
type T = RSRecord.squiggleValue_Record;
|
||||||
|
|
||||||
|
export class SqRecord {
|
||||||
|
constructor(private _value: T, public location: SqValueLocation) {}
|
||||||
|
|
||||||
|
entries() {
|
||||||
|
return RSRecord.getKeyValuePairs(this._value).map(
|
||||||
|
([k, v]) => [k, wrapValue(v, this.location.extend(k))] as const
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
7
packages/squiggle-lang/src/js/SqType.ts
Normal file
7
packages/squiggle-lang/src/js/SqType.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import * as RSType from "../rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_Type.gen";
|
||||||
|
|
||||||
|
type T = RSType.squiggleValue_Type;
|
||||||
|
|
||||||
|
export class SqType {
|
||||||
|
constructor(private _value: T) {}
|
||||||
|
}
|
216
packages/squiggle-lang/src/js/SqValue.ts
Normal file
216
packages/squiggle-lang/src/js/SqValue.ts
Normal file
|
@ -0,0 +1,216 @@
|
||||||
|
import * as RSValue from "../rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue.gen";
|
||||||
|
import { squiggleValueTag as Tag } from "../rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_tag";
|
||||||
|
import { wrapDistribution } from "./SqDistribution";
|
||||||
|
import { SqLambda } from "./SqLambda";
|
||||||
|
import { SqLambdaDeclaration } from "./SqLambdaDeclaration";
|
||||||
|
import { SqModule } from "./SqModule";
|
||||||
|
import { SqRecord } from "./SqRecord";
|
||||||
|
import { SqArray } from "./SqArray";
|
||||||
|
import { SqType } from "./SqType";
|
||||||
|
import { SqProject } from "./SqProject";
|
||||||
|
import { SqValueLocation } from "./SqValueLocation";
|
||||||
|
|
||||||
|
export { Tag as SqValueTag };
|
||||||
|
|
||||||
|
type T = RSValue.squiggleValue;
|
||||||
|
|
||||||
|
export const wrapValue = (value: T, location: SqValueLocation): SqValue => {
|
||||||
|
const tag = RSValue.getTag(value);
|
||||||
|
|
||||||
|
return new tagToClass[tag](value, location);
|
||||||
|
};
|
||||||
|
|
||||||
|
export abstract class SqAbstractValue {
|
||||||
|
abstract tag: Tag;
|
||||||
|
|
||||||
|
constructor(private _value: T, public location: SqValueLocation) {}
|
||||||
|
|
||||||
|
protected valueMethod = <IR>(rsMethod: (v: T) => IR | null | undefined) => {
|
||||||
|
const value = rsMethod(this._value);
|
||||||
|
if (value === undefined || value === null) {
|
||||||
|
throw new Error("Internal casting error");
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return RSValue.toString(this._value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqArrayValue extends SqAbstractValue {
|
||||||
|
tag = Tag.Array as const;
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return new SqArray(this.valueMethod(RSValue.getArray), this.location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqArrayStringValue extends SqAbstractValue {
|
||||||
|
tag = Tag.ArrayString as const;
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return this.valueMethod(RSValue.getArrayString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqBoolValue extends SqAbstractValue {
|
||||||
|
tag = Tag.Bool as const;
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return this.valueMethod(RSValue.getBool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqCallValue extends SqAbstractValue {
|
||||||
|
tag = Tag.Call as const;
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return this.valueMethod(RSValue.getCall);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqDateValue extends SqAbstractValue {
|
||||||
|
tag = Tag.Date as const;
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return this.valueMethod(RSValue.getDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqDeclarationValue extends SqAbstractValue {
|
||||||
|
tag = Tag.Declaration as const;
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return new SqLambdaDeclaration(this.valueMethod(RSValue.getDeclaration));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqDistributionValue extends SqAbstractValue {
|
||||||
|
tag = Tag.Distribution as const;
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return wrapDistribution(this.valueMethod(RSValue.getDistribution));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqLambdaValue extends SqAbstractValue {
|
||||||
|
tag = Tag.Lambda as const;
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return new SqLambda(this.valueMethod(RSValue.getLambda), this.location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqModuleValue extends SqAbstractValue {
|
||||||
|
tag = Tag.Module as const;
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return new SqModule(this.valueMethod(RSValue.getModule), this.location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqNumberValue extends SqAbstractValue {
|
||||||
|
tag = Tag.Number as const;
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return this.valueMethod(RSValue.getNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqRecordValue extends SqAbstractValue {
|
||||||
|
tag = Tag.Record as const;
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return new SqRecord(this.valueMethod(RSValue.getRecord), this.location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqStringValue extends SqAbstractValue {
|
||||||
|
tag = Tag.String as const;
|
||||||
|
|
||||||
|
get value(): string {
|
||||||
|
return this.valueMethod(RSValue.getString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqSymbolValue extends SqAbstractValue {
|
||||||
|
tag = Tag.Symbol as const;
|
||||||
|
|
||||||
|
get value(): string {
|
||||||
|
return this.valueMethod(RSValue.getSymbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqTimeDurationValue extends SqAbstractValue {
|
||||||
|
tag = Tag.TimeDuration as const;
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return this.valueMethod(RSValue.getTimeDuration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqTypeValue extends SqAbstractValue {
|
||||||
|
tag = Tag.Type as const;
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return new SqType(this.valueMethod(RSValue.getType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqTypeIdentifierValue extends SqAbstractValue {
|
||||||
|
tag = Tag.TypeIdentifier as const;
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return this.valueMethod(RSValue.getTypeIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SqVoidValue extends SqAbstractValue {
|
||||||
|
tag = Tag.Void as const;
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagToClass = {
|
||||||
|
[Tag.Array]: SqArrayValue,
|
||||||
|
[Tag.ArrayString]: SqArrayStringValue,
|
||||||
|
[Tag.Bool]: SqBoolValue,
|
||||||
|
[Tag.Call]: SqCallValue,
|
||||||
|
[Tag.Date]: SqDateValue,
|
||||||
|
[Tag.Declaration]: SqDeclarationValue,
|
||||||
|
[Tag.Distribution]: SqDistributionValue,
|
||||||
|
[Tag.Lambda]: SqLambdaValue,
|
||||||
|
[Tag.Module]: SqModuleValue,
|
||||||
|
[Tag.Number]: SqNumberValue,
|
||||||
|
[Tag.Record]: SqRecordValue,
|
||||||
|
[Tag.String]: SqStringValue,
|
||||||
|
[Tag.Symbol]: SqSymbolValue,
|
||||||
|
[Tag.TimeDuration]: SqTimeDurationValue,
|
||||||
|
[Tag.Type]: SqTypeValue,
|
||||||
|
[Tag.TypeIdentifier]: SqTypeIdentifierValue,
|
||||||
|
[Tag.Void]: SqVoidValue,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
// type SqValue = typeof tagToClass[keyof typeof tagToClass];
|
||||||
|
export type SqValue =
|
||||||
|
| SqArrayValue
|
||||||
|
| SqArrayStringValue
|
||||||
|
| SqBoolValue
|
||||||
|
| SqCallValue
|
||||||
|
| SqDateValue
|
||||||
|
| SqDeclarationValue
|
||||||
|
| SqDistributionValue
|
||||||
|
| SqLambdaValue
|
||||||
|
| SqModuleValue
|
||||||
|
| SqNumberValue
|
||||||
|
| SqRecordValue
|
||||||
|
| SqStringValue
|
||||||
|
| SqSymbolValue
|
||||||
|
| SqTimeDurationValue
|
||||||
|
| SqTypeValue
|
||||||
|
| SqTypeIdentifierValue
|
||||||
|
| SqVoidValue;
|
24
packages/squiggle-lang/src/js/SqValueLocation.ts
Normal file
24
packages/squiggle-lang/src/js/SqValueLocation.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { isParenthesisNode } from "mathjs";
|
||||||
|
import { SqProject } from "./SqProject";
|
||||||
|
|
||||||
|
type PathItem = string | number;
|
||||||
|
|
||||||
|
type SqValuePath = {
|
||||||
|
root: "result" | "bindings";
|
||||||
|
items: PathItem[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export class SqValueLocation {
|
||||||
|
constructor(
|
||||||
|
public project: SqProject,
|
||||||
|
public sourceId: string,
|
||||||
|
public path: SqValuePath
|
||||||
|
) {}
|
||||||
|
|
||||||
|
extend(item: PathItem) {
|
||||||
|
return new SqValueLocation(this.project, this.sourceId, {
|
||||||
|
root: this.path.root,
|
||||||
|
items: [...this.path.items, item],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,252 +0,0 @@
|
||||||
import * as _ from "lodash";
|
|
||||||
import {
|
|
||||||
genericDist,
|
|
||||||
continuousShape,
|
|
||||||
discreteShape,
|
|
||||||
environment,
|
|
||||||
distributionError,
|
|
||||||
toPointSet,
|
|
||||||
distributionErrorToString,
|
|
||||||
} from "../rescript/TypescriptInterface.gen";
|
|
||||||
import { result, resultMap, Ok } from "./types";
|
|
||||||
import {
|
|
||||||
Constructors_mean,
|
|
||||||
Constructors_stdev,
|
|
||||||
Constructors_sample,
|
|
||||||
Constructors_pdf,
|
|
||||||
Constructors_cdf,
|
|
||||||
Constructors_inv,
|
|
||||||
Constructors_normalize,
|
|
||||||
Constructors_isNormalized,
|
|
||||||
Constructors_toPointSet,
|
|
||||||
Constructors_toSampleSet,
|
|
||||||
Constructors_truncate,
|
|
||||||
Constructors_inspect,
|
|
||||||
Constructors_toString,
|
|
||||||
Constructors_toSparkline,
|
|
||||||
Constructors_algebraicAdd,
|
|
||||||
Constructors_algebraicMultiply,
|
|
||||||
Constructors_algebraicDivide,
|
|
||||||
Constructors_algebraicSubtract,
|
|
||||||
Constructors_algebraicLogarithm,
|
|
||||||
Constructors_algebraicPower,
|
|
||||||
Constructors_pointwiseAdd,
|
|
||||||
Constructors_pointwiseMultiply,
|
|
||||||
Constructors_pointwiseDivide,
|
|
||||||
Constructors_pointwiseSubtract,
|
|
||||||
Constructors_pointwiseLogarithm,
|
|
||||||
Constructors_pointwisePower,
|
|
||||||
} from "../rescript/Distributions/DistributionOperation.gen";
|
|
||||||
|
|
||||||
export type point = { x: number; y: number };
|
|
||||||
|
|
||||||
function shapePoints(x: continuousShape | discreteShape): point[] {
|
|
||||||
let xs = x.xyShape.xs;
|
|
||||||
let ys = x.xyShape.ys;
|
|
||||||
return _.zipWith(xs, ys, (x, y) => ({ x, y }));
|
|
||||||
}
|
|
||||||
export type shape = {
|
|
||||||
continuous: point[];
|
|
||||||
discrete: point[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export class Distribution {
|
|
||||||
t: genericDist;
|
|
||||||
env: environment;
|
|
||||||
|
|
||||||
constructor(t: genericDist, env: environment) {
|
|
||||||
this.t = t;
|
|
||||||
this.env = env;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
mapResultDist(
|
|
||||||
r: result<genericDist, distributionError>
|
|
||||||
): result<Distribution, distributionError> {
|
|
||||||
return resultMap(r, (v: genericDist) => new Distribution(v, this.env));
|
|
||||||
}
|
|
||||||
|
|
||||||
mean(): result<number, distributionError> {
|
|
||||||
return Constructors_mean({ env: this.env }, this.t);
|
|
||||||
}
|
|
||||||
|
|
||||||
stdev(): result<number, distributionError> {
|
|
||||||
return Constructors_stdev({ env: this.env }, this.t);
|
|
||||||
}
|
|
||||||
|
|
||||||
sample(): result<number, distributionError> {
|
|
||||||
return Constructors_sample({ env: this.env }, this.t);
|
|
||||||
}
|
|
||||||
|
|
||||||
pdf(n: number): result<number, distributionError> {
|
|
||||||
return Constructors_pdf({ env: this.env }, this.t, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
cdf(n: number): result<number, distributionError> {
|
|
||||||
return Constructors_cdf({ env: this.env }, this.t, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
inv(n: number): result<number, distributionError> {
|
|
||||||
return Constructors_inv({ env: this.env }, this.t, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
isNormalized(): result<boolean, distributionError> {
|
|
||||||
return Constructors_isNormalized({ env: this.env }, this.t);
|
|
||||||
}
|
|
||||||
|
|
||||||
normalize(): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(
|
|
||||||
Constructors_normalize({ env: this.env }, this.t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
type() {
|
|
||||||
return this.t.tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
pointSet(): result<shape, distributionError> {
|
|
||||||
let pointSet = toPointSet(
|
|
||||||
this.t,
|
|
||||||
{
|
|
||||||
xyPointLength: this.env.xyPointLength,
|
|
||||||
sampleCount: this.env.sampleCount,
|
|
||||||
},
|
|
||||||
undefined
|
|
||||||
);
|
|
||||||
if (pointSet.tag === "Ok") {
|
|
||||||
let distribution = pointSet.value;
|
|
||||||
if (distribution.tag === "Continuous") {
|
|
||||||
return Ok({
|
|
||||||
continuous: shapePoints(distribution.value),
|
|
||||||
discrete: [],
|
|
||||||
});
|
|
||||||
} else if (distribution.tag === "Discrete") {
|
|
||||||
return Ok({
|
|
||||||
discrete: shapePoints(distribution.value),
|
|
||||||
continuous: [],
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return Ok({
|
|
||||||
discrete: shapePoints(distribution.value.discrete),
|
|
||||||
continuous: shapePoints(distribution.value.continuous),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return pointSet;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toPointSet(): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(
|
|
||||||
Constructors_toPointSet({ env: this.env }, this.t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
toSampleSet(n: number): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(
|
|
||||||
Constructors_toSampleSet({ env: this.env }, this.t, n)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
truncate(
|
|
||||||
left: number,
|
|
||||||
right: number
|
|
||||||
): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(
|
|
||||||
Constructors_truncate({ env: this.env }, this.t, left, right)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
inspect(): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(Constructors_inspect({ env: this.env }, this.t));
|
|
||||||
}
|
|
||||||
|
|
||||||
toString(): string {
|
|
||||||
let result = Constructors_toString({ env: this.env }, this.t);
|
|
||||||
if (result.tag === "Ok") {
|
|
||||||
return result.value;
|
|
||||||
} else {
|
|
||||||
return distributionErrorToString(result.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toSparkline(n: number): result<string, distributionError> {
|
|
||||||
return Constructors_toSparkline({ env: this.env }, this.t, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
algebraicAdd(d2: Distribution): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(
|
|
||||||
Constructors_algebraicAdd({ env: this.env }, this.t, d2.t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
algebraicMultiply(d2: Distribution): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(
|
|
||||||
Constructors_algebraicMultiply({ env: this.env }, this.t, d2.t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
algebraicDivide(d2: Distribution): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(
|
|
||||||
Constructors_algebraicDivide({ env: this.env }, this.t, d2.t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
algebraicSubtract(d2: Distribution): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(
|
|
||||||
Constructors_algebraicSubtract({ env: this.env }, this.t, d2.t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
algebraicLogarithm(
|
|
||||||
d2: Distribution
|
|
||||||
): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(
|
|
||||||
Constructors_algebraicLogarithm({ env: this.env }, this.t, d2.t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
algebraicPower(d2: Distribution): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(
|
|
||||||
Constructors_algebraicPower({ env: this.env }, this.t, d2.t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pointwiseAdd(d2: Distribution): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(
|
|
||||||
Constructors_pointwiseAdd({ env: this.env }, this.t, d2.t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pointwiseMultiply(d2: Distribution): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(
|
|
||||||
Constructors_pointwiseMultiply({ env: this.env }, this.t, d2.t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pointwiseDivide(d2: Distribution): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(
|
|
||||||
Constructors_pointwiseDivide({ env: this.env }, this.t, d2.t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pointwiseSubtract(d2: Distribution): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(
|
|
||||||
Constructors_pointwiseSubtract({ env: this.env }, this.t, d2.t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pointwiseLogarithm(
|
|
||||||
d2: Distribution
|
|
||||||
): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(
|
|
||||||
Constructors_pointwiseLogarithm({ env: this.env }, this.t, d2.t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pointwisePower(d2: Distribution): result<Distribution, distributionError> {
|
|
||||||
return this.mapResultDist(
|
|
||||||
Constructors_pointwisePower({ env: this.env }, this.t, d2.t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,219 +1,36 @@
|
||||||
/* Some of the types have moved to ForTS__Types.
|
import { environment } from "../rescript/ForTS/ForTS_ReducerProject.gen";
|
||||||
Needs to be reimported here if necessary and distribution related
|
import { SqProject } from "./SqProject";
|
||||||
|
import { SqValue, SqValueTag } from "./SqValue";
|
||||||
We only need distribution related extras for back compatibility. Umur
|
export { SqValueLocation } from "./SqValueLocation";
|
||||||
|
export { result } from "../rescript/ForTS/ForTS_Result_tag";
|
||||||
Instead of a global function namespace we should use modules under ForTS directly maybe renaming them for ease.
|
export { SqDistribution, SqDistributionTag } from "./SqDistribution";
|
||||||
|
export { SqDistributionError } from "./SqDistributionError";
|
||||||
.e.g. Project.run(project)
|
export { SqRecord } from "./SqRecord";
|
||||||
.e.g. Distribution.makeSampleSetDist
|
export { SqLambda } from "./SqLambda";
|
||||||
|
export { SqProject };
|
||||||
*/
|
export { SqValue, SqValueTag };
|
||||||
|
|
||||||
import * as _ from "lodash";
|
|
||||||
import type {
|
|
||||||
environment,
|
|
||||||
expressionValue,
|
|
||||||
externalBindings,
|
|
||||||
errorValue,
|
|
||||||
} from "../rescript/TypescriptInterface.gen";
|
|
||||||
import {
|
|
||||||
defaultEnvironment,
|
|
||||||
evaluatePartialUsingExternalBindings,
|
|
||||||
evaluateUsingOptions,
|
|
||||||
foreignFunctionInterface,
|
|
||||||
} from "../rescript/TypescriptInterface.gen";
|
|
||||||
export {
|
export {
|
||||||
makeSampleSetDist,
|
environment,
|
||||||
errorValueToString,
|
defaultEnvironment,
|
||||||
distributionErrorToString,
|
} from "../rescript/ForTS/ForTS_Distribution/ForTS_Distribution.gen";
|
||||||
} from "../rescript/TypescriptInterface.gen";
|
export { SqError } from "./SqError";
|
||||||
export type {
|
export { SqShape } from "./SqPointSetDist";
|
||||||
distributionError,
|
|
||||||
declarationArg,
|
|
||||||
declaration,
|
|
||||||
} from "../rescript/TypescriptInterface.gen";
|
|
||||||
export type { errorValue, externalBindings as bindings, jsImports };
|
|
||||||
import {
|
|
||||||
jsValueToBinding,
|
|
||||||
jsValueToExpressionValue,
|
|
||||||
jsValue,
|
|
||||||
rescriptExport,
|
|
||||||
squiggleExpression,
|
|
||||||
convertRawToTypescript,
|
|
||||||
lambdaValue,
|
|
||||||
} from "./rescript_interop";
|
|
||||||
import { result, resultMap, tag, tagged } from "./types";
|
|
||||||
import { Distribution, shape } from "./distribution";
|
|
||||||
|
|
||||||
export { Distribution, resultMap, defaultEnvironment };
|
export { resultMap } from "./types";
|
||||||
export type { result, shape, environment, lambdaValue, squiggleExpression };
|
|
||||||
|
|
||||||
export { parse } from "./parse";
|
export const run = (
|
||||||
|
code: string,
|
||||||
export let defaultSamplingInputs: environment = {
|
options?: {
|
||||||
sampleCount: 10000,
|
environment?: environment;
|
||||||
xyPointLength: 10000,
|
}
|
||||||
|
) => {
|
||||||
|
const project = SqProject.create();
|
||||||
|
project.setSource("main", code);
|
||||||
|
if (options?.environment) {
|
||||||
|
project.setEnvironment(options.environment);
|
||||||
|
}
|
||||||
|
project.run("main");
|
||||||
|
const result = project.getResult("main");
|
||||||
|
const bindings = project.getBindings("main");
|
||||||
|
return { result, bindings };
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Umur: All the functions below are invalid. ForTS_Reducer project is the new way to do this. */
|
|
||||||
|
|
||||||
// export function run(
|
|
||||||
// squiggleString: string,
|
|
||||||
// bindings?: externalBindings,
|
|
||||||
// environment?: environment,
|
|
||||||
// imports?: jsImports
|
|
||||||
// ): result<squiggleExpression, errorValue> {
|
|
||||||
// let b = bindings ? bindings : defaultBindings;
|
|
||||||
// let i = imports ? imports : defaultImports;
|
|
||||||
// let e = environment ? environment : defaultEnvironment;
|
|
||||||
// let res: result<expressionValue, errorValue> = evaluateUsingOptions(
|
|
||||||
// { externalBindings: mergeImportsWithBindings(b, i), environment: e },
|
|
||||||
// squiggleString
|
|
||||||
// );
|
|
||||||
// return resultMap(res, (x) => createTsExport(x, e));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Run Partial. A partial is a block of code that doesn't return a value
|
|
||||||
// export function runPartial(
|
|
||||||
// squiggleString: string,
|
|
||||||
// bindings?: externalBindings,
|
|
||||||
// environment?: environment,
|
|
||||||
// imports?: jsImports
|
|
||||||
// ): result<externalBindings, errorValue> {
|
|
||||||
// let b = bindings ? bindings : defaultBindings;
|
|
||||||
// let i = imports ? imports : defaultImports;
|
|
||||||
// let e = environment ? environment : defaultEnvironment;
|
|
||||||
|
|
||||||
// return evaluatePartialUsingExternalBindings(
|
|
||||||
// squiggleString,
|
|
||||||
// mergeImportsWithBindings(b, i),
|
|
||||||
// e
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export function runForeign(
|
|
||||||
// fn: lambdaValue,
|
|
||||||
// args: jsValue[],
|
|
||||||
// environment?: environment
|
|
||||||
// ): result<squiggleExpression, errorValue> {
|
|
||||||
// let e = environment ? environment : defaultEnvironment;
|
|
||||||
// let res: result<expressionValue, errorValue> = foreignFunctionInterface(
|
|
||||||
// fn,
|
|
||||||
// args.map(jsValueToExpressionValue),
|
|
||||||
// e
|
|
||||||
// );
|
|
||||||
// return resultMap(res, (x) => createTsExport(x, e));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function mergeImportsWithBindings(
|
|
||||||
// bindings: externalBindings,
|
|
||||||
// imports: jsImports
|
|
||||||
// ): externalBindings {
|
|
||||||
// let transformedImports = Object.fromEntries(
|
|
||||||
// Object.entries(imports).map(([key, value]) => [
|
|
||||||
// "$" + key,
|
|
||||||
// jsValueToBinding(value),
|
|
||||||
// ])
|
|
||||||
// );
|
|
||||||
// return _.merge(bindings, transformedImports);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// type jsImports = { [key: string]: jsValue };
|
|
||||||
|
|
||||||
// export let defaultImports: jsImports = {};
|
|
||||||
// export let defaultBindings: externalBindings = {};
|
|
||||||
|
|
||||||
// export function mergeBindings(
|
|
||||||
// allBindings: externalBindings[]
|
|
||||||
// ): externalBindings {
|
|
||||||
// return allBindings.reduce((acc, x) => ({ ...acc, ...x }));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function createTsExport(
|
|
||||||
// x: expressionValue,
|
|
||||||
// environment: environment
|
|
||||||
// ): squiggleExpression {
|
|
||||||
// switch (x) {
|
|
||||||
// case "EvVoid":
|
|
||||||
// return tag("void", "");
|
|
||||||
// default: {
|
|
||||||
// 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 =>
|
|
||||||
// convertRawToTypescript(
|
|
||||||
// arrayItem as unknown as rescriptExport,
|
|
||||||
// environment
|
|
||||||
// )
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
// case "EvArrayString":
|
|
||||||
// return tag("arraystring", x.value);
|
|
||||||
// case "EvBool":
|
|
||||||
// return tag("boolean", x.value);
|
|
||||||
// case "EvCall":
|
|
||||||
// return tag("call", x.value);
|
|
||||||
// case "EvLambda":
|
|
||||||
// return tag("lambda", x.value);
|
|
||||||
// case "EvDistribution":
|
|
||||||
// return tag("distribution", new Distribution(x.value, environment));
|
|
||||||
// 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, environment)
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
// return result;
|
|
||||||
// case "EvString":
|
|
||||||
// return tag("string", x.value);
|
|
||||||
// case "EvSymbol":
|
|
||||||
// return tag("symbol", x.value);
|
|
||||||
// case "EvDate":
|
|
||||||
// return tag("date", x.value);
|
|
||||||
// case "EvTimeDuration":
|
|
||||||
// return tag("timeDuration", x.value);
|
|
||||||
// case "EvDeclaration":
|
|
||||||
// return tag("lambdaDeclaration", x.value);
|
|
||||||
// case "EvTypeIdentifier":
|
|
||||||
// return tag("typeIdentifier", x.value);
|
|
||||||
// case "EvType":
|
|
||||||
// let typeResult: tagged<
|
|
||||||
// "type",
|
|
||||||
// { [key: string]: squiggleExpression }
|
|
||||||
// > = tag(
|
|
||||||
// "type",
|
|
||||||
// _.mapValues(x.value, (x: unknown) =>
|
|
||||||
// convertRawToTypescript(x as rescriptExport, environment)
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
// return typeResult;
|
|
||||||
// case "EvModule":
|
|
||||||
// let moduleResult: tagged<
|
|
||||||
// "module",
|
|
||||||
// { [key: string]: squiggleExpression }
|
|
||||||
// > = tag(
|
|
||||||
// "module",
|
|
||||||
// _.mapValues(x.value, (x: unknown) =>
|
|
||||||
// convertRawToTypescript(x as rescriptExport, environment)
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
// return moduleResult;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
import {
|
// import {
|
||||||
errorValue,
|
// errorValue,
|
||||||
parse as parseRescript,
|
// parse as parseRescript,
|
||||||
} from "../rescript/TypescriptInterface.gen";
|
// } from "../rescript/TypescriptInterface.gen";
|
||||||
import { result } from "./types";
|
// import { result } from "./types";
|
||||||
import { AnyPeggyNode } from "../rescript/Reducer/Reducer_Peggy/helpers";
|
// import { AnyPeggyNode } from "../rescript/Reducer/Reducer_Peggy/helpers";
|
||||||
|
|
||||||
export function parse(
|
// export function parse(
|
||||||
squiggleString: string
|
// squiggleString: string
|
||||||
): result<AnyPeggyNode, Extract<errorValue, { tag: "RESyntaxError" }>> {
|
// ): result<AnyPeggyNode, Extract<errorValue, { tag: "RESyntaxError" }>> {
|
||||||
const maybeExpression = parseRescript(squiggleString);
|
// const maybeExpression = parseRescript(squiggleString);
|
||||||
if (maybeExpression.tag === "Ok") {
|
// if (maybeExpression.tag === "Ok") {
|
||||||
return { tag: "Ok", value: maybeExpression.value as AnyPeggyNode };
|
// return { tag: "Ok", value: maybeExpression.value as AnyPeggyNode };
|
||||||
} else {
|
// } else {
|
||||||
if (
|
// if (
|
||||||
typeof maybeExpression.value !== "object" ||
|
// typeof maybeExpression.value !== "object" ||
|
||||||
maybeExpression.value.tag !== "RESyntaxError"
|
// maybeExpression.value.tag !== "RESyntaxError"
|
||||||
) {
|
// ) {
|
||||||
throw new Error("Expected syntax error");
|
// throw new Error("Expected syntax error");
|
||||||
}
|
// }
|
||||||
return { tag: "Error", value: maybeExpression.value };
|
// return { tag: "Error", value: maybeExpression.value };
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
|
@ -1,279 +0,0 @@
|
||||||
/**
|
|
||||||
Umur: Delete this file! There is nothing left to see here.
|
|
||||||
**/
|
|
||||||
|
|
||||||
// import * as _ from "lodash";
|
|
||||||
// import type {
|
|
||||||
// // expressionValue,
|
|
||||||
// mixedShape,
|
|
||||||
// sampleSetDist,
|
|
||||||
// genericDist,
|
|
||||||
// // environment,
|
|
||||||
// symbolicDist,
|
|
||||||
// discreteShape,
|
|
||||||
// continuousShape,
|
|
||||||
// // lambdaValue,
|
|
||||||
// // lambdaDeclaration,
|
|
||||||
// // declarationArg,
|
|
||||||
// } from "../rescript/TypescriptInterface.gen";
|
|
||||||
// import { Distribution } from "./distribution";
|
|
||||||
// import { tagged, tag } from "./types";
|
|
||||||
// This file is here to compensate for genType not fully recursively converting types
|
|
||||||
|
|
||||||
// Raw rescript types.
|
|
||||||
// Umur: Rescript expression values are opaque!
|
|
||||||
// export type rescriptExport =
|
|
||||||
// | 0 // EvVoid
|
|
||||||
// | {
|
|
||||||
// TAG: 0; // EvArray
|
|
||||||
// _0: rescriptExport[];
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 1; // EvString
|
|
||||||
// _0: string[];
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 2; // EvBool
|
|
||||||
// _0: boolean;
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 3; // EvCall
|
|
||||||
// _0: string;
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 4; // EvDistribution
|
|
||||||
// _0: rescriptDist;
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 5; // EvLambda
|
|
||||||
// _0: lambdaValue;
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 6; // EvNumber
|
|
||||||
// _0: number;
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 7; // EvRecord
|
|
||||||
// _0: { [key: string]: rescriptExport };
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 8; // EvString
|
|
||||||
// _0: string;
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 9; // EvSymbol
|
|
||||||
// _0: string;
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 10; // EvDate
|
|
||||||
// _0: Date;
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 11; // EvTimeDuration
|
|
||||||
// _0: number;
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 12; // EvDeclaration
|
|
||||||
// _0: rescriptLambdaDeclaration;
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 13; // EvTypeIdentifier
|
|
||||||
// _0: string;
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 14; // EvModule
|
|
||||||
// _0: { [key: string]: rescriptExport };
|
|
||||||
// };
|
|
||||||
|
|
||||||
// Umur: opaque type
|
|
||||||
// type rescriptDist =
|
|
||||||
// | { TAG: 0; _0: rescriptPointSetDist }
|
|
||||||
// | { TAG: 1; _0: sampleSetDist }
|
|
||||||
// | { TAG: 2; _0: symbolicDist };
|
|
||||||
|
|
||||||
// Umur: opaque type, no conversion
|
|
||||||
// type rescriptPointSetDist =
|
|
||||||
// | {
|
|
||||||
// TAG: 0; // Mixed
|
|
||||||
// _0: mixedShape;
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 1; // Discrete
|
|
||||||
// _0: discreteShape;
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 2; // ContinuousShape
|
|
||||||
// _0: continuousShape;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// type rescriptLambdaDeclaration = {
|
|
||||||
// readonly fn: lambdaValue;
|
|
||||||
// readonly args: rescriptDeclarationArg[];
|
|
||||||
// };
|
|
||||||
|
|
||||||
// type rescriptDeclarationArg =
|
|
||||||
// | {
|
|
||||||
// TAG: 0; // Float
|
|
||||||
// min: number;
|
|
||||||
// max: number;
|
|
||||||
// }
|
|
||||||
// | {
|
|
||||||
// TAG: 1; // Date
|
|
||||||
// min: Date;
|
|
||||||
// max: Date;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// Umur: Squiggle expressions are opaque!
|
|
||||||
// export type squiggleExpression =
|
|
||||||
// | tagged<"symbol", string>
|
|
||||||
// | tagged<"string", string>
|
|
||||||
// | tagged<"call", string>
|
|
||||||
// | tagged<"lambda", lambdaValue>
|
|
||||||
// | tagged<"array", squiggleExpression[]>
|
|
||||||
// | tagged<"arraystring", string[]>
|
|
||||||
// | tagged<"boolean", boolean>
|
|
||||||
// | tagged<"distribution", Distribution>
|
|
||||||
// | tagged<"number", number>
|
|
||||||
// | tagged<"date", Date>
|
|
||||||
// | tagged<"timeDuration", number>
|
|
||||||
// | tagged<"lambdaDeclaration", lambdaDeclaration>
|
|
||||||
// | tagged<"record", { [key: string]: squiggleExpression }>
|
|
||||||
// | tagged<"type", { [key: string]: squiggleExpression }>
|
|
||||||
// | tagged<"typeIdentifier", string>
|
|
||||||
// | tagged<"module", { [key: string]: squiggleExpression }>
|
|
||||||
// | tagged<"void", string>;
|
|
||||||
|
|
||||||
// export { lambdaValue };
|
|
||||||
|
|
||||||
// Umur: Opaque type no conversion!
|
|
||||||
// export function convertRawToTypescript(
|
|
||||||
// result: rescriptExport,
|
|
||||||
// environment: environment
|
|
||||||
// ): squiggleExpression {
|
|
||||||
// if (typeof result === "number") {
|
|
||||||
// // EvVoid
|
|
||||||
// return tag("void", "");
|
|
||||||
// }
|
|
||||||
// switch (result.TAG) {
|
|
||||||
// case 0: // EvArray
|
|
||||||
// return tag(
|
|
||||||
// "array",
|
|
||||||
// result._0.map((x) => convertRawToTypescript(x, environment))
|
|
||||||
// );
|
|
||||||
// case 1: // EvArrayString
|
|
||||||
// return tag("arraystring", result._0);
|
|
||||||
// case 2: // EvBool
|
|
||||||
// return tag("boolean", result._0);
|
|
||||||
// case 3: // EvCall
|
|
||||||
// return tag("call", result._0);
|
|
||||||
// case 4: // EvDistribution
|
|
||||||
// return tag(
|
|
||||||
// "distribution",
|
|
||||||
// new Distribution(
|
|
||||||
// convertRawDistributionToGenericDist(result._0),
|
|
||||||
// environment
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
// case 5: // EvDistribution
|
|
||||||
// return tag("lambda", result._0);
|
|
||||||
// case 6: // EvNumber
|
|
||||||
// return tag("number", result._0);
|
|
||||||
// case 7: // EvRecord
|
|
||||||
// return tag(
|
|
||||||
// "record",
|
|
||||||
// _.mapValues(result._0, (x) => convertRawToTypescript(x, environment))
|
|
||||||
// );
|
|
||||||
// case 8: // EvString
|
|
||||||
// return tag("string", result._0);
|
|
||||||
// case 9: // EvSymbol
|
|
||||||
// return tag("symbol", result._0);
|
|
||||||
// case 10: // EvDate
|
|
||||||
// return tag("date", result._0);
|
|
||||||
// case 11: // EvTimeDuration
|
|
||||||
// return tag("number", result._0);
|
|
||||||
// case 12: // EvDeclaration
|
|
||||||
// return tag("lambdaDeclaration", {
|
|
||||||
// fn: result._0.fn,
|
|
||||||
// args: result._0.args.map(convertDeclaration),
|
|
||||||
// });
|
|
||||||
// case 13: // EvSymbol
|
|
||||||
// return tag("typeIdentifier", result._0);
|
|
||||||
// case 14: // EvModule
|
|
||||||
// return tag(
|
|
||||||
// "module",
|
|
||||||
// _.mapValues(result._0, (x) => convertRawToTypescript(x, environment))
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function convertDeclaration(
|
|
||||||
// declarationArg: rescriptDeclarationArg
|
|
||||||
// ): declarationArg {
|
|
||||||
// switch (declarationArg.TAG) {
|
|
||||||
// case 0: // Float
|
|
||||||
// return tag("Float", { min: declarationArg.min, max: declarationArg.max });
|
|
||||||
// case 1: // Date
|
|
||||||
// return tag("Date", { min: declarationArg.min, max: declarationArg.max });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Umur: opaque type no conversion!
|
|
||||||
// function convertRawDistributionToGenericDist(
|
|
||||||
// result: rescriptDist
|
|
||||||
// ): genericDist {
|
|
||||||
// switch (result.TAG) {
|
|
||||||
// case 0: // Point Set Dist
|
|
||||||
// switch (result._0.TAG) {
|
|
||||||
// case 0: // Mixed
|
|
||||||
// return tag("PointSet", tag("Mixed", result._0._0));
|
|
||||||
// case 1: // Discrete
|
|
||||||
// return tag("PointSet", tag("Discrete", result._0._0));
|
|
||||||
// case 2: // Continuous
|
|
||||||
// return tag("PointSet", tag("Continuous", result._0._0));
|
|
||||||
// }
|
|
||||||
// case 1: // Sample Set Dist
|
|
||||||
// return tag("SampleSet", result._0);
|
|
||||||
// case 2: // Symbolic Dist
|
|
||||||
// return tag("Symbolic", result._0);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export type jsValue =
|
|
||||||
// | string
|
|
||||||
// | number
|
|
||||||
// | jsValue[]
|
|
||||||
// | { [key: string]: jsValue }
|
|
||||||
// | boolean;
|
|
||||||
|
|
||||||
// export function jsValueToBinding(value: jsValue): rescriptExport {
|
|
||||||
// if (typeof value === "boolean") {
|
|
||||||
// return { TAG: 2, _0: value as boolean };
|
|
||||||
// } else if (typeof value === "string") {
|
|
||||||
// return { TAG: 8, _0: value as string };
|
|
||||||
// } else if (typeof value === "number") {
|
|
||||||
// return { TAG: 6, _0: value as number };
|
|
||||||
// } else if (Array.isArray(value)) {
|
|
||||||
// return { TAG: 0, _0: value.map(jsValueToBinding) };
|
|
||||||
// } else {
|
|
||||||
// // Record
|
|
||||||
// return { TAG: 7, _0: _.mapValues(value, jsValueToBinding) };
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export function jsValueToExpressionValue(value: jsValue): expressionValue {
|
|
||||||
// if (typeof value === "boolean") {
|
|
||||||
// return { tag: "EvBool", value: value as boolean };
|
|
||||||
// } else if (typeof value === "string") {
|
|
||||||
// return { tag: "EvString", value: value as string };
|
|
||||||
// } else if (typeof value === "number") {
|
|
||||||
// return { tag: "EvNumber", value: value as number };
|
|
||||||
// } else if (Array.isArray(value)) {
|
|
||||||
// return { tag: "EvArray", value: value.map(jsValueToExpressionValue) };
|
|
||||||
// } else {
|
|
||||||
// // Record
|
|
||||||
// return {
|
|
||||||
// tag: "EvRecord",
|
|
||||||
// value: _.mapValues(value, jsValueToExpressionValue),
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// }
|
|
|
@ -1,30 +1,29 @@
|
||||||
export type result<a, b> =
|
import { result } from "../rescript/ForTS/ForTS_Result_tag";
|
||||||
| {
|
export { result };
|
||||||
tag: "Ok";
|
|
||||||
value: a;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
tag: "Error";
|
|
||||||
value: b;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function resultMap<a, b, c>(
|
export function resultMap<a, b, c>(
|
||||||
r: result<a, c>,
|
r: result<a, b>,
|
||||||
mapFn: (x: a) => b
|
mapValue: (x: a) => c
|
||||||
): result<b, c> {
|
): result<c, b> {
|
||||||
if (r.tag === "Ok") {
|
if (r.tag === "Ok") {
|
||||||
return { tag: "Ok", value: mapFn(r.value) };
|
return { tag: "Ok", value: mapValue(r.value) };
|
||||||
} else {
|
} else {
|
||||||
return r;
|
return { tag: "Error", value: r.value };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resultMap2<a, b, c, d>(
|
||||||
|
r: result<a, b>,
|
||||||
|
mapValue: (x: a) => c,
|
||||||
|
mapError: (y: b) => d
|
||||||
|
): result<c, d> {
|
||||||
|
if (r.tag === "Ok") {
|
||||||
|
return { tag: "Ok", value: mapValue(r.value) };
|
||||||
|
} else {
|
||||||
|
return { tag: "Error", value: mapError(r.value) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Ok<a, b>(x: a): result<a, b> {
|
export function Ok<a, b>(x: a): result<a, b> {
|
||||||
return { tag: "Ok", value: x };
|
return { tag: "Ok", value: x };
|
||||||
}
|
}
|
||||||
|
|
||||||
export type tagged<a, b> = { tag: a; value: b };
|
|
||||||
|
|
||||||
export function tag<a, b>(x: a, y: b): tagged<a, b> {
|
|
||||||
return { tag: x, value: y };
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// Genetic Distribution happens to be abstract distribution
|
// Genetic Distribution happens to be abstract distribution
|
||||||
@genType type distribution = DistributionTypes.genericDist
|
@genType type distribution = DistributionTypes.genericDist
|
||||||
|
@genType type distributionError = DistributionTypes.error
|
||||||
@genType type pointSetDistribution = ForTS_Distribution_PointSetDistribution.pointSetDistribution
|
@genType type pointSetDistribution = ForTS_Distribution_PointSetDistribution.pointSetDistribution
|
||||||
@genType type sampleSetDistribution = ForTS_Distribution_SampleSetDistribution.sampleSetDistribution
|
@genType type sampleSetDistribution = ForTS_Distribution_SampleSetDistribution.sampleSetDistribution
|
||||||
@genType type symbolicDistribution = ForTS_Distribution_SymbolicDistribution.symbolicDistribution
|
@genType type symbolicDistribution = ForTS_Distribution_SymbolicDistribution.symbolicDistribution
|
||||||
|
@ -9,19 +10,19 @@ type environment = ForTS_Distribution_Environment.environment //use
|
||||||
@genType
|
@genType
|
||||||
let defaultEnvironment: environment = DistributionOperation.defaultEnv
|
let defaultEnvironment: environment = DistributionOperation.defaultEnv
|
||||||
|
|
||||||
@module("ForTS_Distribution_tag") @scope("distributionTag")
|
@module("./ForTS_Distribution_tag") @scope("distributionTag")
|
||||||
external dtPointSet_: int = "DtPointSet"
|
external dtPointSet_: string = "PointSet"
|
||||||
|
|
||||||
@module("ForTS_Distribution_tag") @scope("distributionTag")
|
@module("./ForTS_Distribution_tag") @scope("distributionTag")
|
||||||
external dtSampleSet_: int = "DtSampleSet"
|
external dtSampleSet_: string = "SampleSet"
|
||||||
|
|
||||||
@module("ForTS_Distribution_tag") @scope("distributionTag")
|
@module("./ForTS_Distribution_tag") @scope("distributionTag")
|
||||||
external dtSymbolic_: int = "DtSymbolic"
|
external dtSymbolic_: string = "Symbolic"
|
||||||
|
|
||||||
@genType.import("./ForTS_Distribution_tag")
|
@genType.import("./ForTS_Distribution_tag")
|
||||||
type distributionTag
|
type distributionTag
|
||||||
|
|
||||||
external castEnum: int => distributionTag = "%identity"
|
external castEnum: string => distributionTag = "%identity"
|
||||||
|
|
||||||
// type genericDist =
|
// type genericDist =
|
||||||
// | PointSet(PointSetTypes.pointSetDist)
|
// | PointSet(PointSetTypes.pointSetDist)
|
||||||
|
@ -73,3 +74,15 @@ let inv = DistributionOperation.Constructors.inv
|
||||||
let pdf = DistributionOperation.Constructors.pdf
|
let pdf = DistributionOperation.Constructors.pdf
|
||||||
@genType
|
@genType
|
||||||
let normalize = DistributionOperation.Constructors.normalize
|
let normalize = DistributionOperation.Constructors.normalize
|
||||||
|
|
||||||
|
@genType
|
||||||
|
let toPointSet = (variant: distribution, env: environment) =>
|
||||||
|
GenericDist.toPointSet(
|
||||||
|
variant,
|
||||||
|
~sampleCount=env.sampleCount,
|
||||||
|
~xyPointLength=env.xyPointLength,
|
||||||
|
(),
|
||||||
|
)
|
||||||
|
|
||||||
|
@genType
|
||||||
|
let toString = (variant: distribution) => GenericDist.toString(variant)
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
@genType type pointSetDistribution = PointSetTypes.pointSetDist
|
@genType type pointSetDistribution = PointSetTypes.pointSetDist
|
||||||
|
@genType type continuousShape = PointSetTypes.continuousShape
|
||||||
|
@genType type discreteShape = PointSetTypes.discreteShape
|
||||||
|
@genType type mixedShape = PointSetTypes.mixedShape
|
||||||
|
|
||||||
@module("ForTS_Distribution_PointSetDistribution_tag") @scope("pointSetDistributionTag")
|
@module("./ForTS_Distribution_PointSetDistribution_tag") @scope("pointSetDistributionTag")
|
||||||
external pstMixed_: int = "PstMixed"
|
external pstMixed_: string = "Mixed"
|
||||||
|
|
||||||
@module("ForTS_Distribution_PointSetDistribution_tag") @scope("pointSetDistributionTag")
|
@module("./ForTS_Distribution_PointSetDistribution_tag") @scope("pointSetDistributionTag")
|
||||||
external pstDiscrete_: int = "PstDiscrete"
|
external pstDiscrete_: string = "Discrete"
|
||||||
|
|
||||||
@module("ForTS_Distribution_PointSetDistribution_tag") @scope("pointSetDistributionTag")
|
@module("./ForTS_Distribution_PointSetDistribution_tag") @scope("pointSetDistributionTag")
|
||||||
external pstContinuous_: int = "PstContinuous"
|
external pstContinuous_: string = "Continuous"
|
||||||
|
|
||||||
@genType.import("./ForTS_Distribution_PointSetDistribution_tag")
|
@genType.import("./ForTS_Distribution_PointSetDistribution_tag")
|
||||||
type pointSetDistributionTag
|
type pointSetDistributionTag
|
||||||
|
|
||||||
external castEnum: int => pointSetDistributionTag = "%identity"
|
external castEnum: string => pointSetDistributionTag = "%identity"
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
let getTag = (variant: pointSetDistribution): pointSetDistributionTag =>
|
let getTag = (variant: pointSetDistribution): pointSetDistributionTag =>
|
||||||
|
@ -42,3 +45,6 @@ let getContinues = (variant: pointSetDistribution): 'd =>
|
||||||
| Continuous(continuous) => continuous->Some
|
| Continuous(continuous) => continuous->Some
|
||||||
| _ => None
|
| _ => None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@genType
|
||||||
|
let toDistribution = (v: pointSetDistribution): DistributionTypes.genericDist => PointSet(v)
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
"use strict";
|
|
||||||
exports.__esModule = true;
|
|
||||||
exports.pointSetDistributionTag = void 0;
|
|
||||||
var pointSetDistributionTag;
|
|
||||||
(function (pointSetDistributionTag) {
|
|
||||||
pointSetDistributionTag[(pointSetDistributionTag["PstMixed"] = 0)] =
|
|
||||||
"PstMixed";
|
|
||||||
pointSetDistributionTag[(pointSetDistributionTag["PstDiscrete"] = 1)] =
|
|
||||||
"PstDiscrete";
|
|
||||||
pointSetDistributionTag[(pointSetDistributionTag["PstContinuous"] = 2)] =
|
|
||||||
"PstContinuous";
|
|
||||||
})(
|
|
||||||
(pointSetDistributionTag =
|
|
||||||
exports.pointSetDistributionTag || (exports.pointSetDistributionTag = {}))
|
|
||||||
);
|
|
|
@ -1,5 +1,5 @@
|
||||||
export enum pointSetDistributionTag {
|
export enum pointSetDistributionTag {
|
||||||
PstMixed,
|
Mixed = "Mixed",
|
||||||
PstDiscrete,
|
Discrete = "Discrete",
|
||||||
PstContinuous,
|
Continuous = "Continuous",
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
export enum distributionTag {
|
export enum distributionTag {
|
||||||
DtPointSet,
|
PointSet = "PointSet",
|
||||||
DtSampleSet,
|
SampleSet = "SampleSet",
|
||||||
DtSymbolic,
|
Symbolic = "Symbolic",
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,3 +10,9 @@ let getLocation = (e: reducerErrorValue): option<syntaxErrorLocation> =>
|
||||||
| RESyntaxError(_, optionalLocation) => optionalLocation
|
| RESyntaxError(_, optionalLocation) => optionalLocation
|
||||||
| _ => None
|
| _ => None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@genType
|
||||||
|
let createTodoError = (v: string) => Reducer_ErrorValue.RETodo(v)
|
||||||
|
|
||||||
|
@genType
|
||||||
|
let createOtherError = (v: string) => Reducer_ErrorValue.REOther(v)
|
||||||
|
|
|
@ -12,55 +12,55 @@ type squiggleValue_Lambda = ForTS_SquiggleValue_Lambda.squiggleValue_Lambda //us
|
||||||
// Return values are kept as they are if they are JavaScript types.
|
// Return values are kept as they are if they are JavaScript types.
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtArray_: string = "SvtArray"
|
external svtArray_: string = "Array"
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtArrayString_: string = "SvtArrayString"
|
external svtArrayString_: string = "ArrayString"
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtBool_: string = "SvtBool"
|
external svtBool_: string = "Bool"
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtCall_: string = "SvtCall"
|
external svtCall_: string = "Call"
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtDate_: string = "SvtDate"
|
external svtDate_: string = "Date"
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtDeclaration_: string = "SvtDeclaration"
|
external svtDeclaration_: string = "Declaration"
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtDistribution_: string = "SvtDistribution"
|
external svtDistribution_: string = "Distribution"
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtLambda_: string = "SvtLambda"
|
external svtLambda_: string = "Lambda"
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtModule_: string = "SvtModule"
|
external svtModule_: string = "Module"
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtNumber_: string = "SvtNumber"
|
external svtNumber_: string = "Number"
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtRecord_: string = "SvtRecord"
|
external svtRecord_: string = "Record"
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtString_: string = "SvtString"
|
external svtString_: string = "String"
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtSymbol_: string = "SvtSymbol"
|
external svtSymbol_: string = "Symbol"
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtTimeDuration_: string = "SvtTimeDuration"
|
external svtTimeDuration_: string = "TimeDuration"
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtType_: string = "SvtType"
|
external svtType_: string = "Type"
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtTypeIdentifier_: string = "SvtUndefined"
|
external svtTypeIdentifier_: string = "TypeIdentifier"
|
||||||
|
|
||||||
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag")
|
||||||
external svtVoid_: string = "SvtVoid"
|
external svtVoid_: string = "Void"
|
||||||
|
|
||||||
@genType.import("./ForTS_SquiggleValue_tag")
|
@genType.import("./ForTS_SquiggleValue_tag")
|
||||||
type squiggleValueTag
|
type squiggleValueTag
|
||||||
|
|
|
@ -8,6 +8,3 @@ let toString = (v: squiggleValue_Lambda): string =>
|
||||||
let parameters = (v: squiggleValue_Lambda): array<string> => {
|
let parameters = (v: squiggleValue_Lambda): array<string> => {
|
||||||
v.parameters
|
v.parameters
|
||||||
}
|
}
|
||||||
|
|
||||||
@genType
|
|
||||||
let getParameters = parameters
|
|
||||||
|
|
|
@ -8,3 +8,9 @@ let getKeyValuePairs = (v: squiggleValue_Module): array<(string, squiggleValue)>
|
||||||
@genType
|
@genType
|
||||||
let toString = (v: squiggleValue_Module): string =>
|
let toString = (v: squiggleValue_Module): string =>
|
||||||
ReducerInterface_InternalExpressionValue.toStringNameSpace(v)
|
ReducerInterface_InternalExpressionValue.toStringNameSpace(v)
|
||||||
|
|
||||||
|
@genType
|
||||||
|
let toSquiggleValue = (v: squiggleValue_Module): squiggleValue => IEvBindings(v)
|
||||||
|
|
||||||
|
@genType
|
||||||
|
let get = ReducerInterface_InternalExpressionValue.nameSpaceGet
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
export enum squiggleValueTag {
|
export enum squiggleValueTag {
|
||||||
SvtArray = "Array",
|
Array = "Array",
|
||||||
SvtArrayString = "ArrayString",
|
ArrayString = "ArrayString",
|
||||||
SvtBool = "Bool",
|
Bool = "Bool",
|
||||||
SvtCall = "Call",
|
Call = "Call",
|
||||||
SvtDate = "Date",
|
Date = "Date",
|
||||||
SvtDeclaration = "Declaration",
|
Declaration = "Declaration",
|
||||||
SvtDistribution = "Distribution",
|
Distribution = "Distribution",
|
||||||
SvtLambda = "Lambda",
|
Lambda = "Lambda",
|
||||||
SvtModule = "Module",
|
Module = "Module",
|
||||||
SvtNumber = "Number",
|
Number = "Number",
|
||||||
SvtRecord = "Record",
|
Record = "Record",
|
||||||
SvtString = "String",
|
String = "String",
|
||||||
SvtSymbol = "Symbol",
|
Symbol = "Symbol",
|
||||||
SvtTimeDuration = "TimeDuration",
|
TimeDuration = "TimeDuration",
|
||||||
SvtType = "Type",
|
Type = "Type",
|
||||||
SvtTypeIdentifier = "TypeIdentifier",
|
TypeIdentifier = "TypeIdentifier",
|
||||||
SvtVoid = "Void",
|
Void = "Void",
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ type errorValue =
|
||||||
| RETodo(string) // To do
|
| RETodo(string) // To do
|
||||||
| REUnitNotFound(string)
|
| REUnitNotFound(string)
|
||||||
| RENeedToRun
|
| RENeedToRun
|
||||||
|
| REOther(string)
|
||||||
|
|
||||||
type t = errorValue
|
type t = errorValue
|
||||||
|
|
||||||
|
@ -59,4 +60,5 @@ let errorToString = err =>
|
||||||
| REExpectedType(typeName, valueString) => `Expected type: ${typeName} but got: ${valueString}`
|
| REExpectedType(typeName, valueString) => `Expected type: ${typeName} but got: ${valueString}`
|
||||||
| REUnitNotFound(unitName) => `Unit not found: ${unitName}`
|
| REUnitNotFound(unitName) => `Unit not found: ${unitName}`
|
||||||
| RENeedToRun => "Need to run"
|
| RENeedToRun => "Need to run"
|
||||||
|
| REOther(msg) => `Error: ${msg}`
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,3 +239,9 @@ let nameSpaceToKeyValuePairs = (nameSpace: nameSpace): array<(string, t)> => {
|
||||||
let NameSpace(container) = nameSpace
|
let NameSpace(container) = nameSpace
|
||||||
container->Belt.Map.String.toArray
|
container->Belt.Map.String.toArray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let nameSpaceGet = (nameSpace: nameSpace, key: string): option<t> => {
|
||||||
|
let NameSpace(container) = nameSpace
|
||||||
|
container->Belt.Map.String.get(key)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ module Bindings = Reducer_Bindings
|
||||||
|
|
||||||
let bindings: Bindings.t =
|
let bindings: Bindings.t =
|
||||||
[
|
[
|
||||||
("System.version", ReducerInterface_InternalExpressionValue.IEvString("0.3.0")),
|
("System.version", ReducerInterface_InternalExpressionValue.IEvString("0.4.0-dev")),
|
||||||
]->Bindings.fromArray
|
]->Bindings.fromArray
|
||||||
|
|
||||||
let makeBindings = (previousBindings: Bindings.t): Bindings.t =>
|
let makeBindings = (previousBindings: Bindings.t): Bindings.t =>
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
"declarationDir": "./dist",
|
"declarationDir": "./dist",
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"composite": true
|
"composite": true,
|
||||||
|
"target": "ES6"
|
||||||
},
|
},
|
||||||
"target": "ES6",
|
|
||||||
"include": ["src/**/*"],
|
"include": ["src/**/*"],
|
||||||
"exclude": ["node_modules", "**/*.spec.ts", "webpack.config.js"]
|
"exclude": ["node_modules", "**/*.spec.ts", "webpack.config.js"]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user