Add bindings to Squiggle Editor
This commit is contained in:
parent
5f78399760
commit
454ac0c252
|
@ -89,6 +89,7 @@
|
|||
"@types/react": "17.0.43"
|
||||
},
|
||||
"source": "./src/index.ts",
|
||||
"browser": "dist/bundle.js",
|
||||
"main": "dist/src/index.js",
|
||||
"types": "dist/src/index.d.ts"
|
||||
}
|
||||
|
|
|
@ -3,10 +3,12 @@ import _ from "lodash";
|
|||
import styled from "styled-components";
|
||||
import {
|
||||
run,
|
||||
runPartial,
|
||||
errorValueToString,
|
||||
squiggleExpression,
|
||||
bindings,
|
||||
samplingParams,
|
||||
} from "@quri/squiggle-lang";
|
||||
import type { samplingParams } from "@quri/squiggle-lang";
|
||||
import { NumberShower } from "./NumberShower";
|
||||
import { DistributionChart } from "./DistributionChart";
|
||||
import { ErrorBox } from "./ErrorBox";
|
||||
|
@ -148,6 +150,8 @@ export interface SquiggleChartProps {
|
|||
/** CSS width of the element */
|
||||
width?: number;
|
||||
height?: number;
|
||||
/** Bindings of previous variables declared */
|
||||
bindings?: bindings;
|
||||
}
|
||||
|
||||
export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
||||
|
@ -156,6 +160,7 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
|||
outputXYPoints = 1000,
|
||||
onChange = () => {},
|
||||
height = 60,
|
||||
bindings = {},
|
||||
width = NaN,
|
||||
}: SquiggleChartProps) => {
|
||||
const target = React.useRef(null);
|
||||
|
@ -167,7 +172,7 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
|||
sampleCount: sampleCount,
|
||||
xyPointLength: outputXYPoints,
|
||||
};
|
||||
let expressionResult = run(squiggleString, samplingInputs);
|
||||
let expressionResult = run(squiggleString, bindings, samplingInputs);
|
||||
let internal: JSX.Element;
|
||||
if (expressionResult.tag === "Ok") {
|
||||
let expression = expressionResult.value;
|
||||
|
|
|
@ -3,7 +3,9 @@ import * as ReactDOM from "react-dom";
|
|||
import { SquiggleChart } from "./SquiggleChart";
|
||||
import { CodeEditor } from "./CodeEditor";
|
||||
import styled from "styled-components";
|
||||
import type { squiggleExpression } from "@quri/squiggle-lang";
|
||||
import type { squiggleExpression, bindings } from "@quri/squiggle-lang";
|
||||
import { runPartial, errorValueToString } from "@quri/squiggle-lang";
|
||||
import { ErrorBox } from "./ErrorBox";
|
||||
|
||||
export interface SquiggleEditorProps {
|
||||
/** The input string for squiggle */
|
||||
|
@ -26,6 +28,8 @@ export interface SquiggleEditorProps {
|
|||
onChange?(expr: squiggleExpression): void;
|
||||
/** The width of the element */
|
||||
width: number;
|
||||
/** Previous variable declarations */
|
||||
bindings: bindings;
|
||||
}
|
||||
|
||||
const Input = styled.div`
|
||||
|
@ -46,6 +50,7 @@ export let SquiggleEditor: React.FC<SquiggleEditorProps> = ({
|
|||
diagramCount,
|
||||
onChange,
|
||||
environment,
|
||||
bindings = {},
|
||||
}: SquiggleEditorProps) => {
|
||||
let [expression, setExpression] = React.useState(initialSquiggleString);
|
||||
return (
|
||||
|
@ -71,6 +76,7 @@ export let SquiggleEditor: React.FC<SquiggleEditorProps> = ({
|
|||
diagramCount={diagramCount}
|
||||
environment={environment}
|
||||
onChange={onChange}
|
||||
bindings={bindings}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -107,3 +113,76 @@ export function renderSquiggleEditorToDom(props: SquiggleEditorProps) {
|
|||
);
|
||||
return parent;
|
||||
}
|
||||
|
||||
export interface SquigglePartialProps {
|
||||
/** The input string for squiggle */
|
||||
initialSquiggleString?: string;
|
||||
/** If the output requires monte carlo sampling, the amount of samples */
|
||||
sampleCount?: number;
|
||||
/** The amount of points returned to draw the distribution */
|
||||
outputXYPoints?: number;
|
||||
kernelWidth?: number;
|
||||
pointDistLength?: number;
|
||||
/** If the result is a function, where the function starts */
|
||||
diagramStart?: number;
|
||||
/** If the result is a function, where the function ends */
|
||||
diagramStop?: number;
|
||||
/** If the result is a function, how many points along the function it samples */
|
||||
diagramCount?: number;
|
||||
/** when the environment changes. Used again for notebook magic*/
|
||||
onChange?(expr: bindings): void;
|
||||
/** The width of the element */
|
||||
width: number;
|
||||
/** Previously declared variables */
|
||||
bindings: bindings;
|
||||
}
|
||||
|
||||
export let SquigglePartial: React.FC<SquigglePartialProps> = ({
|
||||
initialSquiggleString = "",
|
||||
onChange,
|
||||
bindings,
|
||||
}: SquigglePartialProps) => {
|
||||
let [expression, setExpression] = React.useState(initialSquiggleString);
|
||||
let squiggleResult = runPartial(expression, bindings);
|
||||
if (squiggleResult.tag == "Ok") {
|
||||
if (onChange) onChange(squiggleResult.value);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<Input>
|
||||
<CodeEditor
|
||||
value={expression}
|
||||
onChange={setExpression}
|
||||
oneLine={true}
|
||||
showGutter={false}
|
||||
height={20}
|
||||
/>
|
||||
</Input>
|
||||
{squiggleResult.tag == "Error" ? (
|
||||
<ErrorBox heading="Error">
|
||||
{errorValueToString(squiggleResult.value)}
|
||||
</ErrorBox>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export function renderSquigglePartialToDom(props: SquigglePartialProps) {
|
||||
let parent = document.createElement("div");
|
||||
ReactDOM.render(
|
||||
<SquigglePartial
|
||||
{...props}
|
||||
onChange={(bindings) => {
|
||||
// @ts-ignore
|
||||
parent.value = bindings;
|
||||
|
||||
parent.dispatchEvent(new CustomEvent("input"));
|
||||
if (props.onChange) props.onChange(bindings);
|
||||
}}
|
||||
/>,
|
||||
parent
|
||||
);
|
||||
return parent;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
export { SquiggleChart } from "./components/SquiggleChart";
|
||||
export {
|
||||
SquiggleEditor,
|
||||
SquigglePartial,
|
||||
renderSquiggleEditorToDom,
|
||||
renderSquigglePartialToDom,
|
||||
} from "./components/SquiggleEditor";
|
||||
import SquigglePlayground, {
|
||||
renderSquigglePlaygroundToDom,
|
||||
|
|
|
@ -1,23 +1,5 @@
|
|||
import {
|
||||
run,
|
||||
Distribution,
|
||||
resultMap,
|
||||
squiggleExpression,
|
||||
errorValueToString,
|
||||
} from "../../src/js/index";
|
||||
|
||||
let testRun = (x: string): squiggleExpression => {
|
||||
let result = run(x, { sampleCount: 100, xyPointLength: 100 });
|
||||
expect(result.tag).toEqual("Ok");
|
||||
if (result.tag === "Ok") {
|
||||
return result.value;
|
||||
} else {
|
||||
throw Error(
|
||||
"Expected squiggle expression to evaluate but got error: " +
|
||||
errorValueToString(result.value)
|
||||
);
|
||||
}
|
||||
};
|
||||
import { Distribution, resultMap } from "../../src/js/index";
|
||||
import { testRun } from "./TestHelpers";
|
||||
|
||||
function Ok<b>(x: b) {
|
||||
return { tag: "Ok", value: x };
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
} from "../../src/js/index";
|
||||
|
||||
export function testRun(x: string): squiggleExpression {
|
||||
let squiggleResult = run(x, { sampleCount: 1000, xyPointLength: 100 });
|
||||
let squiggleResult = run(x, {}, { sampleCount: 1000, xyPointLength: 100 });
|
||||
// return squiggleResult.value
|
||||
if (squiggleResult.tag === "Ok") {
|
||||
return squiggleResult.value;
|
||||
|
|
|
@ -2,7 +2,9 @@ import * as _ from "lodash";
|
|||
import {
|
||||
genericDist,
|
||||
samplingParams,
|
||||
evaluate,
|
||||
evaluateUsingExternalBindings,
|
||||
evaluatePartialUsingExternalBindings,
|
||||
externalBindings,
|
||||
expressionValue,
|
||||
errorValue,
|
||||
distributionError,
|
||||
|
@ -46,7 +48,7 @@ import {
|
|||
Constructors_pointwiseLogarithm,
|
||||
Constructors_pointwisePower,
|
||||
} from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen";
|
||||
export type { samplingParams, errorValue };
|
||||
export type { samplingParams, errorValue, externalBindings as bindings };
|
||||
|
||||
export let defaultSamplingInputs: samplingParams = {
|
||||
sampleCount: 10000,
|
||||
|
@ -96,15 +98,28 @@ export type squiggleExpression =
|
|||
|
||||
export function run(
|
||||
squiggleString: string,
|
||||
bindings?: externalBindings,
|
||||
samplingInputs?: samplingParams
|
||||
): result<squiggleExpression, errorValue> {
|
||||
let b = bindings ? bindings : {};
|
||||
let si: samplingParams = samplingInputs
|
||||
? samplingInputs
|
||||
: defaultSamplingInputs;
|
||||
let result: result<expressionValue, errorValue> = evaluate(squiggleString);
|
||||
|
||||
let result: result<expressionValue, errorValue> =
|
||||
evaluateUsingExternalBindings(squiggleString, b);
|
||||
return resultMap(result, (x) => createTsExport(x, si));
|
||||
}
|
||||
|
||||
// Run Partial. A partial is a block of code that doesn't return a value
|
||||
export function runPartial(
|
||||
squiggleString: string,
|
||||
bindings: externalBindings,
|
||||
_samplingInputs?: samplingParams
|
||||
): result<externalBindings, errorValue> {
|
||||
return evaluatePartialUsingExternalBindings(squiggleString, bindings);
|
||||
}
|
||||
|
||||
function createTsExport(
|
||||
x: expressionValue,
|
||||
sampEnv: samplingParams
|
||||
|
@ -166,7 +181,7 @@ function createTsExport(
|
|||
}
|
||||
}
|
||||
|
||||
// Helper functions to convert the recsript representations that genType doesn't
|
||||
// Helper functions to convert the rescript representations that genType doesn't
|
||||
// cover
|
||||
function convertRawToTypescript(
|
||||
result: rescriptExport,
|
||||
|
|
|
@ -40,6 +40,12 @@ let evaluate = Reducer.evaluate
|
|||
@genType
|
||||
let evaluateUsingExternalBindings = Reducer.evaluateUsingExternalBindings
|
||||
|
||||
@genType
|
||||
let evaluatePartialUsingExternalBindings = Reducer.evaluatePartialUsingExternalBindings
|
||||
|
||||
@genType
|
||||
type externalBindings = Reducer.externalBindings
|
||||
|
||||
@genType
|
||||
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user