Merge pull request #437 from quantified-uncertainty/js-parameters
JS Parameter import
This commit is contained in:
commit
a2eec0b2e6
|
@ -1,19 +1,19 @@
|
||||||
{
|
{
|
||||||
"name": "@quri/squiggle-components",
|
"name": "@quri/squiggle-components",
|
||||||
"version": "0.2.14",
|
"version": "0.2.15",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-ace": "10.1.0",
|
|
||||||
"@quri/squiggle-lang": "^0.2.7",
|
"@quri/squiggle-lang": "^0.2.7",
|
||||||
"react-dom": "^18.1.0",
|
|
||||||
"vega": "^5.22.1",
|
|
||||||
"vega-embed": "^6.20.6",
|
|
||||||
"vega-lite": "^5.2.0",
|
|
||||||
"react-vega": "^7.5.0",
|
|
||||||
"react": "^18.1.0",
|
|
||||||
"@react-hook/size": "^2.1.2",
|
"@react-hook/size": "^2.1.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"styled-components": "^5.3.5"
|
"react": "^18.1.0",
|
||||||
|
"react-ace": "10.1.0",
|
||||||
|
"react-dom": "^18.1.0",
|
||||||
|
"react-vega": "^7.5.0",
|
||||||
|
"styled-components": "^5.3.5",
|
||||||
|
"vega": "^5.22.1",
|
||||||
|
"vega-embed": "^6.20.6",
|
||||||
|
"vega-lite": "^5.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/plugin-proposal-private-property-in-object": "^7.16.7",
|
"@babel/plugin-proposal-private-property-in-object": "^7.16.7",
|
||||||
|
@ -25,27 +25,26 @@
|
||||||
"@storybook/node-logger": "^6.4.22",
|
"@storybook/node-logger": "^6.4.22",
|
||||||
"@storybook/preset-create-react-app": "^4.1.0",
|
"@storybook/preset-create-react-app": "^4.1.0",
|
||||||
"@storybook/react": "^6.4.22",
|
"@storybook/react": "^6.4.22",
|
||||||
"@types/styled-components": "^5.1.24",
|
|
||||||
"@types/webpack": "^5.28.0",
|
|
||||||
"style-loader": "^3.3.1",
|
|
||||||
"ts-loader": "^9.2.9",
|
|
||||||
"webpack": "^5.72.0",
|
|
||||||
"webpack-cli": "^4.9.2",
|
|
||||||
"webpack-dev-server": "^4.8.1",
|
|
||||||
"@testing-library/jest-dom": "^5.16.4",
|
"@testing-library/jest-dom": "^5.16.4",
|
||||||
"@testing-library/react": "^13.1.1",
|
"@testing-library/react": "^13.1.1",
|
||||||
"@testing-library/user-event": "^14.1.1",
|
"@testing-library/user-event": "^14.1.1",
|
||||||
"@types/jest": "^27.4.0",
|
"@types/jest": "^27.4.0",
|
||||||
"web-vitals": "^2.1.4",
|
|
||||||
"@types/lodash": "^4.14.182",
|
"@types/lodash": "^4.14.182",
|
||||||
"@types/node": "^17.0.29",
|
"@types/node": "^17.0.29",
|
||||||
"@types/react": "^18.0.3",
|
"@types/react": "^18.0.3",
|
||||||
"@types/react-dom": "^18.0.2",
|
"@types/react-dom": "^18.0.2",
|
||||||
|
"@types/styled-components": "^5.1.24",
|
||||||
|
"@types/webpack": "^5.28.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
|
"style-loader": "^3.3.1",
|
||||||
|
"ts-loader": "^9.2.9",
|
||||||
"tsconfig-paths-webpack-plugin": "^3.5.2",
|
"tsconfig-paths-webpack-plugin": "^3.5.2",
|
||||||
"typescript": "^4.6.3",
|
"typescript": "^4.6.3",
|
||||||
"webpack-cli": "^4.9.2"
|
"web-vitals": "^2.1.4",
|
||||||
|
"webpack": "^5.72.0",
|
||||||
|
"webpack-cli": "^4.9.2",
|
||||||
|
"webpack-dev-server": "^4.8.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "cross-env REACT_APP_FAST_REFRESH=false && start-storybook -p 6006 -s public",
|
"start": "cross-env REACT_APP_FAST_REFRESH=false && start-storybook -p 6006 -s public",
|
||||||
|
|
|
@ -3,16 +3,17 @@ import _ from "lodash";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import {
|
import {
|
||||||
run,
|
run,
|
||||||
runPartial,
|
|
||||||
errorValueToString,
|
errorValueToString,
|
||||||
squiggleExpression,
|
squiggleExpression,
|
||||||
bindings,
|
bindings,
|
||||||
samplingParams,
|
samplingParams,
|
||||||
|
jsImports,
|
||||||
|
defaultImports,
|
||||||
|
defaultBindings,
|
||||||
} from "@quri/squiggle-lang";
|
} from "@quri/squiggle-lang";
|
||||||
import { NumberShower } from "./NumberShower";
|
import { NumberShower } from "./NumberShower";
|
||||||
import { DistributionChart } from "./DistributionChart";
|
import { DistributionChart } from "./DistributionChart";
|
||||||
import { ErrorBox } from "./ErrorBox";
|
import { ErrorBox } from "./ErrorBox";
|
||||||
import useSize from "@react-hook/size";
|
|
||||||
|
|
||||||
const variableBox = {
|
const variableBox = {
|
||||||
Component: styled.div`
|
Component: styled.div`
|
||||||
|
@ -152,6 +153,8 @@ export interface SquiggleChartProps {
|
||||||
height?: number;
|
height?: number;
|
||||||
/** Bindings of previous variables declared */
|
/** Bindings of previous variables declared */
|
||||||
bindings?: bindings;
|
bindings?: bindings;
|
||||||
|
/** JS imported parameters */
|
||||||
|
jsImports?: jsImports;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChartWrapper = styled.div`
|
const ChartWrapper = styled.div`
|
||||||
|
@ -166,14 +169,20 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
||||||
outputXYPoints = 1000,
|
outputXYPoints = 1000,
|
||||||
onChange = () => {},
|
onChange = () => {},
|
||||||
height = 60,
|
height = 60,
|
||||||
bindings = {},
|
bindings = defaultBindings,
|
||||||
|
jsImports = defaultImports,
|
||||||
width = NaN,
|
width = NaN,
|
||||||
}: SquiggleChartProps) => {
|
}: SquiggleChartProps) => {
|
||||||
let samplingInputs: samplingParams = {
|
let samplingInputs: samplingParams = {
|
||||||
sampleCount: sampleCount,
|
sampleCount: sampleCount,
|
||||||
xyPointLength: outputXYPoints,
|
xyPointLength: outputXYPoints,
|
||||||
};
|
};
|
||||||
let expressionResult = run(squiggleString, bindings, samplingInputs);
|
let expressionResult = run(
|
||||||
|
squiggleString,
|
||||||
|
bindings,
|
||||||
|
samplingInputs,
|
||||||
|
jsImports
|
||||||
|
);
|
||||||
let internal: JSX.Element;
|
let internal: JSX.Element;
|
||||||
if (expressionResult.tag === "Ok") {
|
if (expressionResult.tag === "Ok") {
|
||||||
let expression = expressionResult.value;
|
let expression = expressionResult.value;
|
||||||
|
|
|
@ -3,8 +3,18 @@ import * as ReactDOM from "react-dom";
|
||||||
import { SquiggleChart } from "./SquiggleChart";
|
import { SquiggleChart } from "./SquiggleChart";
|
||||||
import { CodeEditor } from "./CodeEditor";
|
import { CodeEditor } from "./CodeEditor";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import type { squiggleExpression, bindings } from "@quri/squiggle-lang";
|
import type {
|
||||||
import { runPartial, errorValueToString } from "@quri/squiggle-lang";
|
squiggleExpression,
|
||||||
|
samplingParams,
|
||||||
|
bindings,
|
||||||
|
jsImports,
|
||||||
|
} from "@quri/squiggle-lang";
|
||||||
|
import {
|
||||||
|
runPartial,
|
||||||
|
errorValueToString,
|
||||||
|
defaultImports,
|
||||||
|
defaultBindings,
|
||||||
|
} from "@quri/squiggle-lang";
|
||||||
import { ErrorBox } from "./ErrorBox";
|
import { ErrorBox } from "./ErrorBox";
|
||||||
|
|
||||||
export interface SquiggleEditorProps {
|
export interface SquiggleEditorProps {
|
||||||
|
@ -30,6 +40,8 @@ export interface SquiggleEditorProps {
|
||||||
width: number;
|
width: number;
|
||||||
/** Previous variable declarations */
|
/** Previous variable declarations */
|
||||||
bindings: bindings;
|
bindings: bindings;
|
||||||
|
/** JS Imports */
|
||||||
|
jsImports: jsImports;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Input = styled.div`
|
const Input = styled.div`
|
||||||
|
@ -50,7 +62,8 @@ export let SquiggleEditor: React.FC<SquiggleEditorProps> = ({
|
||||||
diagramCount,
|
diagramCount,
|
||||||
onChange,
|
onChange,
|
||||||
environment,
|
environment,
|
||||||
bindings = {},
|
bindings = defaultBindings,
|
||||||
|
jsImports = defaultImports,
|
||||||
}: SquiggleEditorProps) => {
|
}: SquiggleEditorProps) => {
|
||||||
let [expression, setExpression] = React.useState(initialSquiggleString);
|
let [expression, setExpression] = React.useState(initialSquiggleString);
|
||||||
return (
|
return (
|
||||||
|
@ -77,6 +90,7 @@ export let SquiggleEditor: React.FC<SquiggleEditorProps> = ({
|
||||||
environment={environment}
|
environment={environment}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
bindings={bindings}
|
bindings={bindings}
|
||||||
|
jsImports={jsImports}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -134,16 +148,30 @@ export interface SquigglePartialProps {
|
||||||
/** The width of the element */
|
/** The width of the element */
|
||||||
width: number;
|
width: number;
|
||||||
/** Previously declared variables */
|
/** Previously declared variables */
|
||||||
bindings: bindings;
|
bindings?: bindings;
|
||||||
|
/** Variables imported from js */
|
||||||
|
jsImports?: jsImports;
|
||||||
}
|
}
|
||||||
|
|
||||||
export let SquigglePartial: React.FC<SquigglePartialProps> = ({
|
export let SquigglePartial: React.FC<SquigglePartialProps> = ({
|
||||||
initialSquiggleString = "",
|
initialSquiggleString = "",
|
||||||
onChange,
|
onChange,
|
||||||
bindings,
|
bindings = defaultBindings,
|
||||||
|
sampleCount = 1000,
|
||||||
|
outputXYPoints = 1000,
|
||||||
|
jsImports = defaultImports,
|
||||||
}: SquigglePartialProps) => {
|
}: SquigglePartialProps) => {
|
||||||
|
let samplingInputs: samplingParams = {
|
||||||
|
sampleCount: sampleCount,
|
||||||
|
xyPointLength: outputXYPoints,
|
||||||
|
};
|
||||||
let [expression, setExpression] = React.useState(initialSquiggleString);
|
let [expression, setExpression] = React.useState(initialSquiggleString);
|
||||||
let squiggleResult = runPartial(expression, bindings);
|
let squiggleResult = runPartial(
|
||||||
|
expression,
|
||||||
|
bindings,
|
||||||
|
samplingInputs,
|
||||||
|
jsImports
|
||||||
|
);
|
||||||
if (squiggleResult.tag == "Ok") {
|
if (squiggleResult.tag == "Ok") {
|
||||||
if (onChange) onChange(squiggleResult.value);
|
if (onChange) onChange(squiggleResult.value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Distribution, resultMap } from "../../src/js/index";
|
import { Distribution, resultMap, defaultBindings } from "../../src/js/index";
|
||||||
import { testRun, testRunPartial } from "./TestHelpers";
|
import { testRun, testRunPartial } from "./TestHelpers";
|
||||||
|
|
||||||
function Ok<b>(x: b) {
|
function Ok<b>(x: b) {
|
||||||
|
@ -68,6 +68,28 @@ describe("Partials", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("Distribution", () => {
|
describe("Distribution", () => {
|
||||||
//It's important that sampleCount is less than 9. If it's more, than that will create randomness
|
//It's important that sampleCount is less than 9. If it's more, than that will create randomness
|
||||||
//Also, note, the value should be created using makeSampleSetDist() later on.
|
//Also, note, the value should be created using makeSampleSetDist() later on.
|
||||||
|
|
|
@ -4,14 +4,25 @@ import {
|
||||||
bindings,
|
bindings,
|
||||||
squiggleExpression,
|
squiggleExpression,
|
||||||
errorValueToString,
|
errorValueToString,
|
||||||
|
defaultImports,
|
||||||
|
defaultBindings,
|
||||||
|
jsImports,
|
||||||
} from "../../src/js/index";
|
} from "../../src/js/index";
|
||||||
|
|
||||||
export function testRun(x: string, bindings = {}): squiggleExpression {
|
export function testRun(
|
||||||
let squiggleResult = run(x, bindings, {
|
x: string,
|
||||||
sampleCount: 1000,
|
bindings: bindings = defaultBindings,
|
||||||
xyPointLength: 100,
|
imports: jsImports = defaultImports
|
||||||
});
|
): squiggleExpression {
|
||||||
// return squiggleResult.value
|
let squiggleResult = run(
|
||||||
|
x,
|
||||||
|
bindings,
|
||||||
|
{
|
||||||
|
sampleCount: 1000,
|
||||||
|
xyPointLength: 100,
|
||||||
|
},
|
||||||
|
imports
|
||||||
|
);
|
||||||
if (squiggleResult.tag === "Ok") {
|
if (squiggleResult.tag === "Ok") {
|
||||||
return squiggleResult.value;
|
return squiggleResult.value;
|
||||||
} else {
|
} else {
|
||||||
|
@ -23,11 +34,20 @@ export function testRun(x: string, bindings = {}): squiggleExpression {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function testRunPartial(x: string, bindings: bindings = {}): bindings {
|
export function testRunPartial(
|
||||||
let squiggleResult = runPartial(x, bindings, {
|
x: string,
|
||||||
sampleCount: 1000,
|
bindings: bindings = defaultBindings,
|
||||||
xyPointLength: 100,
|
imports: jsImports = defaultImports
|
||||||
});
|
): bindings {
|
||||||
|
let squiggleResult = runPartial(
|
||||||
|
x,
|
||||||
|
bindings,
|
||||||
|
{
|
||||||
|
sampleCount: 1000,
|
||||||
|
xyPointLength: 100,
|
||||||
|
},
|
||||||
|
imports
|
||||||
|
);
|
||||||
if (squiggleResult.tag === "Ok") {
|
if (squiggleResult.tag === "Ok") {
|
||||||
return squiggleResult.value;
|
return squiggleResult.value;
|
||||||
} else {
|
} else {
|
||||||
|
|
247
packages/squiggle-lang/src/js/distribution.ts
Normal file
247
packages/squiggle-lang/src/js/distribution.ts
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
import * as _ from "lodash";
|
||||||
|
import {
|
||||||
|
genericDist,
|
||||||
|
continuousShape,
|
||||||
|
discreteShape,
|
||||||
|
samplingParams,
|
||||||
|
distributionError,
|
||||||
|
toPointSet,
|
||||||
|
distributionErrorToString,
|
||||||
|
} from "../rescript/TypescriptInterface.gen";
|
||||||
|
import { result, resultMap, Ok } from "./types";
|
||||||
|
import {
|
||||||
|
Constructors_mean,
|
||||||
|
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/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: samplingParams;
|
||||||
|
|
||||||
|
constructor(t: genericDist, env: samplingParams) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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,125 +1,91 @@
|
||||||
import * as _ from "lodash";
|
import * as _ from "lodash";
|
||||||
import {
|
import {
|
||||||
genericDist,
|
|
||||||
samplingParams,
|
samplingParams,
|
||||||
evaluateUsingExternalBindings,
|
evaluateUsingExternalBindings,
|
||||||
evaluatePartialUsingExternalBindings,
|
evaluatePartialUsingExternalBindings,
|
||||||
externalBindings,
|
externalBindings,
|
||||||
expressionValue,
|
expressionValue,
|
||||||
errorValue,
|
errorValue,
|
||||||
distributionError,
|
|
||||||
toPointSet,
|
|
||||||
continuousShape,
|
|
||||||
discreteShape,
|
|
||||||
distributionErrorToString,
|
|
||||||
mixedShape,
|
|
||||||
sampleSetDist,
|
|
||||||
symbolicDist,
|
|
||||||
} from "../rescript/TypescriptInterface.gen";
|
} from "../rescript/TypescriptInterface.gen";
|
||||||
export {
|
export {
|
||||||
makeSampleSetDist,
|
makeSampleSetDist,
|
||||||
errorValueToString,
|
errorValueToString,
|
||||||
distributionErrorToString,
|
distributionErrorToString,
|
||||||
} from "../rescript/TypescriptInterface.gen";
|
} from "../rescript/TypescriptInterface.gen";
|
||||||
|
export type {
|
||||||
|
samplingParams,
|
||||||
|
errorValue,
|
||||||
|
externalBindings as bindings,
|
||||||
|
jsImports,
|
||||||
|
};
|
||||||
import {
|
import {
|
||||||
Constructors_mean,
|
jsValueToBinding,
|
||||||
Constructors_sample,
|
jsValue,
|
||||||
Constructors_pdf,
|
rescriptExport,
|
||||||
Constructors_cdf,
|
squiggleExpression,
|
||||||
Constructors_inv,
|
convertRawToTypescript,
|
||||||
Constructors_normalize,
|
} from "./rescript_interop";
|
||||||
Constructors_isNormalized,
|
import { result, resultMap, tag, tagged } from "./types";
|
||||||
Constructors_toPointSet,
|
import { Distribution } from "./distribution";
|
||||||
Constructors_toSampleSet,
|
|
||||||
Constructors_truncate,
|
export { Distribution, squiggleExpression, result, resultMap };
|
||||||
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/DistributionOperation.gen";
|
|
||||||
export type { samplingParams, errorValue, externalBindings as bindings };
|
|
||||||
|
|
||||||
export let defaultSamplingInputs: samplingParams = {
|
export let defaultSamplingInputs: samplingParams = {
|
||||||
sampleCount: 10000,
|
sampleCount: 10000,
|
||||||
xyPointLength: 10000,
|
xyPointLength: 10000,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type result<a, b> =
|
|
||||||
| {
|
|
||||||
tag: "Ok";
|
|
||||||
value: a;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
tag: "Error";
|
|
||||||
value: b;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function resultMap<a, b, c>(
|
|
||||||
r: result<a, c>,
|
|
||||||
mapFn: (x: a) => b
|
|
||||||
): result<b, c> {
|
|
||||||
if (r.tag === "Ok") {
|
|
||||||
return { tag: "Ok", value: mapFn(r.value) };
|
|
||||||
} else {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Ok<a, b>(x: a): result<a, b> {
|
|
||||||
return { tag: "Ok", value: x };
|
|
||||||
}
|
|
||||||
|
|
||||||
type tagged<a, b> = { tag: a; value: b };
|
|
||||||
|
|
||||||
function tag<a, b>(x: a, y: b): tagged<a, b> {
|
|
||||||
return { tag: x, value: y };
|
|
||||||
}
|
|
||||||
|
|
||||||
export type squiggleExpression =
|
|
||||||
| tagged<"symbol", string>
|
|
||||||
| tagged<"string", string>
|
|
||||||
| tagged<"call", string>
|
|
||||||
| tagged<"array", squiggleExpression[]>
|
|
||||||
| tagged<"boolean", boolean>
|
|
||||||
| tagged<"distribution", Distribution>
|
|
||||||
| tagged<"number", number>
|
|
||||||
| tagged<"record", { [key: string]: squiggleExpression }>;
|
|
||||||
|
|
||||||
export function run(
|
export function run(
|
||||||
squiggleString: string,
|
squiggleString: string,
|
||||||
bindings?: externalBindings,
|
bindings?: externalBindings,
|
||||||
samplingInputs?: samplingParams
|
samplingInputs?: samplingParams,
|
||||||
|
imports?: jsImports
|
||||||
): result<squiggleExpression, errorValue> {
|
): result<squiggleExpression, errorValue> {
|
||||||
let b = bindings ? bindings : {};
|
let b = bindings ? bindings : defaultBindings;
|
||||||
|
let i = imports ? imports : defaultImports;
|
||||||
let si: samplingParams = samplingInputs
|
let si: samplingParams = samplingInputs
|
||||||
? samplingInputs
|
? samplingInputs
|
||||||
: defaultSamplingInputs;
|
: defaultSamplingInputs;
|
||||||
|
|
||||||
let result: result<expressionValue, errorValue> =
|
let result: result<expressionValue, errorValue> =
|
||||||
evaluateUsingExternalBindings(squiggleString, b);
|
evaluateUsingExternalBindings(squiggleString, mergeImports(b, i));
|
||||||
return resultMap(result, (x) => createTsExport(x, si));
|
return resultMap(result, (x) => createTsExport(x, si));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run Partial. A partial is a block of code that doesn't return a value
|
// Run Partial. A partial is a block of code that doesn't return a value
|
||||||
export function runPartial(
|
export function runPartial(
|
||||||
squiggleString: string,
|
squiggleString: string,
|
||||||
bindings: externalBindings,
|
bindings?: externalBindings,
|
||||||
_samplingInputs?: samplingParams
|
_samplingInputs?: samplingParams,
|
||||||
|
imports?: jsImports
|
||||||
): result<externalBindings, errorValue> {
|
): result<externalBindings, errorValue> {
|
||||||
return evaluatePartialUsingExternalBindings(squiggleString, bindings);
|
let b = bindings ? bindings : defaultBindings;
|
||||||
|
let i = imports ? imports : defaultImports;
|
||||||
|
|
||||||
|
return evaluatePartialUsingExternalBindings(
|
||||||
|
squiggleString,
|
||||||
|
mergeImports(b, i)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mergeImports(
|
||||||
|
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 = {};
|
||||||
|
|
||||||
function createTsExport(
|
function createTsExport(
|
||||||
x: expressionValue,
|
x: expressionValue,
|
||||||
sampEnv: samplingParams
|
sampEnv: samplingParams
|
||||||
|
@ -180,329 +146,3 @@ function createTsExport(
|
||||||
return tag("symbol", x.value);
|
return tag("symbol", x.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper functions to convert the rescript representations that genType doesn't
|
|
||||||
// cover
|
|
||||||
function convertRawToTypescript(
|
|
||||||
result: rescriptExport,
|
|
||||||
sampEnv: samplingParams
|
|
||||||
): squiggleExpression {
|
|
||||||
switch (result.TAG) {
|
|
||||||
case 0: // EvArray
|
|
||||||
return tag(
|
|
||||||
"array",
|
|
||||||
result._0.map((x) => convertRawToTypescript(x, sampEnv))
|
|
||||||
);
|
|
||||||
case 1: // EvBool
|
|
||||||
return tag("boolean", result._0);
|
|
||||||
case 2: // EvCall
|
|
||||||
return tag("call", result._0);
|
|
||||||
case 3: // EvDistribution
|
|
||||||
return tag(
|
|
||||||
"distribution",
|
|
||||||
new Distribution(
|
|
||||||
convertRawDistributionToGenericDist(result._0),
|
|
||||||
sampEnv
|
|
||||||
)
|
|
||||||
);
|
|
||||||
case 4: // EvNumber
|
|
||||||
return tag("number", result._0);
|
|
||||||
case 5: // EvRecord
|
|
||||||
return tag(
|
|
||||||
"record",
|
|
||||||
_.mapValues(result._0, (x) => convertRawToTypescript(x, sampEnv))
|
|
||||||
);
|
|
||||||
case 6: // EvString
|
|
||||||
return tag("string", result._0);
|
|
||||||
case 7: // EvSymbol
|
|
||||||
return tag("symbol", result._0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Raw rescript types.
|
|
||||||
type rescriptExport =
|
|
||||||
| {
|
|
||||||
TAG: 0; // EvArray
|
|
||||||
_0: rescriptExport[];
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
TAG: 1; // EvBool
|
|
||||||
_0: boolean;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
TAG: 2; // EvCall
|
|
||||||
_0: string;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
TAG: 3; // EvDistribution
|
|
||||||
_0: rescriptDist;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
TAG: 4; // EvNumber
|
|
||||||
_0: number;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
TAG: 5; // EvRecord
|
|
||||||
_0: { [key: string]: rescriptExport };
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
TAG: 6; // EvString
|
|
||||||
_0: string;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
TAG: 7; // EvSymbol
|
|
||||||
_0: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type rescriptDist =
|
|
||||||
| { TAG: 0; _0: rescriptPointSetDist }
|
|
||||||
| { TAG: 1; _0: sampleSetDist }
|
|
||||||
| { TAG: 2; _0: symbolicDist };
|
|
||||||
|
|
||||||
type rescriptPointSetDist =
|
|
||||||
| {
|
|
||||||
TAG: 0; // Mixed
|
|
||||||
_0: mixedShape;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
TAG: 1; // Discrete
|
|
||||||
_0: discreteShape;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
TAG: 2; // ContinuousShape
|
|
||||||
_0: continuousShape;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function resultExn<a, c>(r: result<a, c>): a | c {
|
|
||||||
return r.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type point = { x: number; y: number };
|
|
||||||
|
|
||||||
export type shape = {
|
|
||||||
continuous: point[];
|
|
||||||
discrete: point[];
|
|
||||||
};
|
|
||||||
|
|
||||||
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 class Distribution {
|
|
||||||
t: genericDist;
|
|
||||||
env: samplingParams;
|
|
||||||
|
|
||||||
constructor(t: genericDist, env: samplingParams) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
155
packages/squiggle-lang/src/js/rescript_interop.ts
Normal file
155
packages/squiggle-lang/src/js/rescript_interop.ts
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
import * as _ from "lodash";
|
||||||
|
import {
|
||||||
|
mixedShape,
|
||||||
|
sampleSetDist,
|
||||||
|
genericDist,
|
||||||
|
samplingParams,
|
||||||
|
symbolicDist,
|
||||||
|
discreteShape,
|
||||||
|
continuousShape,
|
||||||
|
} 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.
|
||||||
|
export type rescriptExport =
|
||||||
|
| {
|
||||||
|
TAG: 0; // EvArray
|
||||||
|
_0: rescriptExport[];
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
TAG: 1; // EvBool
|
||||||
|
_0: boolean;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
TAG: 2; // EvCall
|
||||||
|
_0: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
TAG: 3; // EvDistribution
|
||||||
|
_0: rescriptDist;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
TAG: 4; // EvNumber
|
||||||
|
_0: number;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
TAG: 5; // EvRecord
|
||||||
|
_0: { [key: string]: rescriptExport };
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
TAG: 6; // EvString
|
||||||
|
_0: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
TAG: 7; // EvSymbol
|
||||||
|
_0: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type rescriptDist =
|
||||||
|
| { TAG: 0; _0: rescriptPointSetDist }
|
||||||
|
| { TAG: 1; _0: sampleSetDist }
|
||||||
|
| { TAG: 2; _0: symbolicDist };
|
||||||
|
|
||||||
|
type rescriptPointSetDist =
|
||||||
|
| {
|
||||||
|
TAG: 0; // Mixed
|
||||||
|
_0: mixedShape;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
TAG: 1; // Discrete
|
||||||
|
_0: discreteShape;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
TAG: 2; // ContinuousShape
|
||||||
|
_0: continuousShape;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type squiggleExpression =
|
||||||
|
| tagged<"symbol", string>
|
||||||
|
| tagged<"string", string>
|
||||||
|
| tagged<"call", string>
|
||||||
|
| tagged<"array", squiggleExpression[]>
|
||||||
|
| tagged<"boolean", boolean>
|
||||||
|
| tagged<"distribution", Distribution>
|
||||||
|
| tagged<"number", number>
|
||||||
|
| tagged<"record", { [key: string]: squiggleExpression }>;
|
||||||
|
|
||||||
|
export function convertRawToTypescript(
|
||||||
|
result: rescriptExport,
|
||||||
|
sampEnv: samplingParams
|
||||||
|
): squiggleExpression {
|
||||||
|
switch (result.TAG) {
|
||||||
|
case 0: // EvArray
|
||||||
|
return tag(
|
||||||
|
"array",
|
||||||
|
result._0.map((x) => convertRawToTypescript(x, sampEnv))
|
||||||
|
);
|
||||||
|
case 1: // EvBool
|
||||||
|
return tag("boolean", result._0);
|
||||||
|
case 2: // EvCall
|
||||||
|
return tag("call", result._0);
|
||||||
|
case 3: // EvDistribution
|
||||||
|
return tag(
|
||||||
|
"distribution",
|
||||||
|
new Distribution(
|
||||||
|
convertRawDistributionToGenericDist(result._0),
|
||||||
|
sampEnv
|
||||||
|
)
|
||||||
|
);
|
||||||
|
case 4: // EvNumber
|
||||||
|
return tag("number", result._0);
|
||||||
|
case 5: // EvRecord
|
||||||
|
return tag(
|
||||||
|
"record",
|
||||||
|
_.mapValues(result._0, (x) => convertRawToTypescript(x, sampEnv))
|
||||||
|
);
|
||||||
|
case 6: // EvString
|
||||||
|
return tag("string", result._0);
|
||||||
|
case 7: // EvSymbol
|
||||||
|
return tag("symbol", result._0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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: 1, _0: value as boolean };
|
||||||
|
} else if (typeof value === "string") {
|
||||||
|
return { TAG: 6, _0: value as string };
|
||||||
|
} else if (typeof value === "number") {
|
||||||
|
return { TAG: 4, _0: value as number };
|
||||||
|
} else if (Array.isArray(value)) {
|
||||||
|
return { TAG: 0, _0: value.map(jsValueToBinding) };
|
||||||
|
} else {
|
||||||
|
// Record
|
||||||
|
return { TAG: 5, _0: _.mapValues(value, jsValueToBinding) };
|
||||||
|
}
|
||||||
|
}
|
30
packages/squiggle-lang/src/js/types.ts
Normal file
30
packages/squiggle-lang/src/js/types.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
export type result<a, b> =
|
||||||
|
| {
|
||||||
|
tag: "Ok";
|
||||||
|
value: a;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
tag: "Error";
|
||||||
|
value: b;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function resultMap<a, b, c>(
|
||||||
|
r: result<a, c>,
|
||||||
|
mapFn: (x: a) => b
|
||||||
|
): result<b, c> {
|
||||||
|
if (r.tag === "Ok") {
|
||||||
|
return { tag: "Ok", value: mapFn(r.value) };
|
||||||
|
} else {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Ok<a, b>(x: a): result<a, b> {
|
||||||
|
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 };
|
||||||
|
}
|
|
@ -350,7 +350,7 @@ module JsDate = {
|
||||||
/* List */
|
/* List */
|
||||||
module L = {
|
module L = {
|
||||||
module Util = {
|
module Util = {
|
||||||
let eq = (a, b) => a == b
|
let eq = \"=="
|
||||||
}
|
}
|
||||||
let fmap = List.map
|
let fmap = List.map
|
||||||
let get = Belt.List.get
|
let get = Belt.List.get
|
||||||
|
|
Loading…
Reference in New Issue
Block a user