Merge branch 'develop' into more-graph-settings
This commit is contained in:
commit
ec721b83ce
|
@ -20,7 +20,7 @@ Add to `App.js`:
|
||||||
```jsx
|
```jsx
|
||||||
import { SquiggleEditor } from "@quri/squiggle-components";
|
import { SquiggleEditor } from "@quri/squiggle-components";
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString="x = beta($alpha, 10); x + $shift"
|
defaultCode="x = beta($alpha, 10); x + $shift"
|
||||||
jsImports={{ alpha: 3, shift: 20 }}
|
jsImports={{ alpha: 3, shift: 20 }}
|
||||||
/>;
|
/>;
|
||||||
```
|
```
|
||||||
|
@ -50,7 +50,7 @@ export function DynamicSquiggleChart({ squiggleString }) {
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<SquiggleChart
|
<SquiggleChart
|
||||||
squiggleString={squiggleString}
|
defaultCode={squiggleString}
|
||||||
width={445}
|
width={445}
|
||||||
height={200}
|
height={200}
|
||||||
showSummary={true}
|
showSummary={true}
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
"@hookform/resolvers": "^2.9.3",
|
"@hookform/resolvers": "^2.9.3",
|
||||||
"@quri/squiggle-lang": "^0.2.8",
|
"@quri/squiggle-lang": "^0.2.8",
|
||||||
"@react-hook/size": "^2.1.2",
|
"@react-hook/size": "^2.1.2",
|
||||||
"clsx": "^1.2.0",
|
"clsx": "^1.1.1",
|
||||||
|
"framer-motion": "^6.4.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"react": "^18.1.0",
|
"react": "^18.1.0",
|
||||||
"react-ace": "^10.1.0",
|
"react-ace": "^10.1.0",
|
||||||
|
@ -38,7 +39,6 @@
|
||||||
"@types/lodash": "^4.14.182",
|
"@types/lodash": "^4.14.182",
|
||||||
"@types/node": "^18.0.0",
|
"@types/node": "^18.0.0",
|
||||||
"@types/react": "^18.0.9",
|
"@types/react": "^18.0.9",
|
||||||
"@types/react-dom": "^18.0.5",
|
|
||||||
"@types/styled-components": "^5.1.24",
|
"@types/styled-components": "^5.1.24",
|
||||||
"@types/webpack": "^5.28.0",
|
"@types/webpack": "^5.28.0",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
|
@ -47,7 +47,6 @@
|
||||||
"postcss-import": "^14.1.0",
|
"postcss-import": "^14.1.0",
|
||||||
"postcss-loader": "^7.0.0",
|
"postcss-loader": "^7.0.0",
|
||||||
"react": "^18.1.0",
|
"react": "^18.1.0",
|
||||||
"react-dom": "^18.2.0",
|
|
||||||
"react-scripts": "^5.0.1",
|
"react-scripts": "^5.0.1",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
"tailwindcss": "^3.1.3",
|
"tailwindcss": "^3.1.3",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import React, { FC, useMemo } from "react";
|
import React, { FC, useMemo, useRef } from "react";
|
||||||
import AceEditor from "react-ace";
|
import AceEditor from "react-ace";
|
||||||
|
|
||||||
import "ace-builds/src-noconflict/mode-golang";
|
import "ace-builds/src-noconflict/mode-golang";
|
||||||
|
@ -8,6 +8,7 @@ import "ace-builds/src-noconflict/theme-github";
|
||||||
interface CodeEditorProps {
|
interface CodeEditorProps {
|
||||||
value: string;
|
value: string;
|
||||||
onChange: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
|
onSubmit?: () => void;
|
||||||
oneLine?: boolean;
|
oneLine?: boolean;
|
||||||
width?: number;
|
width?: number;
|
||||||
height: number;
|
height: number;
|
||||||
|
@ -17,6 +18,7 @@ interface CodeEditorProps {
|
||||||
export const CodeEditor: FC<CodeEditorProps> = ({
|
export const CodeEditor: FC<CodeEditorProps> = ({
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
|
onSubmit,
|
||||||
oneLine = false,
|
oneLine = false,
|
||||||
showGutter = false,
|
showGutter = false,
|
||||||
height,
|
height,
|
||||||
|
@ -24,6 +26,10 @@ export const CodeEditor: FC<CodeEditorProps> = ({
|
||||||
const lineCount = value.split("\n").length;
|
const lineCount = value.split("\n").length;
|
||||||
const id = useMemo(() => _.uniqueId(), []);
|
const id = useMemo(() => _.uniqueId(), []);
|
||||||
|
|
||||||
|
// this is necessary because AceEditor binds commands on mount, see https://github.com/securingsincity/react-ace/issues/684
|
||||||
|
const onSubmitRef = useRef<typeof onSubmit | null>(null);
|
||||||
|
onSubmitRef.current = onSubmit;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AceEditor
|
<AceEditor
|
||||||
value={value}
|
value={value}
|
||||||
|
@ -46,6 +52,13 @@ export const CodeEditor: FC<CodeEditorProps> = ({
|
||||||
enableBasicAutocompletion: false,
|
enableBasicAutocompletion: false,
|
||||||
enableLiveAutocompletion: false,
|
enableLiveAutocompletion: false,
|
||||||
}}
|
}}
|
||||||
|
commands={[
|
||||||
|
{
|
||||||
|
name: "submit",
|
||||||
|
bindKey: { mac: "Cmd-Enter", win: "Ctrl-Enter" },
|
||||||
|
exec: () => onSubmitRef.current?.(),
|
||||||
|
},
|
||||||
|
]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,20 +8,23 @@ import {
|
||||||
defaultBindings,
|
defaultBindings,
|
||||||
defaultEnvironment,
|
defaultEnvironment,
|
||||||
} from "@quri/squiggle-lang";
|
} from "@quri/squiggle-lang";
|
||||||
import { FunctionChartSettings } from "./FunctionChart";
|
|
||||||
import { useSquiggle } from "../lib/hooks";
|
import { useSquiggle } from "../lib/hooks";
|
||||||
import { SquiggleErrorAlert } from "./SquiggleErrorAlert";
|
import { SquiggleErrorAlert } from "./SquiggleErrorAlert";
|
||||||
import { SquiggleItem } from "./SquiggleItem";
|
import { SquiggleItem } from "./SquiggleItem";
|
||||||
|
|
||||||
export interface SquiggleChartProps {
|
export interface SquiggleChartProps {
|
||||||
/** The input string for squiggle */
|
/** The input string for squiggle */
|
||||||
squiggleString?: string;
|
code?: string;
|
||||||
/** If the output requires monte carlo sampling, the amount of samples */
|
/** If the output requires monte carlo sampling, the amount of samples */
|
||||||
sampleCount?: number;
|
sampleCount?: number;
|
||||||
/** The amount of points returned to draw the distribution */
|
/** The amount of points returned to draw the distribution */
|
||||||
environment?: environment;
|
environment?: environment;
|
||||||
/** If the result is a function, where the function starts, ends and the amount of stops */
|
/** If the result is a function, where the function domain starts */
|
||||||
chartSettings?: FunctionChartSettings;
|
diagramStart?: number;
|
||||||
|
/** If the result is a function, where the function domain ends */
|
||||||
|
diagramStop?: number;
|
||||||
|
/** If the result is a function, the amount of stops sampled */
|
||||||
|
diagramCount?: number;
|
||||||
/** When the squiggle code gets reevaluated */
|
/** When the squiggle code gets reevaluated */
|
||||||
onChange?(expr: squiggleExpression | undefined): void;
|
onChange?(expr: squiggleExpression | undefined): void;
|
||||||
/** CSS width of the element */
|
/** CSS width of the element */
|
||||||
|
@ -56,10 +59,9 @@ export interface SquiggleChartProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultOnChange = () => {};
|
const defaultOnChange = () => {};
|
||||||
const defaultChartSettings = { start: 0, stop: 10, count: 20 };
|
|
||||||
|
|
||||||
export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
export const SquiggleChart: React.FC<SquiggleChartProps> = React.memo(({
|
||||||
squiggleString = "",
|
code = "",
|
||||||
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,
|
||||||
|
@ -71,7 +73,9 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
||||||
showControls = false,
|
showControls = false,
|
||||||
logX = false,
|
logX = false,
|
||||||
expY = false,
|
expY = false,
|
||||||
chartSettings = defaultChartSettings,
|
diagramStart = 0,
|
||||||
|
diagramStop = 10,
|
||||||
|
diagramCount = 100,
|
||||||
tickFormat,
|
tickFormat,
|
||||||
minX,
|
minX,
|
||||||
maxX,
|
maxX,
|
||||||
|
@ -79,8 +83,8 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
||||||
title,
|
title,
|
||||||
distributionChartActions,
|
distributionChartActions,
|
||||||
}) => {
|
}) => {
|
||||||
const { result } = useSquiggle({
|
const result = useSquiggle({
|
||||||
code: squiggleString,
|
code,
|
||||||
bindings,
|
bindings,
|
||||||
environment,
|
environment,
|
||||||
jsImports,
|
jsImports,
|
||||||
|
@ -104,6 +108,12 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
||||||
actions: distributionChartActions,
|
actions: distributionChartActions,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let chartSettings = {
|
||||||
|
start: diagramStart,
|
||||||
|
stop: diagramStop,
|
||||||
|
count: diagramCount,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SquiggleItem
|
<SquiggleItem
|
||||||
expression={result.value}
|
expression={result.value}
|
||||||
|
@ -115,4 +125,5 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
||||||
environment={environment ?? defaultEnvironment}
|
environment={environment ?? defaultEnvironment}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
);
|
||||||
|
|
|
@ -1,18 +1,11 @@
|
||||||
import React, { useState } from "react";
|
import React from "react";
|
||||||
import * as ReactDOM from "react-dom";
|
|
||||||
import { CodeEditor } from "./CodeEditor";
|
import { CodeEditor } from "./CodeEditor";
|
||||||
import {
|
import { environment, bindings, jsImports } from "@quri/squiggle-lang";
|
||||||
squiggleExpression,
|
|
||||||
environment,
|
|
||||||
bindings,
|
|
||||||
jsImports,
|
|
||||||
defaultEnvironment,
|
|
||||||
} from "@quri/squiggle-lang";
|
|
||||||
import { defaultImports, defaultBindings } from "@quri/squiggle-lang";
|
import { defaultImports, defaultBindings } from "@quri/squiggle-lang";
|
||||||
import { SquiggleContainer } from "./SquiggleContainer";
|
import { SquiggleContainer } from "./SquiggleContainer";
|
||||||
import { useSquiggle, useSquigglePartial } from "../lib/hooks";
|
import { SquiggleChart, SquiggleChartProps } from "./SquiggleChart";
|
||||||
|
import { useSquigglePartial, useMaybeControlledValue } from "../lib/hooks";
|
||||||
import { SquiggleErrorAlert } from "./SquiggleErrorAlert";
|
import { SquiggleErrorAlert } from "./SquiggleErrorAlert";
|
||||||
import { SquiggleItem } from "./SquiggleItem";
|
|
||||||
|
|
||||||
const WrappedCodeEditor: React.FC<{
|
const WrappedCodeEditor: React.FC<{
|
||||||
code: string;
|
code: string;
|
||||||
|
@ -29,113 +22,36 @@ const WrappedCodeEditor: React.FC<{
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export interface SquiggleEditorProps {
|
export type SquiggleEditorProps = SquiggleChartProps & {
|
||||||
/** The input string for squiggle */
|
defaultCode?: string;
|
||||||
initialSquiggleString?: string;
|
onCodeChange?: (code: string) => void;
|
||||||
/** The width of the element */
|
};
|
||||||
width?: 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: squiggleExpression | undefined): void;
|
|
||||||
/** Previous variable declarations */
|
|
||||||
bindings?: bindings;
|
|
||||||
/** If the output requires monte carlo sampling, the amount of samples */
|
|
||||||
environment?: environment;
|
|
||||||
/** JS Imports */
|
|
||||||
jsImports?: jsImports;
|
|
||||||
/** Whether to show detail about types of the returns, default false */
|
|
||||||
showTypes?: boolean;
|
|
||||||
/** Whether to give users access to graph controls */
|
|
||||||
showControls?: boolean;
|
|
||||||
/** Whether to show a summary table */
|
|
||||||
showSummary?: boolean;
|
|
||||||
/** Whether to log the x coordinate on distribution charts */
|
|
||||||
logX?: boolean;
|
|
||||||
/** Whether to exp the y coordinate on distribution charts */
|
|
||||||
expY?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SquiggleEditor: React.FC<SquiggleEditorProps> = ({
|
export const SquiggleEditor: React.FC<SquiggleEditorProps> = (props) => {
|
||||||
initialSquiggleString = "",
|
const [code, setCode] = useMaybeControlledValue({
|
||||||
width,
|
value: props.code,
|
||||||
diagramStart = 0,
|
defaultValue: props.defaultCode ?? "",
|
||||||
diagramStop = 10,
|
onChange: props.onCodeChange,
|
||||||
diagramCount = 20,
|
|
||||||
onChange,
|
|
||||||
bindings = defaultBindings,
|
|
||||||
environment,
|
|
||||||
jsImports = defaultImports,
|
|
||||||
showTypes = false,
|
|
||||||
showControls = false,
|
|
||||||
showSummary = false,
|
|
||||||
logX = false,
|
|
||||||
expY = false,
|
|
||||||
}: SquiggleEditorProps) => {
|
|
||||||
const [code, setCode] = useState(initialSquiggleString);
|
|
||||||
React.useEffect(
|
|
||||||
() => setCode(initialSquiggleString),
|
|
||||||
[initialSquiggleString]
|
|
||||||
);
|
|
||||||
|
|
||||||
const { result, observableRef } = useSquiggle({
|
|
||||||
code,
|
|
||||||
bindings,
|
|
||||||
environment,
|
|
||||||
jsImports,
|
|
||||||
onChange,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const chartSettings = {
|
let chartProps = { ...props, code };
|
||||||
start: diagramStart,
|
|
||||||
stop: diagramStop,
|
|
||||||
count: diagramCount,
|
|
||||||
};
|
|
||||||
|
|
||||||
const distributionPlotSettings = {
|
|
||||||
showControls,
|
|
||||||
showSummary,
|
|
||||||
logX,
|
|
||||||
expY,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={observableRef}>
|
|
||||||
<SquiggleContainer>
|
<SquiggleContainer>
|
||||||
<WrappedCodeEditor code={code} setCode={setCode} />
|
<WrappedCodeEditor code={code} setCode={setCode} />
|
||||||
{result.tag === "Ok" ? (
|
<SquiggleChart {...chartProps} />
|
||||||
<SquiggleItem
|
|
||||||
expression={result.value}
|
|
||||||
width={width}
|
|
||||||
height={200}
|
|
||||||
distributionPlotSettings={distributionPlotSettings}
|
|
||||||
showTypes={showTypes}
|
|
||||||
chartSettings={chartSettings}
|
|
||||||
environment={environment ?? defaultEnvironment}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<SquiggleErrorAlert error={result.value} />
|
|
||||||
)}
|
|
||||||
</SquiggleContainer>
|
</SquiggleContainer>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function renderSquiggleEditorToDom(props: SquiggleEditorProps) {
|
|
||||||
const parent = document.createElement("div");
|
|
||||||
ReactDOM.render(<SquiggleEditor {...props} />, parent);
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SquigglePartialProps {
|
export interface SquigglePartialProps {
|
||||||
/** The input string for squiggle */
|
/** The text inside the input (controlled) */
|
||||||
initialSquiggleString?: string;
|
code?: string;
|
||||||
|
/** The default text inside the input (unControlled) */
|
||||||
|
defaultCode?: string;
|
||||||
/** when the environment changes. Used again for notebook magic*/
|
/** when the environment changes. Used again for notebook magic*/
|
||||||
onChange?(expr: bindings | undefined): void;
|
onChange?(expr: bindings | undefined): void;
|
||||||
|
/** When the code changes */
|
||||||
|
onCodeChange?(code: string): void;
|
||||||
/** Previously declared variables */
|
/** Previously declared variables */
|
||||||
bindings?: bindings;
|
bindings?: bindings;
|
||||||
/** If the output requires monte carlo sampling, the amount of samples */
|
/** If the output requires monte carlo sampling, the amount of samples */
|
||||||
|
@ -145,19 +61,21 @@ export interface SquigglePartialProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SquigglePartial: React.FC<SquigglePartialProps> = ({
|
export const SquigglePartial: React.FC<SquigglePartialProps> = ({
|
||||||
initialSquiggleString = "",
|
code: controlledCode,
|
||||||
|
defaultCode = "",
|
||||||
onChange,
|
onChange,
|
||||||
|
onCodeChange,
|
||||||
bindings = defaultBindings,
|
bindings = defaultBindings,
|
||||||
environment,
|
environment,
|
||||||
jsImports = defaultImports,
|
jsImports = defaultImports,
|
||||||
}: SquigglePartialProps) => {
|
}: SquigglePartialProps) => {
|
||||||
const [code, setCode] = useState(initialSquiggleString);
|
const [code, setCode] = useMaybeControlledValue<string>({
|
||||||
React.useEffect(
|
value: controlledCode,
|
||||||
() => setCode(initialSquiggleString),
|
defaultValue: defaultCode,
|
||||||
[initialSquiggleString]
|
onChange: onCodeChange,
|
||||||
);
|
});
|
||||||
|
|
||||||
const { result, observableRef } = useSquigglePartial({
|
const result = useSquigglePartial({
|
||||||
code,
|
code,
|
||||||
bindings,
|
bindings,
|
||||||
environment,
|
environment,
|
||||||
|
@ -166,19 +84,9 @@ export const SquigglePartial: React.FC<SquigglePartialProps> = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={observableRef}>
|
|
||||||
<SquiggleContainer>
|
<SquiggleContainer>
|
||||||
<WrappedCodeEditor code={code} setCode={setCode} />
|
<WrappedCodeEditor code={code} setCode={setCode} />
|
||||||
{result.tag !== "Ok" ? (
|
{result.tag !== "Ok" ? <SquiggleErrorAlert error={result.value} /> : null}
|
||||||
<SquiggleErrorAlert error={result.value} />
|
|
||||||
) : null}
|
|
||||||
</SquiggleContainer>
|
</SquiggleContainer>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function renderSquigglePartialToDom(props: SquigglePartialProps) {
|
|
||||||
const parent = document.createElement("div");
|
|
||||||
ReactDOM.render(<SquigglePartial {...props} />, parent);
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
import React, { FC, Fragment, useState, useEffect } from "react";
|
import React, { FC, useState, useEffect, useMemo } from "react";
|
||||||
import ReactDOM from "react-dom";
|
|
||||||
import { Path, useForm, UseFormRegister, useWatch } from "react-hook-form";
|
import { Path, useForm, UseFormRegister, useWatch } from "react-hook-form";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
|
import { useMaybeControlledValue } from "../lib/hooks";
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import { Tab } from "@headlessui/react";
|
|
||||||
import {
|
import {
|
||||||
ChartSquareBarIcon,
|
ChartSquareBarIcon,
|
||||||
|
CheckCircleIcon,
|
||||||
CodeIcon,
|
CodeIcon,
|
||||||
CogIcon,
|
CogIcon,
|
||||||
CurrencyDollarIcon,
|
CurrencyDollarIcon,
|
||||||
EyeIcon,
|
EyeIcon,
|
||||||
|
PauseIcon,
|
||||||
|
PlayIcon,
|
||||||
|
RefreshIcon,
|
||||||
} from "@heroicons/react/solid";
|
} from "@heroicons/react/solid";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
|
@ -20,10 +23,13 @@ import { CodeEditor } from "./CodeEditor";
|
||||||
import { JsonEditor } from "./JsonEditor";
|
import { JsonEditor } from "./JsonEditor";
|
||||||
import { ErrorAlert, SuccessAlert } from "./Alert";
|
import { ErrorAlert, SuccessAlert } from "./Alert";
|
||||||
import { SquiggleContainer } from "./SquiggleContainer";
|
import { SquiggleContainer } from "./SquiggleContainer";
|
||||||
|
import { Toggle } from "./ui/Toggle";
|
||||||
|
import { Checkbox } from "./ui/Checkbox";
|
||||||
|
import { StyledTab } from "./ui/StyledTab";
|
||||||
|
|
||||||
interface PlaygroundProps {
|
interface PlaygroundProps {
|
||||||
/** The initial squiggle string to put in the playground */
|
/** The initial squiggle string to put in the playground */
|
||||||
initialSquiggleString?: string;
|
defaultCode?: string;
|
||||||
/** How many pixels high is the playground */
|
/** How many pixels high is the playground */
|
||||||
height?: number;
|
height?: number;
|
||||||
/** Whether to show the types of outputs in the playground */
|
/** Whether to show the types of outputs in the playground */
|
||||||
|
@ -44,9 +50,7 @@ interface PlaygroundProps {
|
||||||
showEditor?: boolean;
|
showEditor?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const schema = yup
|
const schema = yup.object({}).shape({
|
||||||
.object()
|
|
||||||
.shape({
|
|
||||||
sampleCount: yup
|
sampleCount: yup
|
||||||
.number()
|
.number()
|
||||||
.required()
|
.required()
|
||||||
|
@ -72,76 +76,19 @@ const schema = yup
|
||||||
.min(10)
|
.min(10)
|
||||||
.max(100)
|
.max(100)
|
||||||
.default(50),
|
.default(50),
|
||||||
showTypes: yup.boolean(),
|
showTypes: yup.boolean().required(),
|
||||||
showControls: yup.boolean(),
|
showControls: yup.boolean().required(),
|
||||||
showSummary: yup.boolean(),
|
showSummary: yup.boolean().required(),
|
||||||
showEditor: yup.boolean(),
|
showEditor: yup.boolean().required(),
|
||||||
logX: yup.boolean(),
|
logX: yup.boolean().required(),
|
||||||
expY: yup.boolean(),
|
expY: yup.boolean().required(),
|
||||||
showSettingsPage: yup.boolean().default(false),
|
showSettingsPage: yup.boolean().default(false),
|
||||||
diagramStart: yup
|
diagramStart: yup.number().required().positive().integer().default(0).min(0),
|
||||||
.number()
|
diagramStop: yup.number().required().positive().integer().default(10).min(0),
|
||||||
.required()
|
diagramCount: yup.number().required().positive().integer().default(20).min(2),
|
||||||
.positive()
|
});
|
||||||
.integer()
|
|
||||||
.default(0)
|
|
||||||
.min(0),
|
|
||||||
diagramStop: yup
|
|
||||||
.number()
|
|
||||||
.required()
|
|
||||||
.positive()
|
|
||||||
.integer()
|
|
||||||
.default(10)
|
|
||||||
.min(0),
|
|
||||||
diagramCount: yup
|
|
||||||
.number()
|
|
||||||
.required()
|
|
||||||
.positive()
|
|
||||||
.integer()
|
|
||||||
.default(20)
|
|
||||||
.min(2),
|
|
||||||
})
|
|
||||||
.required();
|
|
||||||
|
|
||||||
type StyledTabProps = {
|
type FormFields = yup.InferType<typeof schema>;
|
||||||
name: string;
|
|
||||||
icon: (props: React.ComponentProps<"svg">) => JSX.Element;
|
|
||||||
};
|
|
||||||
|
|
||||||
const StyledTab: React.FC<StyledTabProps> = ({ name, icon: Icon }) => {
|
|
||||||
return (
|
|
||||||
<Tab key={name} as={Fragment}>
|
|
||||||
{({ selected }) => (
|
|
||||||
<button className="group flex rounded-md focus:outline-none focus-visible:ring-offset-gray-100">
|
|
||||||
<span
|
|
||||||
className={clsx(
|
|
||||||
"p-1 pl-2.5 pr-3.5 rounded-md flex items-center text-sm font-medium",
|
|
||||||
selected && "bg-white shadow-sm ring-1 ring-black ring-opacity-5"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
className={clsx(
|
|
||||||
"-ml-0.5 mr-2 h-4 w-4",
|
|
||||||
selected
|
|
||||||
? "text-slate-500"
|
|
||||||
: "text-gray-400 group-hover:text-gray-900"
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
className={clsx(
|
|
||||||
selected
|
|
||||||
? "text-gray-900"
|
|
||||||
: "text-gray-600 group-hover:text-gray-900"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{name}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</Tab>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const HeadedSection: FC<{ title: string; children: React.ReactNode }> = ({
|
const HeadedSection: FC<{ title: string; children: React.ReactNode }> = ({
|
||||||
title,
|
title,
|
||||||
|
@ -182,96 +129,9 @@ function InputItem<T>({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Checkbox<T>({
|
const SamplingSettings: React.FC<{ register: UseFormRegister<FormFields> }> = ({
|
||||||
name,
|
|
||||||
label,
|
|
||||||
register,
|
register,
|
||||||
}: {
|
}) => (
|
||||||
name: Path<T>;
|
|
||||||
label: string;
|
|
||||||
register: UseFormRegister<T>;
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<label className="flex items-center">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
{...register(name)}
|
|
||||||
className="form-checkbox focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
|
||||||
/>
|
|
||||||
{/* Clicking on the div makes the checkbox lose focus while mouse button is pressed, leading to annoying blinking; I couldn't figure out how to fix this. */}
|
|
||||||
<div className="ml-3 text-sm font-medium text-gray-700">{label}</div>
|
|
||||||
</label>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SquigglePlayground: FC<PlaygroundProps> = ({
|
|
||||||
initialSquiggleString = "",
|
|
||||||
height = 500,
|
|
||||||
showTypes = false,
|
|
||||||
showControls = false,
|
|
||||||
showSummary = false,
|
|
||||||
logX = false,
|
|
||||||
expY = false,
|
|
||||||
code: controlledCode,
|
|
||||||
onCodeChange,
|
|
||||||
onSettingsChange,
|
|
||||||
showEditor = true,
|
|
||||||
}) => {
|
|
||||||
const [uncontrolledCode, setUncontrolledCode] = useState(
|
|
||||||
initialSquiggleString
|
|
||||||
);
|
|
||||||
const [importString, setImportString] = useState("{}");
|
|
||||||
const [imports, setImports] = useState({});
|
|
||||||
const [importsAreValid, setImportsAreValid] = useState(true);
|
|
||||||
const { register, control } = useForm({
|
|
||||||
resolver: yupResolver(schema),
|
|
||||||
defaultValues: {
|
|
||||||
sampleCount: 1000,
|
|
||||||
xyPointLength: 1000,
|
|
||||||
chartHeight: 150,
|
|
||||||
showTypes,
|
|
||||||
showControls,
|
|
||||||
logX,
|
|
||||||
expY,
|
|
||||||
showSummary,
|
|
||||||
showEditor,
|
|
||||||
leftSizePercent: 50,
|
|
||||||
showSettingsPage: false,
|
|
||||||
diagramStart: 0,
|
|
||||||
diagramStop: 10,
|
|
||||||
diagramCount: 20,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const vars = useWatch({
|
|
||||||
control,
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
onSettingsChange?.(vars);
|
|
||||||
}, [vars, onSettingsChange]);
|
|
||||||
|
|
||||||
const chartSettings = {
|
|
||||||
start: Number(vars.diagramStart),
|
|
||||||
stop: Number(vars.diagramStop),
|
|
||||||
count: Number(vars.diagramCount),
|
|
||||||
};
|
|
||||||
const env: environment = {
|
|
||||||
sampleCount: Number(vars.sampleCount),
|
|
||||||
xyPointLength: Number(vars.xyPointLength),
|
|
||||||
};
|
|
||||||
const getChangeJson = (r: string) => {
|
|
||||||
setImportString(r);
|
|
||||||
try {
|
|
||||||
setImports(JSON.parse(r));
|
|
||||||
setImportsAreValid(true);
|
|
||||||
} catch (e) {
|
|
||||||
setImportsAreValid(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const code = controlledCode ?? uncontrolledCode;
|
|
||||||
|
|
||||||
const samplingSettings = (
|
|
||||||
<div className="space-y-6 p-3 max-w-xl">
|
<div className="space-y-6 p-3 max-w-xl">
|
||||||
<div>
|
<div>
|
||||||
<InputItem
|
<InputItem
|
||||||
|
@ -296,15 +156,17 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
/>
|
/>
|
||||||
<div className="mt-2">
|
<div className="mt-2">
|
||||||
<Text>
|
<Text>
|
||||||
When distributions are converted into PointSet shapes, we need to
|
When distributions are converted into PointSet shapes, we need to know
|
||||||
know how many coordinates to use.
|
how many coordinates to use.
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const viewSettings = (
|
const ViewSettings: React.FC<{ register: UseFormRegister<FormFields> }> = ({
|
||||||
|
register,
|
||||||
|
}) => (
|
||||||
<div className="space-y-6 p-3 divide-y divide-gray-200 max-w-xl">
|
<div className="space-y-6 p-3 divide-y divide-gray-200 max-w-xl">
|
||||||
<HeadedSection title="General Display Settings">
|
<HeadedSection title="General Display Settings">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
|
@ -358,10 +220,10 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
<HeadedSection title="Function Display Settings">
|
<HeadedSection title="Function Display Settings">
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<Text>
|
<Text>
|
||||||
When displaying functions of single variables that return numbers
|
When displaying functions of single variables that return numbers or
|
||||||
or distributions, we need to use defaults for the x-axis. We need
|
distributions, we need to use defaults for the x-axis. We need to
|
||||||
to select a minimum and maximum value of x to sample, and a number
|
select a minimum and maximum value of x to sample, and a number n of
|
||||||
n of the number of points to sample.
|
the number of points to sample.
|
||||||
</Text>
|
</Text>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<InputItem
|
<InputItem
|
||||||
|
@ -387,9 +249,30 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
</HeadedSection>
|
</HeadedSection>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const inputVariableSettings = (
|
const InputVariablesSettings: React.FC<{
|
||||||
|
initialImports: any; // TODO - any json type
|
||||||
|
setImports: (imports: any) => void;
|
||||||
|
}> = ({ initialImports, setImports }) => {
|
||||||
|
const [importString, setImportString] = useState(() =>
|
||||||
|
JSON.stringify(initialImports)
|
||||||
|
);
|
||||||
|
const [importsAreValid, setImportsAreValid] = useState(true);
|
||||||
|
|
||||||
|
const onChange = (value: string) => {
|
||||||
|
setImportString(value);
|
||||||
|
let imports = {} as any;
|
||||||
|
try {
|
||||||
|
imports = JSON.parse(value);
|
||||||
|
setImportsAreValid(true);
|
||||||
|
} catch (e) {
|
||||||
|
setImportsAreValid(false);
|
||||||
|
}
|
||||||
|
setImports(imports);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
<div className="p-3 max-w-3xl">
|
<div className="p-3 max-w-3xl">
|
||||||
<HeadedSection title="Import Variables from JSON">
|
<HeadedSection title="Import Variables from JSON">
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
|
@ -401,7 +284,7 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
<div className="border border-slate-200 mt-6 mb-2">
|
<div className="border border-slate-200 mt-6 mb-2">
|
||||||
<JsonEditor
|
<JsonEditor
|
||||||
value={importString}
|
value={importString}
|
||||||
onChange={getChangeJson}
|
onChange={onChange}
|
||||||
oneLine={false}
|
oneLine={false}
|
||||||
showGutter={true}
|
showGutter={true}
|
||||||
height={150}
|
height={150}
|
||||||
|
@ -420,12 +303,146 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
</HeadedSection>
|
</HeadedSection>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const RunControls: React.FC<{
|
||||||
|
autorunMode: boolean;
|
||||||
|
isRunning: boolean;
|
||||||
|
isStale: boolean;
|
||||||
|
onAutorunModeChange: (value: boolean) => void;
|
||||||
|
run: () => void;
|
||||||
|
}> = ({ autorunMode, isRunning, isStale, onAutorunModeChange, run }) => {
|
||||||
|
const CurrentPlayIcon = isRunning ? RefreshIcon : PlayIcon;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex space-x-1 items-center">
|
||||||
|
{autorunMode ? null : (
|
||||||
|
<button onClick={run}>
|
||||||
|
<CurrentPlayIcon
|
||||||
|
className={clsx(
|
||||||
|
"w-8 h-8",
|
||||||
|
isRunning && "animate-spin",
|
||||||
|
isStale ? "text-indigo-500" : "text-gray-400"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<Toggle
|
||||||
|
texts={["Autorun", "Paused"]}
|
||||||
|
icons={[CheckCircleIcon, PauseIcon]}
|
||||||
|
status={autorunMode}
|
||||||
|
onChange={onAutorunModeChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const useRunnerState = (code: string) => {
|
||||||
|
const [autorunMode, setAutorunMode] = useState(true);
|
||||||
|
const [renderedCode, setRenderedCode] = useState(code); // used in manual run mode only
|
||||||
|
const [isRunning, setIsRunning] = useState(false); // used in manual run mode only
|
||||||
|
|
||||||
|
// This part is tricky and fragile; we need to re-render first to make sure that the icon is spinning,
|
||||||
|
// and only then evaluate the squiggle code (which freezes the UI).
|
||||||
|
// Also note that `useEffect` execution order matters here.
|
||||||
|
// Hopefully it'll all go away after we make squiggle code evaluation async.
|
||||||
|
useEffect(() => {
|
||||||
|
if (renderedCode === code && isRunning) {
|
||||||
|
// It's not possible to put this after `setRenderedCode(code)` below because React would apply
|
||||||
|
// `setIsRunning` and `setRenderedCode` together and spinning icon will disappear immediately.
|
||||||
|
setIsRunning(false);
|
||||||
|
}
|
||||||
|
}, [renderedCode, code, isRunning]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!autorunMode && isRunning) {
|
||||||
|
setRenderedCode(code); // TODO - force run even if code hasn't changed
|
||||||
|
}
|
||||||
|
}, [autorunMode, code, isRunning]);
|
||||||
|
|
||||||
|
const run = () => {
|
||||||
|
// The rest will be handled by useEffects above, but we need to update the spinner first.
|
||||||
|
setIsRunning(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
run,
|
||||||
|
renderedCode: autorunMode ? code : renderedCode,
|
||||||
|
isRunning,
|
||||||
|
autorunMode,
|
||||||
|
setAutorunMode: (newValue: boolean) => {
|
||||||
|
if (!newValue) setRenderedCode(code);
|
||||||
|
setAutorunMode(newValue);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
|
defaultCode = "",
|
||||||
|
height = 500,
|
||||||
|
showTypes = false,
|
||||||
|
showControls = false,
|
||||||
|
showSummary = false,
|
||||||
|
logX = false,
|
||||||
|
expY = false,
|
||||||
|
code: controlledCode,
|
||||||
|
onCodeChange,
|
||||||
|
onSettingsChange,
|
||||||
|
showEditor = true,
|
||||||
|
}) => {
|
||||||
|
const [code, setCode] = useMaybeControlledValue({
|
||||||
|
value: controlledCode,
|
||||||
|
defaultValue: defaultCode,
|
||||||
|
onChange: onCodeChange,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [imports, setImports] = useState({});
|
||||||
|
|
||||||
|
const { register, control } = useForm({
|
||||||
|
resolver: yupResolver(schema),
|
||||||
|
defaultValues: {
|
||||||
|
sampleCount: 1000,
|
||||||
|
xyPointLength: 1000,
|
||||||
|
chartHeight: 150,
|
||||||
|
showTypes,
|
||||||
|
showControls,
|
||||||
|
logX,
|
||||||
|
expY,
|
||||||
|
showSummary,
|
||||||
|
showEditor,
|
||||||
|
leftSizePercent: 50,
|
||||||
|
showSettingsPage: false,
|
||||||
|
diagramStart: 0,
|
||||||
|
diagramStop: 10,
|
||||||
|
diagramCount: 20,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const vars = useWatch({
|
||||||
|
control,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
onSettingsChange?.(vars);
|
||||||
|
}, [vars, onSettingsChange]);
|
||||||
|
|
||||||
|
const env: environment = useMemo(
|
||||||
|
() => ({
|
||||||
|
sampleCount: Number(vars.sampleCount),
|
||||||
|
xyPointLength: Number(vars.xyPointLength),
|
||||||
|
}),
|
||||||
|
[vars.sampleCount, vars.xyPointLength]
|
||||||
|
);
|
||||||
|
|
||||||
|
const { run, autorunMode, setAutorunMode, isRunning, renderedCode } =
|
||||||
|
useRunnerState(code);
|
||||||
|
|
||||||
const squiggleChart = (
|
const squiggleChart = (
|
||||||
<SquiggleChart
|
<SquiggleChart
|
||||||
squiggleString={code}
|
code={renderedCode}
|
||||||
environment={env}
|
environment={env}
|
||||||
chartSettings={chartSettings}
|
diagramStart={Number(vars.diagramStart)}
|
||||||
|
diagramStop={Number(vars.diagramStop)}
|
||||||
|
diagramCount={Number(vars.diagramCount)}
|
||||||
height={vars.chartHeight}
|
height={vars.chartHeight}
|
||||||
showTypes={vars.showTypes}
|
showTypes={vars.showTypes}
|
||||||
showControls={vars.showControls}
|
showControls={vars.showControls}
|
||||||
|
@ -441,13 +458,8 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
<div className="border border-slate-200">
|
<div className="border border-slate-200">
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
value={code}
|
value={code}
|
||||||
onChange={(newCode) => {
|
onChange={setCode}
|
||||||
if (controlledCode === undefined) {
|
onSubmit={run}
|
||||||
// uncontrolled mode
|
|
||||||
setUncontrolledCode(newCode);
|
|
||||||
}
|
|
||||||
onCodeChange?.(newCode);
|
|
||||||
}}
|
|
||||||
oneLine={false}
|
oneLine={false}
|
||||||
showGutter={true}
|
showGutter={true}
|
||||||
height={height - 1}
|
height={height - 1}
|
||||||
|
@ -458,12 +470,21 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
);
|
);
|
||||||
|
|
||||||
const tabs = (
|
const tabs = (
|
||||||
<Tab.Panels>
|
<StyledTab.Panels>
|
||||||
<Tab.Panel>{firstTab}</Tab.Panel>
|
<StyledTab.Panel>{firstTab}</StyledTab.Panel>
|
||||||
<Tab.Panel>{samplingSettings}</Tab.Panel>
|
<StyledTab.Panel>
|
||||||
<Tab.Panel>{viewSettings}</Tab.Panel>
|
<SamplingSettings register={register} />
|
||||||
<Tab.Panel>{inputVariableSettings}</Tab.Panel>
|
</StyledTab.Panel>
|
||||||
</Tab.Panels>
|
<StyledTab.Panel>
|
||||||
|
<ViewSettings register={register} />
|
||||||
|
</StyledTab.Panel>
|
||||||
|
<StyledTab.Panel>
|
||||||
|
<InputVariablesSettings
|
||||||
|
initialImports={imports}
|
||||||
|
setImports={setImports}
|
||||||
|
/>
|
||||||
|
</StyledTab.Panel>
|
||||||
|
</StyledTab.Panels>
|
||||||
);
|
);
|
||||||
|
|
||||||
const withEditor = (
|
const withEditor = (
|
||||||
|
@ -477,9 +498,10 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SquiggleContainer>
|
<SquiggleContainer>
|
||||||
<Tab.Group>
|
<StyledTab.Group>
|
||||||
<div className="pb-4">
|
<div className="pb-4">
|
||||||
<Tab.List className="flex w-fit p-0.5 mt-2 rounded-md bg-slate-100 hover:bg-slate-200">
|
<div className="flex justify-between items-center mt-2">
|
||||||
|
<StyledTab.List>
|
||||||
<StyledTab
|
<StyledTab
|
||||||
name={vars.showEditor ? "Code" : "Display"}
|
name={vars.showEditor ? "Code" : "Display"}
|
||||||
icon={vars.showEditor ? CodeIcon : EyeIcon}
|
icon={vars.showEditor ? CodeIcon : EyeIcon}
|
||||||
|
@ -487,16 +509,18 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
<StyledTab name="Sampling Settings" icon={CogIcon} />
|
<StyledTab name="Sampling Settings" icon={CogIcon} />
|
||||||
<StyledTab name="View Settings" icon={ChartSquareBarIcon} />
|
<StyledTab name="View Settings" icon={ChartSquareBarIcon} />
|
||||||
<StyledTab name="Input Variables" icon={CurrencyDollarIcon} />
|
<StyledTab name="Input Variables" icon={CurrencyDollarIcon} />
|
||||||
</Tab.List>
|
</StyledTab.List>
|
||||||
|
<RunControls
|
||||||
|
autorunMode={autorunMode}
|
||||||
|
isStale={renderedCode !== code}
|
||||||
|
run={run}
|
||||||
|
isRunning={isRunning}
|
||||||
|
onAutorunModeChange={setAutorunMode}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{vars.showEditor ? withEditor : withoutEditor}
|
{vars.showEditor ? withEditor : withoutEditor}
|
||||||
</div>
|
</div>
|
||||||
</Tab.Group>
|
</StyledTab.Group>
|
||||||
</SquiggleContainer>
|
</SquiggleContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function renderSquigglePlaygroundToDom(props: PlaygroundProps) {
|
|
||||||
const parent = document.createElement("div");
|
|
||||||
ReactDOM.render(<SquigglePlayground {...props} />, parent);
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
24
packages/components/src/components/ui/Checkbox.tsx
Normal file
24
packages/components/src/components/ui/Checkbox.tsx
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import React from "react";
|
||||||
|
import { Path, UseFormRegister } from "react-hook-form";
|
||||||
|
|
||||||
|
export function Checkbox<T>({
|
||||||
|
name,
|
||||||
|
label,
|
||||||
|
register,
|
||||||
|
}: {
|
||||||
|
name: Path<T>;
|
||||||
|
label: string;
|
||||||
|
register: UseFormRegister<T>;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<label className="flex items-center">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
{...register(name)}
|
||||||
|
className="form-checkbox focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
|
/>
|
||||||
|
{/* Clicking on the div makes the checkbox lose focus while mouse button is pressed, leading to annoying blinking; I couldn't figure out how to fix this. */}
|
||||||
|
<div className="ml-3 text-sm font-medium text-gray-700">{label}</div>
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
}
|
60
packages/components/src/components/ui/StyledTab.tsx
Normal file
60
packages/components/src/components/ui/StyledTab.tsx
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
import React, { Fragment } from "react";
|
||||||
|
import { Tab } from "@headlessui/react";
|
||||||
|
import clsx from "clsx";
|
||||||
|
|
||||||
|
type StyledTabProps = {
|
||||||
|
name: string;
|
||||||
|
icon: (props: React.ComponentProps<"svg">) => JSX.Element;
|
||||||
|
};
|
||||||
|
|
||||||
|
type StyledTabType = React.FC<StyledTabProps> & {
|
||||||
|
List: React.FC<{ children: React.ReactNode }>;
|
||||||
|
Group: typeof Tab.Group;
|
||||||
|
Panels: typeof Tab.Panels;
|
||||||
|
Panel: typeof Tab.Panel;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const StyledTab: StyledTabType = ({ name, icon: Icon }) => {
|
||||||
|
return (
|
||||||
|
<Tab as={Fragment}>
|
||||||
|
{({ selected }) => (
|
||||||
|
<button className="group flex rounded-md focus:outline-none focus-visible:ring-offset-gray-100">
|
||||||
|
<span
|
||||||
|
className={clsx(
|
||||||
|
"p-1 pl-2.5 pr-3.5 rounded-md flex items-center text-sm font-medium",
|
||||||
|
selected && "bg-white shadow-sm ring-1 ring-black ring-opacity-5"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
className={clsx(
|
||||||
|
"-ml-0.5 mr-2 h-4 w-4",
|
||||||
|
selected
|
||||||
|
? "text-slate-500"
|
||||||
|
: "text-gray-400 group-hover:text-gray-900"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
className={clsx(
|
||||||
|
selected
|
||||||
|
? "text-gray-900"
|
||||||
|
: "text-gray-600 group-hover:text-gray-900"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</Tab>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
StyledTab.List = ({ children }) => (
|
||||||
|
<Tab.List className="flex w-fit p-0.5 rounded-md bg-slate-100 hover:bg-slate-200">
|
||||||
|
{children}
|
||||||
|
</Tab.List>
|
||||||
|
);
|
||||||
|
|
||||||
|
StyledTab.Group = Tab.Group;
|
||||||
|
StyledTab.Panels = Tab.Panels;
|
||||||
|
StyledTab.Panel = Tab.Panel;
|
41
packages/components/src/components/ui/Toggle.tsx
Normal file
41
packages/components/src/components/ui/Toggle.tsx
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import clsx from "clsx";
|
||||||
|
import { motion } from "framer-motion";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
type IconType = (props: React.ComponentProps<"svg">) => JSX.Element;
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
status: boolean;
|
||||||
|
onChange: (status: boolean) => void;
|
||||||
|
texts: [string, string];
|
||||||
|
icons: [IconType, IconType];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Toggle: React.FC<Props> = ({
|
||||||
|
texts: [onText, offText],
|
||||||
|
icons: [OnIcon, OffIcon],
|
||||||
|
status,
|
||||||
|
onChange,
|
||||||
|
}) => {
|
||||||
|
const CurrentIcon = status ? OnIcon : OffIcon;
|
||||||
|
return (
|
||||||
|
<motion.button
|
||||||
|
layout
|
||||||
|
transition={{ duration: 0.2 }}
|
||||||
|
className={clsx(
|
||||||
|
"rounded-full py-1 bg-indigo-500 text-white text-xs font-semibold flex items-center space-x-1",
|
||||||
|
status ? "bg-indigo-500" : "bg-gray-400",
|
||||||
|
status ? "pl-1 pr-3" : "pl-3 pr-1",
|
||||||
|
!status && "flex-row-reverse space-x-reverse"
|
||||||
|
)}
|
||||||
|
onClick={() => onChange(!status)}
|
||||||
|
>
|
||||||
|
<motion.div layout transition={{ duration: 0.2 }}>
|
||||||
|
<CurrentIcon className="w-6 h-6" />
|
||||||
|
</motion.div>
|
||||||
|
<motion.span layout transition={{ duration: 0.2 }}>
|
||||||
|
{status ? onText : offText}
|
||||||
|
</motion.span>
|
||||||
|
</motion.button>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,14 +1,6 @@
|
||||||
export { SquiggleChart } from "./components/SquiggleChart";
|
export { SquiggleChart } from "./components/SquiggleChart";
|
||||||
export {
|
export { SquiggleEditor, SquigglePartial } from "./components/SquiggleEditor";
|
||||||
SquiggleEditor,
|
export { SquigglePlayground } from "./components/SquigglePlayground";
|
||||||
SquigglePartial,
|
|
||||||
renderSquiggleEditorToDom,
|
|
||||||
renderSquigglePartialToDom,
|
|
||||||
} from "./components/SquiggleEditor";
|
|
||||||
export {
|
|
||||||
SquigglePlayground,
|
|
||||||
renderSquigglePlaygroundToDom,
|
|
||||||
} from "./components/SquigglePlayground";
|
|
||||||
export { SquiggleContainer } from "./components/SquiggleContainer";
|
export { SquiggleContainer } from "./components/SquiggleContainer";
|
||||||
|
|
||||||
export { mergeBindings } from "@quri/squiggle-lang";
|
export { mergeBindings } from "@quri/squiggle-lang";
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {
|
||||||
run,
|
run,
|
||||||
runPartial,
|
runPartial,
|
||||||
} from "@quri/squiggle-lang";
|
} from "@quri/squiggle-lang";
|
||||||
import { useEffect, useMemo, useRef } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
|
|
||||||
type SquiggleArgs<T extends ReturnType<typeof run | typeof runPartial>> = {
|
type SquiggleArgs<T extends ReturnType<typeof run | typeof runPartial>> = {
|
||||||
code: string;
|
code: string;
|
||||||
|
@ -19,37 +19,18 @@ const useSquiggleAny = <T extends ReturnType<typeof run | typeof runPartial>>(
|
||||||
args: SquiggleArgs<T>,
|
args: SquiggleArgs<T>,
|
||||||
f: (...args: Parameters<typeof run>) => T
|
f: (...args: Parameters<typeof run>) => T
|
||||||
) => {
|
) => {
|
||||||
// We're using observable, where div elements can have a `value` property:
|
|
||||||
// https://observablehq.com/@observablehq/introduction-to-views
|
|
||||||
//
|
|
||||||
// This is here to get the 'viewof' part of:
|
|
||||||
// viewof env = cell('normal(0,1)')
|
|
||||||
// to work
|
|
||||||
const ref = useRef<
|
|
||||||
HTMLDivElement & { value?: Extract<T, { tag: "Ok" }>["value"] }
|
|
||||||
>(null);
|
|
||||||
const result: T = useMemo<T>(
|
const result: T = useMemo<T>(
|
||||||
() => f(args.code, args.bindings, args.environment, args.jsImports),
|
() => f(args.code, args.bindings, args.environment, args.jsImports),
|
||||||
[f, args.code, args.bindings, args.environment, args.jsImports]
|
[f, args.code, args.bindings, args.environment, args.jsImports]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!ref.current) return;
|
|
||||||
ref.current.value = result.tag === "Ok" ? result.value : undefined;
|
|
||||||
|
|
||||||
ref.current.dispatchEvent(new CustomEvent("input"));
|
|
||||||
}, [result]);
|
|
||||||
|
|
||||||
const { onChange } = args;
|
const { onChange } = args;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onChange?.(result.tag === "Ok" ? result.value : undefined);
|
onChange?.(result.tag === "Ok" ? result.value : undefined);
|
||||||
}, [result, onChange]);
|
}, [result, onChange]);
|
||||||
|
|
||||||
return {
|
return result;
|
||||||
result, // squiggleExpression or externalBindings
|
|
||||||
observableRef: ref, // can be passed to outermost <div> if you want to use your component as an observablehq's view
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSquigglePartial = (
|
export const useSquigglePartial = (
|
||||||
|
@ -61,3 +42,23 @@ export const useSquigglePartial = (
|
||||||
export const useSquiggle = (args: SquiggleArgs<ReturnType<typeof run>>) => {
|
export const useSquiggle = (args: SquiggleArgs<ReturnType<typeof run>>) => {
|
||||||
return useSquiggleAny(args, run);
|
return useSquiggleAny(args, run);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type ControlledValueArgs<T> = {
|
||||||
|
value?: T;
|
||||||
|
defaultValue: T;
|
||||||
|
onChange?: (x: T) => void;
|
||||||
|
};
|
||||||
|
export function useMaybeControlledValue<T>(
|
||||||
|
args: ControlledValueArgs<T>
|
||||||
|
): [T, (x: T) => void] {
|
||||||
|
let [uncontrolledValue, setUncontrolledValue] = useState(args.defaultValue);
|
||||||
|
let value = args.value ?? uncontrolledValue;
|
||||||
|
let onChange = (newValue: T) => {
|
||||||
|
if (args.value === undefined) {
|
||||||
|
// uncontrolled mode
|
||||||
|
setUncontrolledValue(newValue);
|
||||||
|
}
|
||||||
|
args.onChange?.(newValue);
|
||||||
|
};
|
||||||
|
return [value, onChange];
|
||||||
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ could be continuous, discrete or mixed.
|
||||||
<Story
|
<Story
|
||||||
name="Continuous Symbolic"
|
name="Continuous Symbolic"
|
||||||
args={{
|
args={{
|
||||||
squiggleString: "normal(5,2)",
|
code: "normal(5,2)",
|
||||||
width,
|
width,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -43,7 +43,7 @@ could be continuous, discrete or mixed.
|
||||||
<Story
|
<Story
|
||||||
name="Continuous Pointset"
|
name="Continuous Pointset"
|
||||||
args={{
|
args={{
|
||||||
squiggleString: "toPointSet(normal(5,2))",
|
code: "toPointSet(normal(5,2))",
|
||||||
width,
|
width,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -57,7 +57,7 @@ could be continuous, discrete or mixed.
|
||||||
<Story
|
<Story
|
||||||
name="Continuous SampleSet"
|
name="Continuous SampleSet"
|
||||||
args={{
|
args={{
|
||||||
squiggleString: "toSampleSet(normal(5,2), 1000)",
|
code: "toSampleSet(normal(5,2), 1000)",
|
||||||
width,
|
width,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -71,7 +71,7 @@ could be continuous, discrete or mixed.
|
||||||
<Story
|
<Story
|
||||||
name="Discrete"
|
name="Discrete"
|
||||||
args={{
|
args={{
|
||||||
squiggleString: "mx(0, 1, 3, 5, 8, 10, [0.1, 0.8, 0.5, 0.3, 0.2, 0.1])",
|
code: "mx(0, 1, 3, 5, 8, 10, [0.1, 0.8, 0.5, 0.3, 0.2, 0.1])",
|
||||||
width,
|
width,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -85,8 +85,7 @@ could be continuous, discrete or mixed.
|
||||||
<Story
|
<Story
|
||||||
name="Mixed"
|
name="Mixed"
|
||||||
args={{
|
args={{
|
||||||
squiggleString:
|
code: "mx(0, 1, 3, 5, 8, normal(8, 1), [0.1, 0.3, 0.4, 0.35, 0.2, 0.8])",
|
||||||
"mx(0, 1, 3, 5, 8, normal(8, 1), [0.1, 0.3, 0.4, 0.35, 0.2, 0.8])",
|
|
||||||
width,
|
width,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -103,7 +102,7 @@ to allow large and small numbers being printed cleanly.
|
||||||
<Story
|
<Story
|
||||||
name="Constant"
|
name="Constant"
|
||||||
args={{
|
args={{
|
||||||
squiggleString: "500000000",
|
code: "500000000",
|
||||||
width,
|
width,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -117,7 +116,7 @@ to allow large and small numbers being printed cleanly.
|
||||||
<Story
|
<Story
|
||||||
name="Array"
|
name="Array"
|
||||||
args={{
|
args={{
|
||||||
squiggleString: "[normal(5,2), normal(10,1), normal(40,2), 400000]",
|
code: "[normal(5,2), normal(10,1), normal(40,2), 400000]",
|
||||||
width,
|
width,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -131,7 +130,7 @@ to allow large and small numbers being printed cleanly.
|
||||||
<Story
|
<Story
|
||||||
name="Error"
|
name="Error"
|
||||||
args={{
|
args={{
|
||||||
squiggleString: "f(x) = normal(",
|
code: "f(x) = normal(",
|
||||||
width,
|
width,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -145,7 +144,7 @@ to allow large and small numbers being printed cleanly.
|
||||||
<Story
|
<Story
|
||||||
name="Boolean"
|
name="Boolean"
|
||||||
args={{
|
args={{
|
||||||
squiggleString: "3 == 3",
|
code: "3 == 3",
|
||||||
width,
|
width,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -159,7 +158,7 @@ to allow large and small numbers being printed cleanly.
|
||||||
<Story
|
<Story
|
||||||
name="Function to Distribution"
|
name="Function to Distribution"
|
||||||
args={{
|
args={{
|
||||||
squiggleString: "foo(t) = normal(t,2)*normal(5,3); foo",
|
code: "foo(t) = normal(t,2)*normal(5,3); foo",
|
||||||
width,
|
width,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -173,7 +172,7 @@ to allow large and small numbers being printed cleanly.
|
||||||
<Story
|
<Story
|
||||||
name="Function to Number"
|
name="Function to Number"
|
||||||
args={{
|
args={{
|
||||||
squiggleString: "foo(t) = t^2; foo",
|
code: "foo(t) = t^2; foo",
|
||||||
width,
|
width,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -187,7 +186,7 @@ to allow large and small numbers being printed cleanly.
|
||||||
<Story
|
<Story
|
||||||
name="Record"
|
name="Record"
|
||||||
args={{
|
args={{
|
||||||
squiggleString: "{foo: 35 to 50, bar: [1,2,3]}",
|
code: "{foo: 35 to 50, bar: [1,2,3]}",
|
||||||
width,
|
width,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -201,7 +200,7 @@ to allow large and small numbers being printed cleanly.
|
||||||
<Story
|
<Story
|
||||||
name="String"
|
name="String"
|
||||||
args={{
|
args={{
|
||||||
squiggleString: '"Lucky day!"',
|
code: '"Lucky day!"',
|
||||||
width,
|
width,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
@ -14,7 +14,20 @@ the distribution.
|
||||||
<Story
|
<Story
|
||||||
name="Normal"
|
name="Normal"
|
||||||
args={{
|
args={{
|
||||||
initialSquiggleString: "normal(5,2)",
|
defaultCode: "normal(5,2)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{Template.bind({})}
|
||||||
|
</Story>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
It's also possible to create a controlled version of the same component
|
||||||
|
|
||||||
|
<Canvas>
|
||||||
|
<Story
|
||||||
|
name="Controlled"
|
||||||
|
args={{
|
||||||
|
code: "normal(5,2)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{Template.bind({})}
|
{Template.bind({})}
|
||||||
|
@ -27,7 +40,7 @@ You can also name variables like so:
|
||||||
<Story
|
<Story
|
||||||
name="Variables"
|
name="Variables"
|
||||||
args={{
|
args={{
|
||||||
initialSquiggleString: "x = 2\nnormal(x,2)",
|
defaultCode: "x = 2\nnormal(x,2)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{Template.bind({})}
|
{Template.bind({})}
|
||||||
|
|
|
@ -15,7 +15,7 @@ instead returns bindings that can be used by further Squiggle Editors.
|
||||||
<Story
|
<Story
|
||||||
name="Standalone"
|
name="Standalone"
|
||||||
args={{
|
args={{
|
||||||
initialSquiggleString: "x = normal(5,2)",
|
defaultCode: "x = normal(5,2)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{Template.bind({})}
|
{Template.bind({})}
|
||||||
|
@ -36,12 +36,12 @@ instead returns bindings that can be used by further Squiggle Editors.
|
||||||
<>
|
<>
|
||||||
<SquigglePartial
|
<SquigglePartial
|
||||||
{...props}
|
{...props}
|
||||||
initialSquiggleString={props.initialPartialString}
|
defaultCode={props.initialPartialString}
|
||||||
onChange={setBindings}
|
onChange={setBindings}
|
||||||
/>
|
/>
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
{...props}
|
{...props}
|
||||||
initialSquiggleString={props.initialEditorString}
|
defaultCode={props.initialEditorString}
|
||||||
bindings={bindings}
|
bindings={bindings}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -14,7 +14,7 @@ including sampling settings, in squiggle.
|
||||||
<Story
|
<Story
|
||||||
name="Normal"
|
name="Normal"
|
||||||
args={{
|
args={{
|
||||||
initialSquiggleString: "normal(5,2)",
|
defaultCode: "normal(5,2)",
|
||||||
height: 800,
|
height: 800,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
@ -77,6 +77,23 @@ describe("(Symbolic) mean", () => {
|
||||||
meanValue->unpackFloat->expect->ExpectJs.toBeFalsy
|
meanValue->unpackFloat->expect->ExpectJs.toBeFalsy
|
||||||
})
|
})
|
||||||
|
|
||||||
|
testAll(
|
||||||
|
"of beta distributions from mean and standard dev",
|
||||||
|
list{(0.39, 0.1), (0.08, 0.1), (0.8, 0.3)},
|
||||||
|
tup => {
|
||||||
|
let (mean, stdev) = tup
|
||||||
|
let betaDistribution = SymbolicDist.Beta.fromMeanAndStdev(mean, stdev)
|
||||||
|
let meanValue =
|
||||||
|
betaDistribution->E.R2.fmap(d =>
|
||||||
|
run(FromDist(ToFloat(#Mean), d->DistributionTypes.Symbolic))
|
||||||
|
)
|
||||||
|
switch meanValue {
|
||||||
|
| Ok(value) => value->unpackFloat->expect->toBeCloseTo(mean)
|
||||||
|
| Error(err) => err->expect->toBe("shouldn't happen")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
testAll(
|
testAll(
|
||||||
"of lognormal distributions",
|
"of lognormal distributions",
|
||||||
list{(2.0, 4.0), (1e-7, 1e-2), (-1e6, 10.0), (1e3, -1e2), (-1e8, -1e4), (1e2, 1e-5)},
|
list{(2.0, 4.0), (1e-7, 1e-2), (-1e6, 10.0), (1e3, -1e2), (-1e8, -1e4), (1e2, 1e-5)},
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
module ErrorValue = Reducer_ErrorValue
|
module ErrorValue = Reducer_ErrorValue
|
||||||
module ExternalExpressionValue = ReducerInterface.ExternalExpressionValue
|
module ExternalExpressionValue = ReducerInterface.ExternalExpressionValue
|
||||||
module InternalExpressionValue = ReducerInterface.InternalExpressionValue
|
module InternalExpressionValue = ReducerInterface.InternalExpressionValue
|
||||||
module Module = Reducer_Category_Module
|
module Module = Reducer_Module
|
||||||
|
|
||||||
let removeDefaultsInternal = (iev: InternalExpressionValue.t) => {
|
let removeDefaultsInternal = (iev: InternalExpressionValue.t) => {
|
||||||
switch iev {
|
switch iev {
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
|
module ExpressionT = Reducer_Expression_T
|
||||||
|
module Module = Reducer_Module
|
||||||
|
module Bindings = Reducer_Module
|
||||||
|
module ErrorValue = Reducer_ErrorValue
|
||||||
|
|
||||||
|
open Jest
|
||||||
|
open Expect
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
// --- Start of Module File
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
module FooImplementation = {
|
||||||
|
// As this is a Rescript module, functions can use other functions in this module
|
||||||
|
// and in other stdLib modules implemented this way.
|
||||||
|
// Embedding function definitions in to switch statements is a bad practice
|
||||||
|
// - to reduce line count or to
|
||||||
|
let fooNumber = 0.0
|
||||||
|
let fooString = "Foo String"
|
||||||
|
let fooBool = true
|
||||||
|
let makeFoo = (a: string, b: string, _environment): string => `I am ${a}-foo and I am ${b}-foo`
|
||||||
|
let makeBar = (a: float, b: float, _environment): string =>
|
||||||
|
`I am ${a->Js.Float.toString}-bar and I am ${b->Js.Float.toString}-bar`
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is a potential for type modules to define lift functions
|
||||||
|
// for their own type to get rid of switch statements.
|
||||||
|
module FooFFI = {
|
||||||
|
let makeFoo: ExpressionT.optionFfiFn = (args: array<InternalExpressionValue.t>, environment) => {
|
||||||
|
switch args {
|
||||||
|
| [IEvString(a), IEvString(b)] => FooImplementation.makeFoo(a, b, environment)->IEvString->Some
|
||||||
|
| _ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let makeBar: ExpressionT.optionFfiFn = (args: array<InternalExpressionValue.t>, environment) =>
|
||||||
|
switch args {
|
||||||
|
| [IEvNumber(a), IEvNumber(b)] => FooImplementation.makeBar(a, b, environment)->IEvString->Some
|
||||||
|
| _ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let fooModule: Module.t =
|
||||||
|
Module.emptyStdLib
|
||||||
|
->Module.defineNumber("fooNumber", FooImplementation.fooNumber)
|
||||||
|
->Module.defineString("fooString", FooImplementation.fooString)
|
||||||
|
->Module.defineBool("fooBool", FooImplementation.fooBool)
|
||||||
|
->Module.defineFunction("makeFoo", FooFFI.makeFoo)
|
||||||
|
->Module.defineFunction("makeBar", FooFFI.makeBar)
|
||||||
|
|
||||||
|
let makeBindings = (prevBindings: Bindings.t): Bindings.t =>
|
||||||
|
prevBindings->Module.defineModule("Foo", fooModule)
|
||||||
|
|
||||||
|
// ----------------------
|
||||||
|
// --- End of Module File
|
||||||
|
// ----------------------
|
||||||
|
|
||||||
|
let stdLibWithFoo = Bindings.emptyBindings->makeBindings
|
||||||
|
let evalWithFoo = sourceCode =>
|
||||||
|
Reducer_Expression.parse(sourceCode)->Belt.Result.flatMap(expr =>
|
||||||
|
Reducer_Expression.reduceExpression(
|
||||||
|
expr,
|
||||||
|
stdLibWithFoo,
|
||||||
|
InternalExpressionValue.defaultEnvironment,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
let evalToStringResultWithFoo = sourceCode =>
|
||||||
|
evalWithFoo(sourceCode)->InternalExpressionValue.toStringResult
|
||||||
|
|
||||||
|
describe("Module", () => {
|
||||||
|
test("fooNumber", () => {
|
||||||
|
let result = evalToStringResultWithFoo("Foo.fooNumber")
|
||||||
|
expect(result)->toEqual("Ok(0)")
|
||||||
|
})
|
||||||
|
test("fooString", () => {
|
||||||
|
let result = evalToStringResultWithFoo("Foo.fooString")
|
||||||
|
expect(result)->toEqual("Ok('Foo String')")
|
||||||
|
})
|
||||||
|
test("fooBool", () => {
|
||||||
|
let result = evalToStringResultWithFoo("Foo.fooBool")
|
||||||
|
expect(result)->toEqual("Ok(true)")
|
||||||
|
})
|
||||||
|
test("fooBool", () => {
|
||||||
|
let result = evalToStringResultWithFoo("Foo.fooBool")
|
||||||
|
expect(result)->toEqual("Ok(true)")
|
||||||
|
})
|
||||||
|
test("makeFoo", () => {
|
||||||
|
let result = evalToStringResultWithFoo("Foo.makeFoo('a', 'b')")
|
||||||
|
expect(result)->toEqual("Ok('I am a-foo and I am b-foo')")
|
||||||
|
})
|
||||||
|
test("makeFoo wrong arguments", () => {
|
||||||
|
let result = evalToStringResultWithFoo("Foo.makeFoo(1, 2)")
|
||||||
|
// Notice the error with types
|
||||||
|
expect(result)->toEqual("Error(Function not found: makeFoo(Number,Number))")
|
||||||
|
})
|
||||||
|
test("makeBar", () => {
|
||||||
|
let result = evalToStringResultWithFoo("Foo.makeBar(1, 2)")
|
||||||
|
expect(result)->toEqual("Ok('I am 1-bar and I am 2-bar')")
|
||||||
|
})
|
||||||
|
})
|
|
@ -8,7 +8,7 @@ module InternalExpressionValue = ReducerInterface.InternalExpressionValue
|
||||||
module ExpressionWithContext = Reducer_ExpressionWithContext
|
module ExpressionWithContext = Reducer_ExpressionWithContext
|
||||||
module Macro = Reducer_Expression_Macro
|
module Macro = Reducer_Expression_Macro
|
||||||
module T = Reducer_Expression_T
|
module T = Reducer_Expression_T
|
||||||
module Module = Reducer_Category_Module
|
module Module = Reducer_Module
|
||||||
|
|
||||||
let testMacro_ = (
|
let testMacro_ = (
|
||||||
tester,
|
tester,
|
||||||
|
|
|
@ -172,6 +172,15 @@ function createTsExport(
|
||||||
return tag("lambdaDeclaration", x.value);
|
return tag("lambdaDeclaration", x.value);
|
||||||
case "EvTypeIdentifier":
|
case "EvTypeIdentifier":
|
||||||
return tag("typeIdentifier", x.value);
|
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":
|
case "EvModule":
|
||||||
let moduleResult: tagged<
|
let moduleResult: tagged<
|
||||||
"module",
|
"module",
|
||||||
|
|
|
@ -129,6 +129,7 @@ export type squiggleExpression =
|
||||||
| tagged<"timeDuration", number>
|
| tagged<"timeDuration", number>
|
||||||
| tagged<"lambdaDeclaration", lambdaDeclaration>
|
| tagged<"lambdaDeclaration", lambdaDeclaration>
|
||||||
| tagged<"record", { [key: string]: squiggleExpression }>
|
| tagged<"record", { [key: string]: squiggleExpression }>
|
||||||
|
| tagged<"type", { [key: string]: squiggleExpression }>
|
||||||
| tagged<"typeIdentifier", string>
|
| tagged<"typeIdentifier", string>
|
||||||
| tagged<"module", { [key: string]: squiggleExpression }>;
|
| tagged<"module", { [key: string]: squiggleExpression }>;
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,26 @@ module Beta = {
|
||||||
let sample = (t: t) => Jstat.Beta.sample(t.alpha, t.beta)
|
let sample = (t: t) => Jstat.Beta.sample(t.alpha, t.beta)
|
||||||
let mean = (t: t) => Ok(Jstat.Beta.mean(t.alpha, t.beta))
|
let mean = (t: t) => Ok(Jstat.Beta.mean(t.alpha, t.beta))
|
||||||
let toString = ({alpha, beta}: t) => j`Beta($alpha,$beta)`
|
let toString = ({alpha, beta}: t) => j`Beta($alpha,$beta)`
|
||||||
|
|
||||||
|
let fromMeanAndSampleSize = (mean, sampleSize) => {
|
||||||
|
// https://en.wikipedia.org/wiki/Beta_distribution#Mean_and_sample_size
|
||||||
|
let alpha = mean *. sampleSize
|
||||||
|
let beta = (1.0 -. mean) *. sampleSize
|
||||||
|
make(alpha, beta)
|
||||||
|
}
|
||||||
|
|
||||||
|
let fromMeanAndStdev = (mean, stdev) => {
|
||||||
|
// https://en.wikipedia.org/wiki/Beta_distribution#Mean_and_variance
|
||||||
|
if !(0.0 < stdev && stdev <= 0.5) {
|
||||||
|
Error("Stdev must be in in between 0 and 0.5.")
|
||||||
|
} else if !(0.0 <= mean && mean <= 1.0) {
|
||||||
|
Error("Mean must be in between 0 and 1.0.")
|
||||||
|
} else {
|
||||||
|
let var = stdev *. stdev
|
||||||
|
let sampleSize = mean *. (1.0 -. mean) /. var -. 1.0
|
||||||
|
fromMeanAndSampleSize(mean, sampleSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module Lognormal = {
|
module Lognormal = {
|
||||||
|
|
|
@ -117,8 +117,12 @@ lognormal({mean: 5, stdev: 2})`,
|
||||||
),
|
),
|
||||||
Function.make(
|
Function.make(
|
||||||
~name="Beta",
|
~name="Beta",
|
||||||
~examples=`beta(20, 25)`,
|
~examples=`beta(20, 25)
|
||||||
~definitions=[TwoArgDist.make("beta", twoArgs(SymbolicDist.Beta.make))],
|
beta({mean: 0.39, stdev: 0.1})`,
|
||||||
|
~definitions=[
|
||||||
|
TwoArgDist.make("beta", twoArgs(SymbolicDist.Beta.make)),
|
||||||
|
TwoArgDist.makeRecordMeanStdev("beta", twoArgs(SymbolicDist.Beta.fromMeanAndStdev)),
|
||||||
|
],
|
||||||
(),
|
(),
|
||||||
),
|
),
|
||||||
Function.make(
|
Function.make(
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
module ExpressionValue = ReducerInterface_InternalExpressionValue
|
|
||||||
module ExpressionT = Reducer_Expression_T
|
|
||||||
open ExpressionValue
|
|
||||||
|
|
||||||
let isOfResolvedType = (aType, aValue) => {
|
|
||||||
let caseTypeIdentifier = (aTypeIdentifier0, aValue) => {
|
|
||||||
let valueType = aValue->valueToValueType->valueTypeToString->Js.String2.toLowerCase
|
|
||||||
let aTypeIdentifier = aTypeIdentifier0->Js.String2.toLowerCase
|
|
||||||
aTypeIdentifier === valueType
|
|
||||||
}
|
|
||||||
|
|
||||||
switch aType {
|
|
||||||
| IEvTypeIdentifier(aTypeIdentifier) => caseTypeIdentifier(aTypeIdentifier, aValue)
|
|
||||||
| _ => false
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,8 +3,9 @@ module ExpressionT = Reducer_Expression_T
|
||||||
module ExternalLibrary = ReducerInterface.ExternalLibrary
|
module ExternalLibrary = ReducerInterface.ExternalLibrary
|
||||||
module Lambda = Reducer_Expression_Lambda
|
module Lambda = Reducer_Expression_Lambda
|
||||||
module MathJs = Reducer_MathJs
|
module MathJs = Reducer_MathJs
|
||||||
module Module = Reducer_Category_Module
|
module Module = Reducer_Module
|
||||||
module Result = Belt.Result
|
module Result = Belt.Result
|
||||||
|
module TypeBuilder = Reducer_Type_TypeBuilder
|
||||||
open ReducerInterface_InternalExpressionValue
|
open ReducerInterface_InternalExpressionValue
|
||||||
open Reducer_ErrorValue
|
open Reducer_ErrorValue
|
||||||
|
|
||||||
|
@ -166,59 +167,6 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let typeModifier_memberOf = (aType, anArray) => {
|
|
||||||
let newRecord = Belt.Map.String.fromArray([
|
|
||||||
("typeTag", IEvString("typeIdentifier")),
|
|
||||||
("typeIdentifier", aType),
|
|
||||||
])
|
|
||||||
newRecord->Belt.Map.String.set("memberOf", anArray)->IEvRecord->Ok
|
|
||||||
}
|
|
||||||
let typeModifier_memberOf_update = (aRecord, anArray) => {
|
|
||||||
aRecord->Belt.Map.String.set("memberOf", anArray)->IEvRecord->Ok
|
|
||||||
}
|
|
||||||
|
|
||||||
let typeModifier_min = (aType, value) => {
|
|
||||||
let newRecord = Belt.Map.String.fromArray([
|
|
||||||
("typeTag", IEvString("typeIdentifier")),
|
|
||||||
("typeIdentifier", aType),
|
|
||||||
])
|
|
||||||
newRecord->Belt.Map.String.set("min", value)->IEvRecord->Ok
|
|
||||||
}
|
|
||||||
let typeModifier_min_update = (aRecord, value) => {
|
|
||||||
aRecord->Belt.Map.String.set("min", value)->IEvRecord->Ok
|
|
||||||
}
|
|
||||||
|
|
||||||
let typeModifier_max = (aType, value) => {
|
|
||||||
let newRecord = Belt.Map.String.fromArray([
|
|
||||||
("typeTag", IEvString("typeIdentifier")),
|
|
||||||
("typeIdentifier", aType),
|
|
||||||
])
|
|
||||||
newRecord->Belt.Map.String.set("max", value)->IEvRecord->Ok
|
|
||||||
}
|
|
||||||
let typeModifier_max_update = (aRecord, value) =>
|
|
||||||
aRecord->Belt.Map.String.set("max", value)->IEvRecord->Ok
|
|
||||||
|
|
||||||
let typeModifier_opaque_update = aRecord =>
|
|
||||||
aRecord->Belt.Map.String.set("opaque", IEvBool(true))->IEvRecord->Ok
|
|
||||||
|
|
||||||
let typeOr = evArray => {
|
|
||||||
let newRecord = Belt.Map.String.fromArray([
|
|
||||||
("typeTag", IEvString("typeOr")),
|
|
||||||
("typeOr", evArray),
|
|
||||||
])
|
|
||||||
newRecord->IEvRecord->Ok
|
|
||||||
}
|
|
||||||
let typeFunction = anArray => {
|
|
||||||
let output = Belt.Array.getUnsafe(anArray, Js.Array2.length(anArray) - 1)
|
|
||||||
let inputs = Js.Array2.slice(anArray, ~start=0, ~end_=-1)
|
|
||||||
let newRecord = Belt.Map.String.fromArray([
|
|
||||||
("typeTag", IEvString("typeFunction")),
|
|
||||||
("inputs", IEvArray(inputs)),
|
|
||||||
("output", output),
|
|
||||||
])
|
|
||||||
newRecord->IEvRecord->Ok
|
|
||||||
}
|
|
||||||
|
|
||||||
switch call {
|
switch call {
|
||||||
| ("$_atIndex_$", [IEvArray(aValueArray), IEvNumber(fIndex)]) => arrayAtIndex(aValueArray, fIndex)
|
| ("$_atIndex_$", [IEvArray(aValueArray), IEvNumber(fIndex)]) => arrayAtIndex(aValueArray, fIndex)
|
||||||
| ("$_atIndex_$", [IEvModule(dict), IEvString(sIndex)]) => moduleAtIndex(dict, sIndex)
|
| ("$_atIndex_$", [IEvModule(dict), IEvString(sIndex)]) => moduleAtIndex(dict, sIndex)
|
||||||
|
@ -233,20 +181,24 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
|
||||||
| ("$_setTypeOfBindings_$", [IEvModule(nameSpace), IEvSymbol(symbol), value]) =>
|
| ("$_setTypeOfBindings_$", [IEvModule(nameSpace), IEvSymbol(symbol), value]) =>
|
||||||
doSetTypeOfBindings(nameSpace, symbol, value)
|
doSetTypeOfBindings(nameSpace, symbol, value)
|
||||||
| ("$_typeModifier_memberOf_$", [IEvTypeIdentifier(typeIdentifier), IEvArray(arr)]) =>
|
| ("$_typeModifier_memberOf_$", [IEvTypeIdentifier(typeIdentifier), IEvArray(arr)]) =>
|
||||||
typeModifier_memberOf(IEvTypeIdentifier(typeIdentifier), IEvArray(arr))
|
TypeBuilder.typeModifier_memberOf(IEvTypeIdentifier(typeIdentifier), IEvArray(arr))
|
||||||
| ("$_typeModifier_memberOf_$", [IEvRecord(typeRecord), IEvArray(arr)]) =>
|
| ("$_typeModifier_memberOf_$", [IEvType(typeRecord), IEvArray(arr)]) =>
|
||||||
typeModifier_memberOf_update(typeRecord, IEvArray(arr))
|
TypeBuilder.typeModifier_memberOf_update(typeRecord, IEvArray(arr))
|
||||||
| ("$_typeModifier_min_$", [IEvTypeIdentifier(typeIdentifier), value]) =>
|
| ("$_typeModifier_min_$", [IEvTypeIdentifier(typeIdentifier), value]) =>
|
||||||
typeModifier_min(IEvTypeIdentifier(typeIdentifier), value)
|
TypeBuilder.typeModifier_min(IEvTypeIdentifier(typeIdentifier), value)
|
||||||
| ("$_typeModifier_min_$", [IEvRecord(typeRecord), value]) =>
|
| ("$_typeModifier_min_$", [IEvType(typeRecord), value]) =>
|
||||||
typeModifier_min_update(typeRecord, value)
|
TypeBuilder.typeModifier_min_update(typeRecord, value)
|
||||||
| ("$_typeModifier_max_$", [IEvTypeIdentifier(typeIdentifier), value]) =>
|
| ("$_typeModifier_max_$", [IEvTypeIdentifier(typeIdentifier), value]) =>
|
||||||
typeModifier_max(IEvTypeIdentifier(typeIdentifier), value)
|
TypeBuilder.typeModifier_max(IEvTypeIdentifier(typeIdentifier), value)
|
||||||
| ("$_typeModifier_max_$", [IEvRecord(typeRecord), value]) =>
|
| ("$_typeModifier_max_$", [IEvType(typeRecord), value]) =>
|
||||||
typeModifier_max_update(typeRecord, value)
|
TypeBuilder.typeModifier_max_update(typeRecord, value)
|
||||||
| ("$_typeModifier_opaque_$", [IEvRecord(typeRecord)]) => typeModifier_opaque_update(typeRecord)
|
| ("$_typeModifier_opaque_$", [IEvType(typeRecord)]) =>
|
||||||
| ("$_typeOr_$", [IEvArray(arr)]) => typeOr(IEvArray(arr))
|
TypeBuilder.typeModifier_opaque_update(typeRecord)
|
||||||
| ("$_typeFunction_$", [IEvArray(arr)]) => typeFunction(arr)
|
| ("$_typeOr_$", [IEvArray(arr)]) => TypeBuilder.typeOr(IEvArray(arr))
|
||||||
|
| ("$_typeFunction_$", [IEvArray(arr)]) => TypeBuilder.typeFunction(arr)
|
||||||
|
| ("$_typeTuple_$", [IEvArray(elems)]) => TypeBuilder.typeTuple(elems)
|
||||||
|
| ("$_typeArray_$", [elem]) => TypeBuilder.typeArray(elem)
|
||||||
|
| ("$_typeRecord_$", [IEvArray(arrayOfPairs)]) => TypeBuilder.typeRecord(arrayOfPairs)
|
||||||
| ("concat", [IEvArray(aValueArray), IEvArray(bValueArray)]) =>
|
| ("concat", [IEvArray(aValueArray), IEvArray(bValueArray)]) =>
|
||||||
doAddArray(aValueArray, bValueArray)
|
doAddArray(aValueArray, bValueArray)
|
||||||
| ("concat", [IEvString(aValueString), IEvString(bValueString)]) =>
|
| ("concat", [IEvString(aValueString), IEvString(bValueString)]) =>
|
||||||
|
|
|
@ -9,7 +9,7 @@ module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
|
||||||
module ExpressionT = Reducer_Expression_T
|
module ExpressionT = Reducer_Expression_T
|
||||||
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
module ExpressionWithContext = Reducer_ExpressionWithContext
|
module ExpressionWithContext = Reducer_ExpressionWithContext
|
||||||
module Module = Reducer_Category_Module
|
module Module = Reducer_Module
|
||||||
module Result = Belt.Result
|
module Result = Belt.Result
|
||||||
open Reducer_Expression_ExpressionBuilder
|
open Reducer_Expression_ExpressionBuilder
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
// There are switch stament cases in the code which are impossible to reach by design.
|
||||||
|
// ImpossibleException is a sign of programming error.
|
||||||
|
exception ImpossibleException
|
|
@ -6,7 +6,7 @@ module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
module Lambda = Reducer_Expression_Lambda
|
module Lambda = Reducer_Expression_Lambda
|
||||||
module Macro = Reducer_Expression_Macro
|
module Macro = Reducer_Expression_Macro
|
||||||
module MathJs = Reducer_MathJs
|
module MathJs = Reducer_MathJs
|
||||||
module Module = Reducer_Category_Module
|
module Module = Reducer_Module
|
||||||
module Result = Belt.Result
|
module Result = Belt.Result
|
||||||
module T = Reducer_Expression_T
|
module T = Reducer_Expression_T
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ module ErrorValue = Reducer_ErrorValue
|
||||||
module ExpressionT = Reducer_Expression_T
|
module ExpressionT = Reducer_Expression_T
|
||||||
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
module Result = Belt.Result
|
module Result = Belt.Result
|
||||||
module Module = Reducer_Category_Module
|
module Module = Reducer_Module
|
||||||
|
|
||||||
type bindings = ExpressionT.bindings
|
type bindings = ExpressionT.bindings
|
||||||
type context = bindings
|
type context = bindings
|
||||||
|
|
|
@ -2,7 +2,7 @@ module ErrorValue = Reducer_ErrorValue
|
||||||
module ExpressionT = Reducer_Expression_T
|
module ExpressionT = Reducer_Expression_T
|
||||||
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
module Result = Belt.Result
|
module Result = Belt.Result
|
||||||
module Module = Reducer_Category_Module
|
module Module = Reducer_Module
|
||||||
|
|
||||||
type errorValue = Reducer_ErrorValue.errorValue
|
type errorValue = Reducer_ErrorValue.errorValue
|
||||||
type expression = ExpressionT.expression
|
type expression = ExpressionT.expression
|
||||||
|
|
|
@ -2,7 +2,7 @@ module BBindingsReplacer = Reducer_Expression_BindingsReplacer
|
||||||
module BErrorValue = Reducer_ErrorValue
|
module BErrorValue = Reducer_ErrorValue
|
||||||
module BExpressionT = Reducer_Expression_T
|
module BExpressionT = Reducer_Expression_T
|
||||||
module BInternalExpressionValue = ReducerInterface_InternalExpressionValue
|
module BInternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
module BModule = Reducer_Category_Module
|
module BModule = Reducer_Module
|
||||||
|
|
||||||
type errorValue = BErrorValue.errorValue
|
type errorValue = BErrorValue.errorValue
|
||||||
type expression = BExpressionT.expression
|
type expression = BExpressionT.expression
|
||||||
|
@ -10,8 +10,6 @@ type expressionOrFFI = BExpressionT.expressionOrFFI
|
||||||
type ffiFn = BExpressionT.ffiFn
|
type ffiFn = BExpressionT.ffiFn
|
||||||
type internalCode = ReducerInterface_InternalExpressionValue.internalCode
|
type internalCode = ReducerInterface_InternalExpressionValue.internalCode
|
||||||
|
|
||||||
external castExpressionToInternalCode: expressionOrFFI => internalCode = "%identity"
|
|
||||||
|
|
||||||
let eArray = anArray => anArray->BInternalExpressionValue.IEvArray->BExpressionT.EValue
|
let eArray = anArray => anArray->BInternalExpressionValue.IEvArray->BExpressionT.EValue
|
||||||
|
|
||||||
let eArrayString = anArray => anArray->BInternalExpressionValue.IEvArrayString->BExpressionT.EValue
|
let eArrayString = anArray => anArray->BInternalExpressionValue.IEvArrayString->BExpressionT.EValue
|
||||||
|
@ -37,17 +35,12 @@ let eLambda = (
|
||||||
BInternalExpressionValue.IEvLambda({
|
BInternalExpressionValue.IEvLambda({
|
||||||
parameters: parameters,
|
parameters: parameters,
|
||||||
context: context,
|
context: context,
|
||||||
body: NotFFI(expr)->castExpressionToInternalCode,
|
body: NotFFI(expr)->BModule.castExpressionToInternalCode,
|
||||||
})->BExpressionT.EValue
|
})->BExpressionT.EValue
|
||||||
}
|
}
|
||||||
|
|
||||||
let eLambdaFFI = (parameters: array<string>, ffiFn: ffiFn) => {
|
let eLambdaFFI = (ffiFn: ffiFn) => {
|
||||||
let context = BModule.emptyModule
|
ffiFn->BModule.eLambdaFFIValue->BExpressionT.EValue
|
||||||
BInternalExpressionValue.IEvLambda({
|
|
||||||
parameters: parameters,
|
|
||||||
context: context,
|
|
||||||
body: FFI(ffiFn)->castExpressionToInternalCode,
|
|
||||||
})->BExpressionT.EValue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let eNumber = aNumber => aNumber->BInternalExpressionValue.IEvNumber->BExpressionT.EValue
|
let eNumber = aNumber => aNumber->BInternalExpressionValue.IEvNumber->BExpressionT.EValue
|
||||||
|
@ -81,6 +74,9 @@ let eBindExpression = (bindingExpr: expression, expression: expression): express
|
||||||
let eBindExpressionDefault = (expression: expression): expression =>
|
let eBindExpressionDefault = (expression: expression): expression =>
|
||||||
eFunction("$$_bindExpression_$$", list{expression})
|
eFunction("$$_bindExpression_$$", list{expression})
|
||||||
|
|
||||||
|
let eTernary = (truth: expression, trueCase: expression, falseCase: expression): expression =>
|
||||||
|
eFunction("$$_ternary_$$", list{truth, trueCase, falseCase})
|
||||||
|
|
||||||
let eIdentifier = (name: string): expression =>
|
let eIdentifier = (name: string): expression =>
|
||||||
name->BInternalExpressionValue.IEvSymbol->BExpressionT.EValue
|
name->BInternalExpressionValue.IEvSymbol->BExpressionT.EValue
|
||||||
|
|
||||||
|
|
|
@ -3,14 +3,13 @@ module ErrorValue = Reducer_ErrorValue
|
||||||
module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
|
module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
|
||||||
module ExpressionT = Reducer_Expression_T
|
module ExpressionT = Reducer_Expression_T
|
||||||
module ExpressionValue = ReducerInterface_InternalExpressionValue
|
module ExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
module Module = Reducer_Category_Module
|
module Module = Reducer_Module
|
||||||
module Result = Belt.Result
|
module Result = Belt.Result
|
||||||
|
|
||||||
type environment = ReducerInterface_InternalExpressionValue.environment
|
type environment = ReducerInterface_InternalExpressionValue.environment
|
||||||
type expression = ExpressionT.expression
|
type expression = ExpressionT.expression
|
||||||
type expressionOrFFI = ExpressionT.expressionOrFFI
|
type expressionOrFFI = ExpressionT.expressionOrFFI
|
||||||
type internalExpressionValue = ReducerInterface_InternalExpressionValue.t
|
type internalExpressionValue = ReducerInterface_InternalExpressionValue.t
|
||||||
// type tmpExternalBindings = ReducerInterface_InternalExpressionValue.tmpExternalBindings
|
|
||||||
type internalCode = ReducerInterface_InternalExpressionValue.internalCode
|
type internalCode = ReducerInterface_InternalExpressionValue.internalCode
|
||||||
|
|
||||||
external castInternalCodeToExpression: internalCode => expressionOrFFI = "%identity"
|
external castInternalCodeToExpression: internalCode => expressionOrFFI = "%identity"
|
||||||
|
@ -19,6 +18,7 @@ let checkArity = (
|
||||||
lambdaValue: ExpressionValue.lambdaValue,
|
lambdaValue: ExpressionValue.lambdaValue,
|
||||||
args: list<internalExpressionValue>,
|
args: list<internalExpressionValue>,
|
||||||
) => {
|
) => {
|
||||||
|
let reallyCheck = {
|
||||||
let argsLength = Belt.List.length(args)
|
let argsLength = Belt.List.length(args)
|
||||||
let parametersLength = Js.Array2.length(lambdaValue.parameters)
|
let parametersLength = Js.Array2.length(lambdaValue.parameters)
|
||||||
if argsLength !== parametersLength {
|
if argsLength !== parametersLength {
|
||||||
|
@ -26,6 +26,12 @@ let checkArity = (
|
||||||
} else {
|
} else {
|
||||||
args->Ok
|
args->Ok
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
let exprOrFFI = castInternalCodeToExpression(lambdaValue.body)
|
||||||
|
switch exprOrFFI {
|
||||||
|
| NotFFI(_) => reallyCheck
|
||||||
|
| FFI(_) => args->Ok
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let checkIfReduced = (args: list<internalExpressionValue>) =>
|
let checkIfReduced = (args: list<internalExpressionValue>) =>
|
||||||
|
|
|
@ -71,6 +71,8 @@ type ffiFn = (
|
||||||
environment,
|
environment,
|
||||||
) => result<internalExpressionValue, Reducer_ErrorValue.errorValue>
|
) => result<internalExpressionValue, Reducer_ErrorValue.errorValue>
|
||||||
|
|
||||||
|
type optionFfiFn = (array<internalExpressionValue>, environment) => option<internalExpressionValue>
|
||||||
|
|
||||||
type expressionOrFFI =
|
type expressionOrFFI =
|
||||||
| NotFFI(expression)
|
| NotFFI(expression)
|
||||||
| FFI(ffiFn)
|
| FFI(ffiFn)
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
module ExpressionT = Reducer_Expression_T
|
module ExpressionT = Reducer_Expression_T
|
||||||
|
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
|
open Reducer_ErrorValue
|
||||||
open ReducerInterface_InternalExpressionValue
|
open ReducerInterface_InternalExpressionValue
|
||||||
|
|
||||||
let expressionValueToString = toString
|
let expressionValueToString = toString
|
||||||
|
|
||||||
type t = ReducerInterface_InternalExpressionValue.nameSpace
|
type t = ReducerInterface_InternalExpressionValue.nameSpace
|
||||||
|
@ -66,7 +69,8 @@ let set = (nameSpace: t, id: string, value): t => {
|
||||||
Belt.Map.String.set(container, id, value)->NameSpace
|
Belt.Map.String.set(container, id, value)->NameSpace
|
||||||
}
|
}
|
||||||
|
|
||||||
let emptyModule: t = NameSpace(Belt.Map.String.empty)
|
let emptyModule: t = NameSpace(emptyMap)
|
||||||
|
let emptyBindings = emptyModule
|
||||||
|
|
||||||
let fromTypeScriptBindings = ReducerInterface_InternalExpressionValue.nameSpaceFromTypeScriptBindings
|
let fromTypeScriptBindings = ReducerInterface_InternalExpressionValue.nameSpaceFromTypeScriptBindings
|
||||||
let toTypeScriptBindings = ReducerInterface_InternalExpressionValue.nameSpaceToTypeScriptBindings
|
let toTypeScriptBindings = ReducerInterface_InternalExpressionValue.nameSpaceToTypeScriptBindings
|
||||||
|
@ -100,13 +104,59 @@ let removeOther = (nameSpace: t, other: t): t => {
|
||||||
})->NameSpace
|
})->NameSpace
|
||||||
}
|
}
|
||||||
|
|
||||||
|
external castExpressionToInternalCode: ExpressionT.expressionOrFFI => internalCode = "%identity"
|
||||||
|
let eLambdaFFIValue = (ffiFn: ExpressionT.ffiFn) => {
|
||||||
|
IEvLambda({
|
||||||
|
parameters: [],
|
||||||
|
context: emptyModule,
|
||||||
|
body: FFI(ffiFn)->castExpressionToInternalCode,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let functionNotFoundError = (call: functionCall) =>
|
||||||
|
REFunctionNotFound(call->functionCallToCallSignature->functionCallSignatureToString)->Error
|
||||||
|
|
||||||
|
let functionNotFoundErrorFFIFn = (functionName: string): ExpressionT.ffiFn => {
|
||||||
|
(args: array<internalExpressionValue>, _environment: environment): result<
|
||||||
|
internalExpressionValue,
|
||||||
|
errorValue,
|
||||||
|
> => {
|
||||||
|
let call = (functionName, args)
|
||||||
|
functionNotFoundError(call)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let convertOptionToFfiFn = (
|
||||||
|
myFunctionName: string,
|
||||||
|
myFunction: ExpressionT.optionFfiFn,
|
||||||
|
): ExpressionT.ffiFn => {
|
||||||
|
(args: array<InternalExpressionValue.t>, environment) => {
|
||||||
|
myFunction(args, environment)
|
||||||
|
->Belt.Option.map(v => v->Ok)
|
||||||
|
->Belt.Option.getWithDefault(functionNotFoundErrorFFIFn(myFunctionName)(args, environment))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -- Module definition
|
// -- Module definition
|
||||||
let define = (nameSpace: t, identifier: string, ev: internalExpressionValue): t => {
|
let define = (nameSpace: t, identifier: string, ev: internalExpressionValue): t => {
|
||||||
let NameSpace(container) = nameSpace
|
let NameSpace(container) = nameSpace
|
||||||
Belt.Map.String.set(container, identifier, ev)->NameSpace // TODO build lambda for polymorphic functions here
|
Belt.Map.String.set(container, identifier, ev)->NameSpace
|
||||||
}
|
}
|
||||||
|
|
||||||
let defineNumber = (nameSpace: t, identifier: string, value: float): t =>
|
let defineNumber = (nameSpace: t, identifier: string, value: float): t =>
|
||||||
nameSpace->define(identifier, IEvNumber(value))
|
nameSpace->define(identifier, IEvNumber(value))
|
||||||
|
|
||||||
|
let defineString = (nameSpace: t, identifier: string, value: string): t =>
|
||||||
|
nameSpace->define(identifier, IEvString(value))
|
||||||
|
|
||||||
|
let defineBool = (nameSpace: t, identifier: string, value: bool): t =>
|
||||||
|
nameSpace->define(identifier, IEvBool(value))
|
||||||
|
|
||||||
let defineModule = (nameSpace: t, identifier: string, value: t): t =>
|
let defineModule = (nameSpace: t, identifier: string, value: t): t =>
|
||||||
nameSpace->define(identifier, toExpressionValue(value))
|
nameSpace->define(identifier, toExpressionValue(value))
|
||||||
|
|
||||||
|
let defineFunction = (nameSpace: t, identifier: string, value: ExpressionT.optionFfiFn): t => {
|
||||||
|
nameSpace->define(identifier, convertOptionToFfiFn(identifier, value)->eLambdaFFIValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
let emptyStdLib: t = emptyModule->defineBool("stdlib", true)
|
|
@ -0,0 +1,14 @@
|
||||||
|
module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
|
||||||
|
module ExpressionT = Reducer_Expression_T
|
||||||
|
|
||||||
|
type expression = ExpressionT.expression
|
||||||
|
|
||||||
|
let defaultCaseFFI = (functionName: string): expression => {
|
||||||
|
ExpressionBuilder.eLambdaFFI(Reducer_Module.functionNotFoundErrorFFIFn(functionName))
|
||||||
|
}
|
||||||
|
|
||||||
|
let addGuard = (
|
||||||
|
guard: expression,
|
||||||
|
expression: expression,
|
||||||
|
previousExpression: expression,
|
||||||
|
): expression => ExpressionBuilder.eTernary(guard, expression, previousExpression)
|
|
@ -154,9 +154,7 @@ unary
|
||||||
unaryOperator "unary operator"
|
unaryOperator "unary operator"
|
||||||
= ('-' / '.-' / '!' )
|
= ('-' / '.-' / '!' )
|
||||||
|
|
||||||
postOperator = indexedValue
|
postOperator
|
||||||
|
|
||||||
indexedValue
|
|
||||||
= collectionElement
|
= collectionElement
|
||||||
/ atom
|
/ atom
|
||||||
|
|
||||||
|
@ -343,11 +341,18 @@ typeModifierExpression = head:basicType tail:(_ '<-' _nl @typeModifier)*
|
||||||
/ modifier:identifier _ noArguments
|
/ modifier:identifier _ noArguments
|
||||||
{ return {modifier: modifier, args: []}; }
|
{ return {modifier: modifier, args: []}; }
|
||||||
|
|
||||||
basicType = typeConstructor / typeArray / typeRecord / typeInParanthesis / typeIdentifier
|
basicType = typeConstructor / typeArray / typeTuple / typeRecord / typeInParanthesis / typeIdentifier
|
||||||
|
|
||||||
typeArray = '[' _nl elem:typeExpression _nl ']'
|
typeArray = '[' _nl elem:typeExpression _nl ']'
|
||||||
{return h.apply('$_typeArray_$', elem)}
|
{return h.apply('$_typeArray_$', elem)}
|
||||||
|
|
||||||
|
typeTuple = '[' _nl elems:array_typeTupleArguments _nl ']'
|
||||||
|
{ return h.apply('$_typeTuple_$', h.constructArray(elems))}
|
||||||
|
|
||||||
|
array_typeTupleArguments
|
||||||
|
= head:typeExpression tail:(_ ',' _nl @typeExpression)*
|
||||||
|
{ return [head, ...tail]; }
|
||||||
|
|
||||||
typeRecord = '{' _nl elems:array_typeRecordArguments _nl '}'
|
typeRecord = '{' _nl elems:array_typeRecordArguments _nl '}'
|
||||||
{ return h.apply('$_typeRecord_$', h.constructRecord(elems)); }
|
{ return h.apply('$_typeRecord_$', h.constructRecord(elems)); }
|
||||||
|
|
||||||
|
@ -375,9 +380,3 @@ typeOfStatement = identifier:identifier _ ':' _nl typeExpression:typeExpression
|
||||||
{ return h.makeFunctionCall('$_typeOf_$', [identifier, typeExpression])}
|
{ return h.makeFunctionCall('$_typeOf_$', [identifier, typeExpression])}
|
||||||
|
|
||||||
typeInParanthesis = '(' _nl typeExpression:typeExpression _nl ')' {return typeExpression}
|
typeInParanthesis = '(' _nl typeExpression:typeExpression _nl ')' {return typeExpression}
|
||||||
|
|
||||||
// TODO: min max example
|
|
||||||
// TODO: Example of foo = {a: 2, b: 5}; type fooKeys = string $ memberOf(foo->keys)
|
|
||||||
// TODO: Example of memberOf( [1,2,3] )
|
|
||||||
// TODO: Example of $
|
|
||||||
// TODO: Cons(a, list) | EmptyList
|
|
||||||
|
|
|
@ -5,7 +5,11 @@ type node = {"type": string}
|
||||||
|
|
||||||
@module("./Reducer_Peggy_GeneratedParser.js") external parse__: string => node = "parse"
|
@module("./Reducer_Peggy_GeneratedParser.js") external parse__: string => node = "parse"
|
||||||
|
|
||||||
let syntaxErrorToLocation: Js.Exn.t => Reducer_ErrorValue.location = error => %raw(`error.location`)
|
type withLocation = {"location": Reducer_ErrorValue.location}
|
||||||
|
external castWithLocation: Js.Exn.t => withLocation = "%identity"
|
||||||
|
|
||||||
|
let syntaxErrorToLocation = (error: Js.Exn.t): Reducer_ErrorValue.location =>
|
||||||
|
castWithLocation(error)["location"]
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
let parse = (expr: string): result<node, errorValue> =>
|
let parse = (expr: string): result<node, errorValue> =>
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
|
open InternalExpressionValue
|
||||||
|
|
||||||
|
type rec iType =
|
||||||
|
| ItTypeIdentifier(string)
|
||||||
|
| ItModifiedType({modifiedType: iType})
|
||||||
|
| ItTypeOr({typeOr: array<iType>})
|
||||||
|
| ItTypeFunction({inputs: array<iType>, output: iType})
|
||||||
|
| ItTypeArray({element: iType})
|
||||||
|
| ItTypeTuple({elements: array<iType>})
|
||||||
|
| ItTypeRecord({properties: Belt.Map.String.t<iType>})
|
||||||
|
|
||||||
|
let rec fromTypeMap = typeMap => {
|
||||||
|
let default = IEvString("")
|
||||||
|
let evTypeTag: InternalExpressionValue.t = Belt.Map.String.getWithDefault(
|
||||||
|
typeMap,
|
||||||
|
"typeTag",
|
||||||
|
default,
|
||||||
|
)
|
||||||
|
let evTypeIdentifier: InternalExpressionValue.t = Belt.Map.String.getWithDefault(
|
||||||
|
typeMap,
|
||||||
|
"typeIdentifier",
|
||||||
|
default,
|
||||||
|
)
|
||||||
|
let evTypeOr: InternalExpressionValue.t = Belt.Map.String.getWithDefault(
|
||||||
|
typeMap,
|
||||||
|
"typeOr",
|
||||||
|
default,
|
||||||
|
)
|
||||||
|
let evInputs: InternalExpressionValue.t = Belt.Map.String.getWithDefault(
|
||||||
|
typeMap,
|
||||||
|
"inputs",
|
||||||
|
default,
|
||||||
|
)
|
||||||
|
let evOutput: InternalExpressionValue.t = Belt.Map.String.getWithDefault(
|
||||||
|
typeMap,
|
||||||
|
"output",
|
||||||
|
default,
|
||||||
|
)
|
||||||
|
let evElement: InternalExpressionValue.t = Belt.Map.String.getWithDefault(
|
||||||
|
typeMap,
|
||||||
|
"element",
|
||||||
|
default,
|
||||||
|
)
|
||||||
|
let evElements: InternalExpressionValue.t = Belt.Map.String.getWithDefault(
|
||||||
|
typeMap,
|
||||||
|
"elements",
|
||||||
|
default,
|
||||||
|
)
|
||||||
|
let evProperties: InternalExpressionValue.t = Belt.Map.String.getWithDefault(
|
||||||
|
typeMap,
|
||||||
|
"properties",
|
||||||
|
default,
|
||||||
|
)
|
||||||
|
//TODO: map type modifiers
|
||||||
|
switch evTypeTag {
|
||||||
|
| IEvString("typeIdentifier") => ItModifiedType({modifiedType: fromIEvValue(evTypeIdentifier)})
|
||||||
|
| IEvString("typeOr") => ItTypeOr({typeOr: fromIEvArray(evTypeOr)})
|
||||||
|
| IEvString("typeFunction") =>
|
||||||
|
ItTypeFunction({inputs: fromIEvArray(evInputs), output: fromIEvValue(evOutput)})
|
||||||
|
| IEvString("typeArray") => ItTypeArray({element: fromIEvValue(evElement)})
|
||||||
|
| IEvString("typeTuple") => ItTypeTuple({elements: fromIEvArray(evElements)})
|
||||||
|
| IEvString("typeRecord") => ItTypeRecord({properties: fromIEvRecord(evProperties)})
|
||||||
|
| _ => raise(Reducer_Exception.ImpossibleException)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
and fromIEvValue = (ievValue: InternalExpressionValue.t) =>
|
||||||
|
switch ievValue {
|
||||||
|
| IEvTypeIdentifier(typeIdentifier) => ItTypeIdentifier({typeIdentifier})
|
||||||
|
| IEvType(typeMap) => fromTypeMap(typeMap)
|
||||||
|
| _ => raise(Reducer_Exception.ImpossibleException)
|
||||||
|
}
|
||||||
|
and fromIEvArray = (ievArray: InternalExpressionValue.t) =>
|
||||||
|
switch ievArray {
|
||||||
|
| IEvArray(array) => array->Belt.Array.map(fromIEvValue)
|
||||||
|
| _ => raise(Reducer_Exception.ImpossibleException)
|
||||||
|
}
|
||||||
|
and fromIEvRecord = (ievRecord: InternalExpressionValue.t) =>
|
||||||
|
switch ievRecord {
|
||||||
|
| IEvRecord(record) => record->Belt.Map.String.map(fromIEvValue)
|
||||||
|
| _ => raise(Reducer_Exception.ImpossibleException)
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
open ReducerInterface_InternalExpressionValue
|
||||||
|
|
||||||
|
let typeModifier_memberOf = (aType, anArray) => {
|
||||||
|
let newRecord = Belt.Map.String.fromArray([
|
||||||
|
("typeTag", IEvString("typeIdentifier")),
|
||||||
|
("typeIdentifier", aType),
|
||||||
|
])
|
||||||
|
newRecord->Belt.Map.String.set("memberOf", anArray)->IEvType->Ok
|
||||||
|
}
|
||||||
|
|
||||||
|
let typeModifier_memberOf_update = (aRecord, anArray) => {
|
||||||
|
aRecord->Belt.Map.String.set("memberOf", anArray)->IEvType->Ok
|
||||||
|
}
|
||||||
|
|
||||||
|
let typeModifier_min = (aType, value) => {
|
||||||
|
let newRecord = Belt.Map.String.fromArray([
|
||||||
|
("typeTag", IEvString("typeIdentifier")),
|
||||||
|
("typeIdentifier", aType),
|
||||||
|
])
|
||||||
|
newRecord->Belt.Map.String.set("min", value)->IEvType->Ok
|
||||||
|
}
|
||||||
|
|
||||||
|
let typeModifier_min_update = (aRecord, value) => {
|
||||||
|
aRecord->Belt.Map.String.set("min", value)->IEvType->Ok
|
||||||
|
}
|
||||||
|
|
||||||
|
let typeModifier_max = (aType, value) => {
|
||||||
|
let newRecord = Belt.Map.String.fromArray([
|
||||||
|
("typeTag", IEvString("typeIdentifier")),
|
||||||
|
("typeIdentifier", aType),
|
||||||
|
])
|
||||||
|
newRecord->Belt.Map.String.set("max", value)->IEvType->Ok
|
||||||
|
}
|
||||||
|
|
||||||
|
let typeModifier_max_update = (aRecord, value) =>
|
||||||
|
aRecord->Belt.Map.String.set("max", value)->IEvType->Ok
|
||||||
|
|
||||||
|
let typeModifier_opaque_update = aRecord =>
|
||||||
|
aRecord->Belt.Map.String.set("opaque", IEvBool(true))->IEvType->Ok
|
||||||
|
|
||||||
|
let typeOr = evArray => {
|
||||||
|
let newRecord = Belt.Map.String.fromArray([("typeTag", IEvString("typeOr")), ("typeOr", evArray)])
|
||||||
|
newRecord->IEvType->Ok
|
||||||
|
}
|
||||||
|
|
||||||
|
let typeFunction = anArray => {
|
||||||
|
let output = Belt.Array.getUnsafe(anArray, Js.Array2.length(anArray) - 1)
|
||||||
|
let inputs = Js.Array2.slice(anArray, ~start=0, ~end_=-1)
|
||||||
|
let newRecord = Belt.Map.String.fromArray([
|
||||||
|
("typeTag", IEvString("typeFunction")),
|
||||||
|
("inputs", IEvArray(inputs)),
|
||||||
|
("output", output),
|
||||||
|
])
|
||||||
|
newRecord->IEvType->Ok
|
||||||
|
}
|
||||||
|
|
||||||
|
let typeArray = element => {
|
||||||
|
let newRecord = Belt.Map.String.fromArray([
|
||||||
|
("typeTag", IEvString("typeTuple")),
|
||||||
|
("element", element),
|
||||||
|
])
|
||||||
|
newRecord->IEvType->Ok
|
||||||
|
}
|
||||||
|
|
||||||
|
let typeTuple = anArray => {
|
||||||
|
let newRecord = Belt.Map.String.fromArray([
|
||||||
|
("typeTag", IEvString("typeArray")),
|
||||||
|
("elements", IEvArray(anArray)),
|
||||||
|
])
|
||||||
|
newRecord->IEvType->Ok
|
||||||
|
}
|
||||||
|
|
||||||
|
let typeRecord = arrayOfPairs => {
|
||||||
|
let newProperties =
|
||||||
|
Belt.Array.map(arrayOfPairs, pairValue =>
|
||||||
|
switch pairValue {
|
||||||
|
| IEvArray([IEvString(key), valueValue]) => (key, valueValue)
|
||||||
|
| _ => ("wrong key type", pairValue->toStringWithType->IEvString)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
->Belt.Map.String.fromArray
|
||||||
|
->IEvRecord
|
||||||
|
let newRecord = Belt.Map.String.fromArray([
|
||||||
|
("typeTag", IEvString("typeRecord")),
|
||||||
|
("properties", newProperties),
|
||||||
|
])
|
||||||
|
newRecord->IEvType->Ok
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
module ExpressionT = Reducer_Expression_T
|
||||||
|
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||||
|
module T = Reducer_Type_T
|
||||||
|
module TypeBuilder = Reducer_Type_TypeBuilder
|
||||||
|
open InternalExpressionValue
|
||||||
|
|
||||||
|
type typeErrorValue =
|
||||||
|
| TypeError(T.iType, InternalExpressionValue.t)
|
||||||
|
| TypeErrorWithPosition(T.iType, InternalExpressionValue.t, int)
|
||||||
|
| TypeErrorWithProperty(T.iType, InternalExpressionValue.t, string)
|
||||||
|
|
||||||
|
let rec isOfResolvedIType = (anIType: T.iType, aValue): result<bool, typeErrorValue> => {
|
||||||
|
let caseTypeIdentifier = (anUpperTypeName, aValue) => {
|
||||||
|
let aTypeName = anUpperTypeName->Js.String2.toLowerCase
|
||||||
|
let valueTypeName = aValue->valueToValueType->valueTypeToString->Js.String2.toLowerCase
|
||||||
|
switch aTypeName === valueTypeName {
|
||||||
|
| true => Ok(true)
|
||||||
|
| false => TypeError(anIType, aValue)->Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let _caseRecord = (anIType, evValue, propertyMap, map) => {
|
||||||
|
Belt.Map.String.reduce(propertyMap, Ok(true), (acc, property, propertyType) => {
|
||||||
|
Belt.Result.flatMap(acc, _ =>
|
||||||
|
switch Belt.Map.String.get(map, property) {
|
||||||
|
| Some(propertyValue) => isOfResolvedIType(propertyType, propertyValue)
|
||||||
|
| None => TypeErrorWithProperty(anIType, evValue, property)->Error
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
let _caseArray = (anIType, evValue, elementType, anArray) => {
|
||||||
|
Belt.Array.reduceWithIndex(anArray, Ok(true), (acc, element, index) => {
|
||||||
|
switch isOfResolvedIType(elementType, element) {
|
||||||
|
| Ok(_) => acc
|
||||||
|
| Error(_) => TypeErrorWithPosition(anIType, evValue, index)->Error
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
switch anIType {
|
||||||
|
| ItTypeIdentifier(name) => caseTypeIdentifier(name, aValue)
|
||||||
|
// TODO: Work in progress. Code is commented to make an a release of other features
|
||||||
|
// | ItModifiedType({modifiedType: anIType}) => raise(Reducer_Exception.ImpossibleException)
|
||||||
|
// | ItTypeOr({typeOr: anITypeArray}) => raise(Reducer_Exception.ImpossibleException)
|
||||||
|
// | ItTypeFunction({inputs: anITypeArray, output: anIType}) =>
|
||||||
|
// raise(Reducer_Exception.ImpossibleException)
|
||||||
|
// | ItTypeArray({element: anIType}) => raise(Reducer_Exception.ImpossibleException)
|
||||||
|
// | ItTypeTuple({elements: anITypeArray}) => raise(Reducer_Exception.ImpossibleException)
|
||||||
|
// | ItTypeRecord({properties: anITypeMap}) => raise(Reducer_Exception.ImpossibleException)
|
||||||
|
| _ => raise(Reducer_Exception.ImpossibleException)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let isOfResolvedType = (aType: InternalExpressionValue.t, aValue): result<bool, typeErrorValue> =>
|
||||||
|
aType->T.fromIEvValue->isOfResolvedIType(aValue)
|
||||||
|
|
||||||
|
// TODO: Work in progress. Code is commented to make an a release of other features
|
||||||
|
// let checkArguments = (
|
||||||
|
// evFunctionType: InternalExpressionValue.t,
|
||||||
|
// args: array<InternalExpressionValue.t>,
|
||||||
|
// ) => {
|
||||||
|
// let functionType = switch evFunctionType {
|
||||||
|
// | IEvRecord(functionType) => functionType
|
||||||
|
// | _ => raise(Reducer_Exception.ImpossibleException)
|
||||||
|
// }
|
||||||
|
// let evInputs = functionType->Belt.Map.String.getWithDefault("inputs", []->IEvArray)
|
||||||
|
// let inputs = switch evInputs {
|
||||||
|
// | IEvArray(inputs) => inputs
|
||||||
|
// | _ => raise(Reducer_Exception.ImpossibleException)
|
||||||
|
// }
|
||||||
|
// let rTupleType = TypeBuilder.typeTuple(inputs)
|
||||||
|
// Belt.Result.flatMap(rTupleType, tuppleType => isOfResolvedType(tuppleType, args->IEvArray))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let compileTypeExpression = (typeExpression: string, bindings: ExpressionT.bindings, reducerFn: ExpressionT.reducerFn) => {
|
||||||
|
// statement = `type compiled=${typeExpression}`
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
//TODO: asGuard
|
|
@ -24,6 +24,7 @@ type rec externalExpressionValue =
|
||||||
| EvDeclaration(lambdaDeclaration)
|
| EvDeclaration(lambdaDeclaration)
|
||||||
| EvTypeIdentifier(string)
|
| EvTypeIdentifier(string)
|
||||||
| EvModule(record)
|
| EvModule(record)
|
||||||
|
| EvType(record)
|
||||||
and record = Js.Dict.t<externalExpressionValue>
|
and record = Js.Dict.t<externalExpressionValue>
|
||||||
and externalBindings = record
|
and externalBindings = record
|
||||||
and lambdaValue = {
|
and lambdaValue = {
|
||||||
|
@ -50,17 +51,18 @@ let rec toString = aValue =>
|
||||||
}
|
}
|
||||||
| EvBool(aBool) => Js.String.make(aBool)
|
| EvBool(aBool) => Js.String.make(aBool)
|
||||||
| EvCall(fName) => `:${fName}`
|
| EvCall(fName) => `:${fName}`
|
||||||
|
| EvDate(date) => DateTime.Date.toString(date)
|
||||||
|
| EvDeclaration(d) => Declaration.toString(d, r => toString(EvLambda(r)))
|
||||||
|
| EvDistribution(dist) => GenericDist.toString(dist)
|
||||||
| EvLambda(lambdaValue) => `lambda(${Js.Array2.toString(lambdaValue.parameters)}=>internal code)`
|
| EvLambda(lambdaValue) => `lambda(${Js.Array2.toString(lambdaValue.parameters)}=>internal code)`
|
||||||
|
| EvModule(m) => `@${m->toStringRecord}`
|
||||||
| EvNumber(aNumber) => Js.String.make(aNumber)
|
| EvNumber(aNumber) => Js.String.make(aNumber)
|
||||||
|
| EvRecord(aRecord) => aRecord->toStringRecord
|
||||||
| EvString(aString) => `'${aString}'`
|
| EvString(aString) => `'${aString}'`
|
||||||
| EvSymbol(aString) => `:${aString}`
|
| EvSymbol(aString) => `:${aString}`
|
||||||
| EvRecord(aRecord) => aRecord->toStringRecord
|
|
||||||
| EvDistribution(dist) => GenericDist.toString(dist)
|
|
||||||
| EvDate(date) => DateTime.Date.toString(date)
|
|
||||||
| EvTimeDuration(t) => DateTime.Duration.toString(t)
|
| EvTimeDuration(t) => DateTime.Duration.toString(t)
|
||||||
| EvDeclaration(d) => Declaration.toString(d, r => toString(EvLambda(r)))
|
| EvType(t) => `type${t->toStringRecord}`
|
||||||
| EvTypeIdentifier(id) => `#${id}`
|
| EvTypeIdentifier(id) => `#${id}`
|
||||||
| EvModule(m) => `@${m->toStringRecord}`
|
|
||||||
}
|
}
|
||||||
and toStringRecord = aRecord => {
|
and toStringRecord = aRecord => {
|
||||||
let pairs =
|
let pairs =
|
||||||
|
@ -88,72 +90,3 @@ type environment = DistributionOperation.env
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
let defaultEnvironment: environment = DistributionOperation.defaultEnv
|
let defaultEnvironment: environment = DistributionOperation.defaultEnv
|
||||||
|
|
||||||
type expressionValueType =
|
|
||||||
| EvtArray
|
|
||||||
| EvtArrayString
|
|
||||||
| EvtBool
|
|
||||||
| EvtCall
|
|
||||||
| EvtDistribution
|
|
||||||
| EvtLambda
|
|
||||||
| EvtNumber
|
|
||||||
| EvtRecord
|
|
||||||
| EvtString
|
|
||||||
| EvtSymbol
|
|
||||||
| EvtDate
|
|
||||||
| EvtTimeDuration
|
|
||||||
| EvtDeclaration
|
|
||||||
| EvtTypeIdentifier
|
|
||||||
| EvtModule
|
|
||||||
|
|
||||||
type functionCallSignature = CallSignature(string, array<expressionValueType>)
|
|
||||||
type functionDefinitionSignature =
|
|
||||||
FunctionDefinitionSignature(functionCallSignature, expressionValueType)
|
|
||||||
|
|
||||||
let valueToValueType = value =>
|
|
||||||
switch value {
|
|
||||||
| EvArray(_) => EvtArray
|
|
||||||
| EvArrayString(_) => EvtArrayString
|
|
||||||
| EvBool(_) => EvtBool
|
|
||||||
| EvCall(_) => EvtCall
|
|
||||||
| EvDistribution(_) => EvtDistribution
|
|
||||||
| EvLambda(_) => EvtLambda
|
|
||||||
| EvNumber(_) => EvtNumber
|
|
||||||
| EvRecord(_) => EvtRecord
|
|
||||||
| EvString(_) => EvtString
|
|
||||||
| EvSymbol(_) => EvtSymbol
|
|
||||||
| EvDate(_) => EvtDate
|
|
||||||
| EvTimeDuration(_) => EvtTimeDuration
|
|
||||||
| EvDeclaration(_) => EvtDeclaration
|
|
||||||
| EvTypeIdentifier(_) => EvtTypeIdentifier
|
|
||||||
| EvModule(_) => EvtModule
|
|
||||||
}
|
|
||||||
|
|
||||||
let functionCallToCallSignature = (functionCall: functionCall): functionCallSignature => {
|
|
||||||
let (fn, args) = functionCall
|
|
||||||
CallSignature(fn, args->Js.Array2.map(valueToValueType))
|
|
||||||
}
|
|
||||||
|
|
||||||
let valueTypeToString = (valueType: expressionValueType): string =>
|
|
||||||
switch valueType {
|
|
||||||
| EvtArray => `Array`
|
|
||||||
| EvtArrayString => `ArrayString`
|
|
||||||
| EvtBool => `Bool`
|
|
||||||
| EvtCall => `Call`
|
|
||||||
| EvtDistribution => `Distribution`
|
|
||||||
| EvtLambda => `Lambda`
|
|
||||||
| EvtNumber => `Number`
|
|
||||||
| EvtRecord => `Record`
|
|
||||||
| EvtString => `String`
|
|
||||||
| EvtSymbol => `Symbol`
|
|
||||||
| EvtDate => `Date`
|
|
||||||
| EvtTimeDuration => `Duration`
|
|
||||||
| EvtDeclaration => `Declaration`
|
|
||||||
| EvtTypeIdentifier => `TypeIdentifier`
|
|
||||||
| EvtModule => `Module`
|
|
||||||
}
|
|
||||||
|
|
||||||
let functionCallSignatureToString = (functionCallSignature: functionCallSignature): string => {
|
|
||||||
let CallSignature(fn, args) = functionCallSignature
|
|
||||||
`${fn}(${args->Js.Array2.map(valueTypeToString)->Js.Array2.toString})`
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,8 +7,8 @@ type environment = ExternalExpressionValue.environment
|
||||||
let defaultEnvironment = ExternalExpressionValue.defaultEnvironment
|
let defaultEnvironment = ExternalExpressionValue.defaultEnvironment
|
||||||
|
|
||||||
type rec t =
|
type rec t =
|
||||||
| IEvArray(array<t>) // FIXME: Convert
|
| IEvArray(array<t>) // FIXME: Convert to MapInt
|
||||||
| IEvArrayString(array<string>) // FIXME: Convert
|
| IEvArrayString(array<string>)
|
||||||
| IEvBool(bool)
|
| IEvBool(bool)
|
||||||
| IEvCall(string) // External function call
|
| IEvCall(string) // External function call
|
||||||
| IEvDate(Js.Date.t)
|
| IEvDate(Js.Date.t)
|
||||||
|
@ -21,6 +21,7 @@ type rec t =
|
||||||
| IEvString(string)
|
| IEvString(string)
|
||||||
| IEvSymbol(string)
|
| IEvSymbol(string)
|
||||||
| IEvTimeDuration(float)
|
| IEvTimeDuration(float)
|
||||||
|
| IEvType(map)
|
||||||
| IEvTypeIdentifier(string)
|
| IEvTypeIdentifier(string)
|
||||||
and map = Belt.Map.String.t<t>
|
and map = Belt.Map.String.t<t>
|
||||||
and nameSpace = NameSpace(Belt.Map.String.t<t>)
|
and nameSpace = NameSpace(Belt.Map.String.t<t>)
|
||||||
|
@ -56,6 +57,7 @@ let rec toString = aValue =>
|
||||||
| IEvRecord(aMap) => aMap->toStringMap
|
| IEvRecord(aMap) => aMap->toStringMap
|
||||||
| IEvString(aString) => `'${aString}'`
|
| IEvString(aString) => `'${aString}'`
|
||||||
| IEvSymbol(aString) => `:${aString}`
|
| IEvSymbol(aString) => `:${aString}`
|
||||||
|
| IEvType(aMap) => aMap->toStringMap
|
||||||
| IEvTimeDuration(t) => DateTime.Duration.toString(t)
|
| IEvTimeDuration(t) => DateTime.Duration.toString(t)
|
||||||
| IEvTypeIdentifier(id) => `#${id}`
|
| IEvTypeIdentifier(id) => `#${id}`
|
||||||
}
|
}
|
||||||
|
@ -78,17 +80,18 @@ let toStringWithType = aValue =>
|
||||||
| IEvArrayString(_) => `ArrayString::${toString(aValue)}`
|
| IEvArrayString(_) => `ArrayString::${toString(aValue)}`
|
||||||
| IEvBool(_) => `Bool::${toString(aValue)}`
|
| IEvBool(_) => `Bool::${toString(aValue)}`
|
||||||
| IEvCall(_) => `Call::${toString(aValue)}`
|
| IEvCall(_) => `Call::${toString(aValue)}`
|
||||||
|
| IEvDate(_) => `Date::${toString(aValue)}`
|
||||||
|
| IEvDeclaration(_) => `Declaration::${toString(aValue)}`
|
||||||
| IEvDistribution(_) => `Distribution::${toString(aValue)}`
|
| IEvDistribution(_) => `Distribution::${toString(aValue)}`
|
||||||
| IEvLambda(_) => `Lambda::${toString(aValue)}`
|
| IEvLambda(_) => `Lambda::${toString(aValue)}`
|
||||||
|
| IEvModule(_) => `Module::${toString(aValue)}`
|
||||||
| IEvNumber(_) => `Number::${toString(aValue)}`
|
| IEvNumber(_) => `Number::${toString(aValue)}`
|
||||||
| IEvRecord(_) => `Record::${toString(aValue)}`
|
| IEvRecord(_) => `Record::${toString(aValue)}`
|
||||||
| IEvString(_) => `String::${toString(aValue)}`
|
| IEvString(_) => `String::${toString(aValue)}`
|
||||||
| IEvSymbol(_) => `Symbol::${toString(aValue)}`
|
| IEvSymbol(_) => `Symbol::${toString(aValue)}`
|
||||||
| IEvDate(_) => `Date::${toString(aValue)}`
|
|
||||||
| IEvTimeDuration(_) => `Date::${toString(aValue)}`
|
| IEvTimeDuration(_) => `Date::${toString(aValue)}`
|
||||||
| IEvDeclaration(_) => `Declaration::${toString(aValue)}`
|
| IEvType(_) => `Type::${toString(aValue)}`
|
||||||
| IEvTypeIdentifier(_) => `TypeIdentifier::${toString(aValue)}`
|
| IEvTypeIdentifier(_) => `TypeIdentifier::${toString(aValue)}`
|
||||||
| IEvModule(_) => `Module::${toString(aValue)}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let argsToString = (args: array<t>): string => {
|
let argsToString = (args: array<t>): string => {
|
||||||
|
@ -120,17 +123,18 @@ type internalExpressionValueType =
|
||||||
| EvtArrayString
|
| EvtArrayString
|
||||||
| EvtBool
|
| EvtBool
|
||||||
| EvtCall
|
| EvtCall
|
||||||
|
| EvtDate
|
||||||
|
| EvtDeclaration
|
||||||
| EvtDistribution
|
| EvtDistribution
|
||||||
| EvtLambda
|
| EvtLambda
|
||||||
|
| EvtModule
|
||||||
| EvtNumber
|
| EvtNumber
|
||||||
| EvtRecord
|
| EvtRecord
|
||||||
| EvtString
|
| EvtString
|
||||||
| EvtSymbol
|
| EvtSymbol
|
||||||
| EvtDate
|
|
||||||
| EvtTimeDuration
|
| EvtTimeDuration
|
||||||
| EvtDeclaration
|
| EvtType
|
||||||
| EvtTypeIdentifier
|
| EvtTypeIdentifier
|
||||||
| EvtModule
|
|
||||||
|
|
||||||
type functionCallSignature = CallSignature(string, array<internalExpressionValueType>)
|
type functionCallSignature = CallSignature(string, array<internalExpressionValueType>)
|
||||||
type functionDefinitionSignature =
|
type functionDefinitionSignature =
|
||||||
|
@ -142,17 +146,18 @@ let valueToValueType = value =>
|
||||||
| IEvArrayString(_) => EvtArrayString
|
| IEvArrayString(_) => EvtArrayString
|
||||||
| IEvBool(_) => EvtBool
|
| IEvBool(_) => EvtBool
|
||||||
| IEvCall(_) => EvtCall
|
| IEvCall(_) => EvtCall
|
||||||
|
| IEvDate(_) => EvtDate
|
||||||
|
| IEvDeclaration(_) => EvtDeclaration
|
||||||
| IEvDistribution(_) => EvtDistribution
|
| IEvDistribution(_) => EvtDistribution
|
||||||
| IEvLambda(_) => EvtLambda
|
| IEvLambda(_) => EvtLambda
|
||||||
|
| IEvModule(_) => EvtModule
|
||||||
| IEvNumber(_) => EvtNumber
|
| IEvNumber(_) => EvtNumber
|
||||||
| IEvRecord(_) => EvtRecord
|
| IEvRecord(_) => EvtRecord
|
||||||
| IEvString(_) => EvtString
|
| IEvString(_) => EvtString
|
||||||
| IEvSymbol(_) => EvtSymbol
|
| IEvSymbol(_) => EvtSymbol
|
||||||
| IEvDate(_) => EvtDate
|
|
||||||
| IEvTimeDuration(_) => EvtTimeDuration
|
| IEvTimeDuration(_) => EvtTimeDuration
|
||||||
| IEvDeclaration(_) => EvtDeclaration
|
| IEvType(_) => EvtType
|
||||||
| IEvTypeIdentifier(_) => EvtTypeIdentifier
|
| IEvTypeIdentifier(_) => EvtTypeIdentifier
|
||||||
| IEvModule(_) => EvtModule
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let functionCallToCallSignature = (functionCall: functionCall): functionCallSignature => {
|
let functionCallToCallSignature = (functionCall: functionCall): functionCallSignature => {
|
||||||
|
@ -166,17 +171,18 @@ let valueTypeToString = (valueType: internalExpressionValueType): string =>
|
||||||
| EvtArrayString => `ArrayString`
|
| EvtArrayString => `ArrayString`
|
||||||
| EvtBool => `Bool`
|
| EvtBool => `Bool`
|
||||||
| EvtCall => `Call`
|
| EvtCall => `Call`
|
||||||
|
| EvtDate => `Date`
|
||||||
|
| EvtDeclaration => `Declaration`
|
||||||
| EvtDistribution => `Distribution`
|
| EvtDistribution => `Distribution`
|
||||||
| EvtLambda => `Lambda`
|
| EvtLambda => `Lambda`
|
||||||
|
| EvtModule => `Module`
|
||||||
| EvtNumber => `Number`
|
| EvtNumber => `Number`
|
||||||
| EvtRecord => `Record`
|
| EvtRecord => `Record`
|
||||||
| EvtString => `String`
|
| EvtString => `String`
|
||||||
| EvtSymbol => `Symbol`
|
| EvtSymbol => `Symbol`
|
||||||
| EvtDate => `Date`
|
|
||||||
| EvtTimeDuration => `Duration`
|
| EvtTimeDuration => `Duration`
|
||||||
| EvtDeclaration => `Declaration`
|
| EvtType => `Type`
|
||||||
| EvtTypeIdentifier => `TypeIdentifier`
|
| EvtTypeIdentifier => `TypeIdentifier`
|
||||||
| EvtModule => `Module`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let functionCallSignatureToString = (functionCallSignature: functionCallSignature): string => {
|
let functionCallSignatureToString = (functionCallSignature: functionCallSignature): string => {
|
||||||
|
@ -190,6 +196,11 @@ let rec toExternal = (iev: t): ExternalExpressionValue.t => {
|
||||||
| IEvArrayString(v) => EvArrayString(v)
|
| IEvArrayString(v) => EvArrayString(v)
|
||||||
| IEvBool(v) => EvBool(v)
|
| IEvBool(v) => EvBool(v)
|
||||||
| IEvCall(v) => EvCall(v)
|
| IEvCall(v) => EvCall(v)
|
||||||
|
| IEvDeclaration(v) => {
|
||||||
|
let fn = lambdaValueToExternal(v.fn)
|
||||||
|
let args = v.args
|
||||||
|
EvDeclaration({fn: fn, args: args})
|
||||||
|
}
|
||||||
| IEvDistribution(v) => EvDistribution(v)
|
| IEvDistribution(v) => EvDistribution(v)
|
||||||
| IEvLambda(v) => EvLambda(lambdaValueToExternal(v))
|
| IEvLambda(v) => EvLambda(lambdaValueToExternal(v))
|
||||||
| IEvNumber(v) => EvNumber(v)
|
| IEvNumber(v) => EvNumber(v)
|
||||||
|
@ -198,11 +209,7 @@ let rec toExternal = (iev: t): ExternalExpressionValue.t => {
|
||||||
| IEvSymbol(v) => EvSymbol(v)
|
| IEvSymbol(v) => EvSymbol(v)
|
||||||
| IEvDate(v) => EvDate(v)
|
| IEvDate(v) => EvDate(v)
|
||||||
| IEvTimeDuration(v) => EvTimeDuration(v)
|
| IEvTimeDuration(v) => EvTimeDuration(v)
|
||||||
| IEvDeclaration(v) => {
|
| IEvType(v) => v->mapToExternal->EvType
|
||||||
let fn = lambdaValueToExternal(v.fn)
|
|
||||||
let args = v.args
|
|
||||||
EvDeclaration({fn: fn, args: args})
|
|
||||||
}
|
|
||||||
| IEvTypeIdentifier(v) => EvTypeIdentifier(v)
|
| IEvTypeIdentifier(v) => EvTypeIdentifier(v)
|
||||||
| IEvModule(v) => v->nameSpaceToTypeScriptBindings->EvModule
|
| IEvModule(v) => v->nameSpaceToTypeScriptBindings->EvModule
|
||||||
}
|
}
|
||||||
|
@ -228,21 +235,22 @@ let rec toInternal = (ev: ExternalExpressionValue.t): t => {
|
||||||
| EvArrayString(v) => IEvArrayString(v)
|
| EvArrayString(v) => IEvArrayString(v)
|
||||||
| EvBool(v) => IEvBool(v)
|
| EvBool(v) => IEvBool(v)
|
||||||
| EvCall(v) => IEvCall(v)
|
| EvCall(v) => IEvCall(v)
|
||||||
| EvDistribution(v) => IEvDistribution(v)
|
|
||||||
| EvLambda(v) => IEvLambda(lambdaValueToInternal(v))
|
|
||||||
| EvNumber(v) => IEvNumber(v)
|
|
||||||
| EvRecord(v) => v->recordToInternal->IEvRecord
|
|
||||||
| EvString(v) => IEvString(v)
|
|
||||||
| EvSymbol(v) => IEvSymbol(v)
|
|
||||||
| EvDate(v) => IEvDate(v)
|
| EvDate(v) => IEvDate(v)
|
||||||
| EvTimeDuration(v) => IEvTimeDuration(v)
|
|
||||||
| EvDeclaration(v) => {
|
| EvDeclaration(v) => {
|
||||||
let fn = lambdaValueToInternal(v.fn)
|
let fn = lambdaValueToInternal(v.fn)
|
||||||
let args = v.args
|
let args = v.args
|
||||||
IEvDeclaration({fn: fn, args: args})
|
IEvDeclaration({fn: fn, args: args})
|
||||||
}
|
}
|
||||||
| EvTypeIdentifier(v) => IEvTypeIdentifier(v)
|
| EvDistribution(v) => IEvDistribution(v)
|
||||||
|
| EvLambda(v) => IEvLambda(lambdaValueToInternal(v))
|
||||||
| EvModule(v) => v->nameSpaceFromTypeScriptBindings->IEvModule
|
| EvModule(v) => v->nameSpaceFromTypeScriptBindings->IEvModule
|
||||||
|
| EvNumber(v) => IEvNumber(v)
|
||||||
|
| EvRecord(v) => v->recordToInternal->IEvRecord
|
||||||
|
| EvString(v) => IEvString(v)
|
||||||
|
| EvSymbol(v) => IEvSymbol(v)
|
||||||
|
| EvTimeDuration(v) => IEvTimeDuration(v)
|
||||||
|
| EvType(v) => v->recordToInternal->IEvType
|
||||||
|
| EvTypeIdentifier(v) => IEvTypeIdentifier(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
and recordToInternal = v =>
|
and recordToInternal = v =>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
module Module = Reducer_Category_Module
|
module Module = Reducer_Module
|
||||||
|
|
||||||
let internalStdLib = Module.emptyModule->SquiggleLibrary_Math.makeBindings
|
let internalStdLib = Module.emptyModule->SquiggleLibrary_Math.makeBindings
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
module Bindings = Reducer_Category_Module
|
module Bindings = Reducer_Module
|
||||||
module Module = Reducer_Category_Module
|
module Module = Reducer_Module
|
||||||
|
|
||||||
let availableNumbers: array<(string, float)> = [
|
let availableNumbers: array<(string, float)> = [
|
||||||
("pi", Js.Math._PI),
|
("pi", Js.Math._PI),
|
||||||
|
|
|
@ -70,12 +70,14 @@ uniform(10, 12);
|
||||||
|
|
||||||
```
|
```
|
||||||
beta: (distribution|number, distribution|number) => distribution
|
beta: (distribution|number, distribution|number) => distribution
|
||||||
|
beta: (dict<{mean: distribution|number, stdev: distribution|number}>) => distribution
|
||||||
```
|
```
|
||||||
|
|
||||||
**Examples**
|
**Examples**
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
beta(20, 25);
|
beta(20, 25);
|
||||||
|
beta({ mean: 0.39, stdev: 0.1 });
|
||||||
```
|
```
|
||||||
|
|
||||||
### cauchy
|
### cauchy
|
||||||
|
|
|
@ -16,7 +16,7 @@ If you take the pointwise mixture of two distributions with very different means
|
||||||
In the following case, the mean of the mixture should be equal to the sum of the means of the parts. These are shown as the first two displayed variables. These variables diverge as the underlying distributions change.
|
In the following case, the mean of the mixture should be equal to the sum of the means of the parts. These are shown as the first two displayed variables. These variables diverge as the underlying distributions change.
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`dist1 = {value: normal(1,1), weight: 1}
|
defaultCode={`dist1 = {value: normal(1,1), weight: 1}
|
||||||
dist2 = {value: normal(100000000000,1), weight: 1}
|
dist2 = {value: normal(100000000000,1), weight: 1}
|
||||||
totalWeight = dist1.weight + dist2.weight
|
totalWeight = dist1.weight + dist2.weight
|
||||||
distMixture = mixture(dist1.value, dist2.value, [dist1.weight, dist2.weight])
|
distMixture = mixture(dist1.value, dist2.value, [dist1.weight, dist2.weight])
|
||||||
|
@ -30,7 +30,7 @@ separateMeansCombined = (mean(dist1.value) * (dist1.weight) + mean(dist2.value)
|
||||||
The means of sample set distributions can vary dramatically, especially as the numbers get high.
|
The means of sample set distributions can vary dramatically, especially as the numbers get high.
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`symbolicDist = 5 to 50333333
|
defaultCode={`symbolicDist = 5 to 50333333
|
||||||
sampleSetDist = toSampleSet(symbolicDist)
|
sampleSetDist = toSampleSet(symbolicDist)
|
||||||
[mean(symbolicDist), mean(sampleSetDist), symbolicDist, sampleSetDist]`}
|
[mean(symbolicDist), mean(sampleSetDist), symbolicDist, sampleSetDist]`}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -22,22 +22,22 @@ If both values are above zero, a `lognormal` distribution is used. If not, a `no
|
||||||
When <code>5 to 10</code> is entered, both numbers are positive, so it
|
When <code>5 to 10</code> is entered, both numbers are positive, so it
|
||||||
generates a lognormal distribution with 5th and 95th percentiles at 5 and
|
generates a lognormal distribution with 5th and 95th percentiles at 5 and
|
||||||
10.
|
10.
|
||||||
<SquiggleEditor initialSquiggleString="5 to 10" />
|
<SquiggleEditor defaultCode="5 to 10" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex3" label="to(5,10)">
|
<TabItem value="ex3" label="to(5,10)">
|
||||||
<code>5 to 10</code> does the same thing as <code>to(5,10)</code>.
|
<code>5 to 10</code> does the same thing as <code>to(5,10)</code>.
|
||||||
<SquiggleEditor initialSquiggleString="to(5,10)" />
|
<SquiggleEditor defaultCode="to(5,10)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex2" label="-5 to 5">
|
<TabItem value="ex2" label="-5 to 5">
|
||||||
When <code>-5 to 5</code> is entered, there's negative values, so it
|
When <code>-5 to 5</code> is entered, there's negative values, so it
|
||||||
generates a normal distribution. This has 5th and 95th percentiles at 5 and
|
generates a normal distribution. This has 5th and 95th percentiles at 5 and
|
||||||
10.
|
10.
|
||||||
<SquiggleEditor initialSquiggleString="-5 to -3" />
|
<SquiggleEditor defaultCode="-5 to -3" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex4" label="1 to 10000">
|
<TabItem value="ex4" label="1 to 10000">
|
||||||
It's very easy to generate distributions with very long tails. If this
|
It's very easy to generate distributions with very long tails. If this
|
||||||
happens, you can click the "log x scale" box to view this using a log scale.
|
happens, you can click the "log x scale" box to view this using a log scale.
|
||||||
<SquiggleEditor initialSquiggleString="1 to 10000" />
|
<SquiggleEditor defaultCode="1 to 10000" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
@ -76,16 +76,16 @@ The `mixture` mixes combines multiple distributions to create a mixture. You can
|
||||||
|
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<TabItem value="ex1" label="Simple" default>
|
<TabItem value="ex1" label="Simple" default>
|
||||||
<SquiggleEditor initialSquiggleString="mixture(1 to 2, 5 to 8, 9 to 10)" />
|
<SquiggleEditor defaultCode="mixture(1 to 2, 5 to 8, 9 to 10)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex2" label="With Weights">
|
<TabItem value="ex2" label="With Weights">
|
||||||
<SquiggleEditor initialSquiggleString="mixture(1 to 2, 5 to 8, 9 to 10, [0.1, 0.1, 0.8])" />
|
<SquiggleEditor defaultCode="mixture(1 to 2, 5 to 8, 9 to 10, [0.1, 0.1, 0.8])" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex3" label="With Continuous and Discrete Inputs">
|
<TabItem value="ex3" label="With Continuous and Discrete Inputs">
|
||||||
<SquiggleEditor initialSquiggleString="mixture(1 to 5, 8 to 10, 1, 3, 20)" />
|
<SquiggleEditor defaultCode="mixture(1 to 5, 8 to 10, 1, 3, 20)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex4" label="Array of Distributions Input">
|
<TabItem value="ex4" label="Array of Distributions Input">
|
||||||
<SquiggleEditor initialSquiggleString="mx([1 to 2, exponential(1)], [1,1])" />
|
<SquiggleEditor defaultCode="mx([1 to 2, exponential(1)], [1,1])" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ The `mixture` mixes combines multiple distributions to create a mixture. You can
|
||||||
In this case, I have a 20% chance of spending 0 time with it. I might estimate my hours with,
|
In this case, I have a 20% chance of spending 0 time with it. I might estimate my hours with,
|
||||||
</p>
|
</p>
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`hours_the_project_will_take = 5 to 20
|
defaultCode={`hours_the_project_will_take = 5 to 20
|
||||||
chance_of_doing_anything = 0.8
|
chance_of_doing_anything = 0.8
|
||||||
mx(hours_the_project_will_take, 0, [chance_of_doing_anything, 1 - chance_of_doing_anything])`}
|
mx(hours_the_project_will_take, 0, [chance_of_doing_anything, 1 - chance_of_doing_anything])`}
|
||||||
/>
|
/>
|
||||||
|
@ -125,7 +125,7 @@ mx(hours_the_project_will_take, 0, [chance_of_doing_anything, 1 - chance_of_doin
|
||||||
very wide, just in case they were dramatically off for some weird reason.
|
very wide, just in case they were dramatically off for some weird reason.
|
||||||
</p>
|
</p>
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`forecast = 3 to 30
|
defaultCode={`forecast = 3 to 30
|
||||||
chance_completely_wrong = 0.05
|
chance_completely_wrong = 0.05
|
||||||
forecast_if_completely_wrong = -100 to 200
|
forecast_if_completely_wrong = -100 to 200
|
||||||
mx(forecast, forecast_if_completely_wrong, [1-chance_completely_wrong, chance_completely_wrong])`}
|
mx(forecast, forecast_if_completely_wrong, [1-chance_completely_wrong, chance_completely_wrong])`}
|
||||||
|
@ -141,10 +141,10 @@ Creates a [normal distribution](https://en.wikipedia.org/wiki/Normal_distributio
|
||||||
|
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<TabItem value="ex1" label="normal(5,1)" default>
|
<TabItem value="ex1" label="normal(5,1)" default>
|
||||||
<SquiggleEditor initialSquiggleString="normal(5, 1)" />
|
<SquiggleEditor defaultCode="normal(5, 1)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex2" label="normal(100000000000, 100000000000)">
|
<TabItem value="ex2" label="normal(100000000000, 100000000000)">
|
||||||
<SquiggleEditor initialSquiggleString="normal(100000000000, 100000000000)" />
|
<SquiggleEditor defaultCode="normal(100000000000, 100000000000)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ Creates a [log-normal distribution](https://en.wikipedia.org/wiki/Log-normal_dis
|
||||||
you take the log of our lognormal distribution. They can be difficult to directly reason about.
|
you take the log of our lognormal distribution. They can be difficult to directly reason about.
|
||||||
Because of this complexity, we recommend typically using the <a href="#to">to</a> syntax instead of estimating `mu` and `sigma` directly.
|
Because of this complexity, we recommend typically using the <a href="#to">to</a> syntax instead of estimating `mu` and `sigma` directly.
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="lognormal(0, 0.7)" />
|
<SquiggleEditor defaultCode="lognormal(0, 0.7)" />
|
||||||
|
|
||||||
### Arguments
|
### Arguments
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ Because of this complexity, we recommend typically using the <a href="#to">to</a
|
||||||
are identical:
|
are identical:
|
||||||
</p>
|
</p>
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`normalMean = 10
|
defaultCode={`normalMean = 10
|
||||||
normalStdDev = 2
|
normalStdDev = 2
|
||||||
logOfLognormal = log(lognormal(normalMean, normalStdDev))
|
logOfLognormal = log(lognormal(normalMean, normalStdDev))
|
||||||
[logOfLognormal, normal(normalMean, normalStdDev)]`}
|
[logOfLognormal, normal(normalMean, normalStdDev)]`}
|
||||||
|
@ -198,7 +198,7 @@ logOfLognormal = log(lognormal(normalMean, normalStdDev))
|
||||||
|
|
||||||
Creates a [uniform distribution](<https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)>) with the given low and high values.
|
Creates a [uniform distribution](<https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)>) with the given low and high values.
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="uniform(3,7)" />
|
<SquiggleEditor defaultCode="uniform(3,7)" />
|
||||||
|
|
||||||
### Arguments
|
### Arguments
|
||||||
|
|
||||||
|
@ -236,19 +236,19 @@ with values at 1 and 2. Therefore, this is the same as `mixture(pointMass(1),poi
|
||||||
|
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<TabItem value="ex1" label="pointMass(3)" default>
|
<TabItem value="ex1" label="pointMass(3)" default>
|
||||||
<SquiggleEditor initialSquiggleString="pointMass(3)" />
|
<SquiggleEditor defaultCode="pointMass(3)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex3" label="mixture(1,3,5)">
|
<TabItem value="ex3" label="mixture(1,3,5)">
|
||||||
<SquiggleEditor initialSquiggleString="mixture(1,3,5)" />
|
<SquiggleEditor defaultCode="mixture(1,3,5)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex2" label="normal(5,2) * 6">
|
<TabItem value="ex2" label="normal(5,2) * 6">
|
||||||
<SquiggleEditor initialSquiggleString="normal(5,2) * 6" />
|
<SquiggleEditor defaultCode="normal(5,2) * 6" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex4" label="dotAdd(normal(5,2), 6)">
|
<TabItem value="ex4" label="dotAdd(normal(5,2), 6)">
|
||||||
<SquiggleEditor initialSquiggleString="dotAdd(normal(5,2), 6)" />
|
<SquiggleEditor defaultCode="dotAdd(normal(5,2), 6)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex5" label="dotMultiply(normal(5,2), 6)">
|
<TabItem value="ex5" label="dotMultiply(normal(5,2), 6)">
|
||||||
<SquiggleEditor initialSquiggleString="dotMultiply(normal(5,2), 6)" />
|
<SquiggleEditor defaultCode="dotMultiply(normal(5,2), 6)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
@ -259,24 +259,31 @@ with values at 1 and 2. Therefore, this is the same as `mixture(pointMass(1),poi
|
||||||
## Beta
|
## Beta
|
||||||
|
|
||||||
`beta(alpha:number, beta:number)`
|
`beta(alpha:number, beta:number)`
|
||||||
|
`beta({mean: number, stdev: number})`
|
||||||
|
|
||||||
Creates a [beta distribution](https://en.wikipedia.org/wiki/Beta_distribution) with the given `alpha` and `beta` values. For a good summary of the beta distribution, see [this explanation](https://stats.stackexchange.com/a/47782) on Stack Overflow.
|
Creates a [beta distribution](https://en.wikipedia.org/wiki/Beta_distribution) with the given `alpha` and `beta` values. For a good summary of the beta distribution, see [this explanation](https://stats.stackexchange.com/a/47782) on Stack Overflow.
|
||||||
|
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<TabItem value="ex1" label="beta(10, 20)" default>
|
<TabItem value="ex1" label="beta(10, 20)" default>
|
||||||
<SquiggleEditor initialSquiggleString="beta(10,20)" />
|
<SquiggleEditor defaultCode="beta(10,20)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex2" label="beta(1000, 1000)">
|
<TabItem value="ex2" label="beta(1000, 1000)">
|
||||||
<SquiggleEditor initialSquiggleString="beta(1000, 2000)" />
|
<SquiggleEditor defaultCode="beta(1000, 2000)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex3" label="beta(1, 10)">
|
<TabItem value="ex3" label="beta(1, 10)">
|
||||||
<SquiggleEditor initialSquiggleString="beta(1, 10)" />
|
<SquiggleEditor defaultCode="beta(1, 10)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex4" label="beta(10, 1)">
|
<TabItem value="ex4" label="beta(10, 1)">
|
||||||
<SquiggleEditor initialSquiggleString="beta(10, 1)" />
|
<SquiggleEditor defaultCode="beta(10, 1)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex5" label="beta(0.8, 0.8)">
|
<TabItem value="ex5" label="beta(0.8, 0.8)">
|
||||||
<SquiggleEditor initialSquiggleString="beta(0.8, 0.8)" />
|
<SquiggleEditor defaultCode="beta(0.8, 0.8)" />
|
||||||
|
</TabItem>
|
||||||
|
<TabItem
|
||||||
|
value="from mean and standard deviation"
|
||||||
|
label="beta({mean: 0.39, stdev: 0.1})"
|
||||||
|
>
|
||||||
|
<SquiggleEditor initialSquiggleString="beta({mean: 0.39, stdev: 0.1})" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
@ -295,16 +302,16 @@ Creates a [beta distribution](https://en.wikipedia.org/wiki/Beta_distribution) w
|
||||||
<summary>Examples</summary>
|
<summary>Examples</summary>
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<TabItem value="ex1" label="beta(0.3, 0.3)" default>
|
<TabItem value="ex1" label="beta(0.3, 0.3)" default>
|
||||||
<SquiggleEditor initialSquiggleString="beta(0.3, 0.3)" />
|
<SquiggleEditor defaultCode="beta(0.3, 0.3)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex2" label="beta(0.5, 0.5)">
|
<TabItem value="ex2" label="beta(0.5, 0.5)">
|
||||||
<SquiggleEditor initialSquiggleString="beta(0.5, 0.5)" />
|
<SquiggleEditor defaultCode="beta(0.5, 0.5)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex3" label="beta(0.8, 0.8)">
|
<TabItem value="ex3" label="beta(0.8, 0.8)">
|
||||||
<SquiggleEditor initialSquiggleString="beta(.8,.8)" />
|
<SquiggleEditor defaultCode="beta(.8,.8)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem value="ex4" label="beta(0.9, 0.9)">
|
<TabItem value="ex4" label="beta(0.9, 0.9)">
|
||||||
<SquiggleEditor initialSquiggleString="beta(.9,.9)" />
|
<SquiggleEditor defaultCode="beta(.9,.9)" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</details>
|
</details>
|
||||||
|
@ -316,7 +323,7 @@ Creates a [beta distribution](https://en.wikipedia.org/wiki/Beta_distribution) w
|
||||||
|
|
||||||
Creates an [exponential distribution](https://en.wikipedia.org/wiki/Exponential_distribution) with the given rate.
|
Creates an [exponential distribution](https://en.wikipedia.org/wiki/Exponential_distribution) with the given rate.
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="exponential(4)" />
|
<SquiggleEditor defaultCode="exponential(4)" />
|
||||||
|
|
||||||
### Arguments
|
### Arguments
|
||||||
|
|
||||||
|
@ -334,7 +341,7 @@ Creates a [triangular distribution](https://en.wikipedia.org/wiki/Triangular_dis
|
||||||
- `mode`: Number greater than `low`
|
- `mode`: Number greater than `low`
|
||||||
- `high`: Number greater than `mode`
|
- `high`: Number greater than `mode`
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="triangular(1, 2, 4)" />
|
<SquiggleEditor defaultCode="triangular(1, 2, 4)" />
|
||||||
|
|
||||||
## FromSamples
|
## FromSamples
|
||||||
|
|
||||||
|
@ -342,7 +349,7 @@ Creates a [triangular distribution](https://en.wikipedia.org/wiki/Triangular_dis
|
||||||
|
|
||||||
Creates a sample set distribution using an array of samples.
|
Creates a sample set distribution using an array of samples.
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="fromSamples([1,2,3,4,6,5,5,5])" />
|
<SquiggleEditor defaultCode="fromSamples([1,2,3,4,6,5,5,5])" />
|
||||||
|
|
||||||
### Arguments
|
### Arguments
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ the value of one random sample chosen from the first distribution and the value
|
||||||
chosen from the second distribution.
|
chosen from the second distribution.
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`dist1 = 1 to 10
|
defaultCode={`dist1 = 1 to 10
|
||||||
dist2 = triangular(1,2,3)
|
dist2 = triangular(1,2,3)
|
||||||
dist1 + dist2`}
|
dist1 + dist2`}
|
||||||
/>
|
/>
|
||||||
|
@ -28,7 +28,7 @@ the distribution of the value of one random sample chosen from the first distrib
|
||||||
the value of one random sample chosen from the second distribution.
|
the value of one random sample chosen from the second distribution.
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`dist1 = 1 to 10
|
defaultCode={`dist1 = 1 to 10
|
||||||
dist2 = triangular(1,2,3)
|
dist2 = triangular(1,2,3)
|
||||||
dist1 - dist2`}
|
dist1 - dist2`}
|
||||||
/>
|
/>
|
||||||
|
@ -40,14 +40,14 @@ the value of one random sample chosen from the first distribution times the valu
|
||||||
chosen from the second distribution.
|
chosen from the second distribution.
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`dist1 = 1 to 10
|
defaultCode={`dist1 = 1 to 10
|
||||||
dist2 = triangular(1,2,3)
|
dist2 = triangular(1,2,3)
|
||||||
dist1 * dist2`}
|
dist1 * dist2`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
We also provide concatenation of two distributions as a syntax sugar for `*`
|
We also provide concatenation of two distributions as a syntax sugar for `*`
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="(0.1 to 1) triangular(1,2,3)" />
|
<SquiggleEditor defaultCode="(0.1 to 1) triangular(1,2,3)" />
|
||||||
|
|
||||||
### Division
|
### Division
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ chosen from the second distribution. If the second distribution has some values
|
||||||
tends to be particularly unstable.
|
tends to be particularly unstable.
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`dist1 = 1 to 10
|
defaultCode={`dist1 = 1 to 10
|
||||||
dist2 = triangular(1,2,3)
|
dist2 = triangular(1,2,3)
|
||||||
dist1 / dist2`}
|
dist1 / dist2`}
|
||||||
/>
|
/>
|
||||||
|
@ -69,12 +69,12 @@ A projection over a contracted x-axis. The exponentiation operation represents t
|
||||||
the exponentiation of the value of one random sample chosen from the first distribution to the power of
|
the exponentiation of the value of one random sample chosen from the first distribution to the power of
|
||||||
the value one random sample chosen from the second distribution.
|
the value one random sample chosen from the second distribution.
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString={`(0.1 to 1) ^ beta(2, 3)`} />
|
<SquiggleEditor defaultCode={`(0.1 to 1) ^ beta(2, 3)`} />
|
||||||
|
|
||||||
### Taking the base `e` exponential
|
### Taking the base `e` exponential
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`dist = triangular(1,2,3)
|
defaultCode={`dist = triangular(1,2,3)
|
||||||
exp(dist)`}
|
exp(dist)`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -83,19 +83,19 @@ exp(dist)`}
|
||||||
A projection over a stretched x-axis.
|
A projection over a stretched x-axis.
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`dist = triangular(1,2,3)
|
defaultCode={`dist = triangular(1,2,3)
|
||||||
log(dist)`}
|
log(dist)`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`dist = beta(1,2)
|
defaultCode={`dist = beta(1,2)
|
||||||
log10(dist)`}
|
log10(dist)`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
Base `x`
|
Base `x`
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`x = 2
|
defaultCode={`x = 2
|
||||||
dist = beta(2,3)
|
dist = beta(2,3)
|
||||||
log(dist, x)`}
|
log(dist, x)`}
|
||||||
/>
|
/>
|
||||||
|
@ -114,7 +114,7 @@ For every point on the x-axis, operate the corresponding points in the y axis of
|
||||||
TODO: this isn't in the new interpreter/parser yet.
|
TODO: this isn't in the new interpreter/parser yet.
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`dist1 = 1 to 10
|
defaultCode={`dist1 = 1 to 10
|
||||||
dist2 = triangular(1,2,3)
|
dist2 = triangular(1,2,3)
|
||||||
dist1 .+ dist2`}
|
dist1 .+ dist2`}
|
||||||
/>
|
/>
|
||||||
|
@ -124,7 +124,7 @@ dist1 .+ dist2`}
|
||||||
TODO: this isn't in the new interpreter/parser yet.
|
TODO: this isn't in the new interpreter/parser yet.
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`dist1 = 1 to 10
|
defaultCode={`dist1 = 1 to 10
|
||||||
dist2 = triangular(1,2,3)
|
dist2 = triangular(1,2,3)
|
||||||
dist1 .- dist2`}
|
dist1 .- dist2`}
|
||||||
/>
|
/>
|
||||||
|
@ -132,7 +132,7 @@ dist1 .- dist2`}
|
||||||
### Pointwise multiplication
|
### Pointwise multiplication
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`dist1 = 1 to 10
|
defaultCode={`dist1 = 1 to 10
|
||||||
dist2 = triangular(1,2,3)
|
dist2 = triangular(1,2,3)
|
||||||
dist1 .* dist2`}
|
dist1 .* dist2`}
|
||||||
/>
|
/>
|
||||||
|
@ -140,7 +140,7 @@ dist1 .* dist2`}
|
||||||
### Pointwise division
|
### Pointwise division
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`dist1 = uniform(0,20)
|
defaultCode={`dist1 = uniform(0,20)
|
||||||
dist2 = normal(10,8)
|
dist2 = normal(10,8)
|
||||||
dist1 ./ dist2`}
|
dist1 ./ dist2`}
|
||||||
/>
|
/>
|
||||||
|
@ -148,7 +148,7 @@ dist1 ./ dist2`}
|
||||||
### Pointwise exponentiation
|
### Pointwise exponentiation
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`dist1 = 1 to 10
|
defaultCode={`dist1 = 1 to 10
|
||||||
dist2 = triangular(1,2,3)
|
dist2 = triangular(1,2,3)
|
||||||
dist1 .^ dist2`}
|
dist1 .^ dist2`}
|
||||||
/>
|
/>
|
||||||
|
@ -160,7 +160,7 @@ dist1 .^ dist2`}
|
||||||
The `pdf(dist, x)` function returns the density of a distribution at the
|
The `pdf(dist, x)` function returns the density of a distribution at the
|
||||||
given point x.
|
given point x.
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="pdf(normal(0,1),0)" />
|
<SquiggleEditor defaultCode="pdf(normal(0,1),0)" />
|
||||||
|
|
||||||
#### Validity
|
#### Validity
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ given point x.
|
||||||
The `cdf(dist, x)` gives the cumulative probability of the distribution
|
The `cdf(dist, x)` gives the cumulative probability of the distribution
|
||||||
or all values lower than x. It is the inverse of `quantile`.
|
or all values lower than x. It is the inverse of `quantile`.
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="cdf(normal(0,1),0)" />
|
<SquiggleEditor defaultCode="cdf(normal(0,1),0)" />
|
||||||
|
|
||||||
#### Validity
|
#### Validity
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ The `quantile(dist, prob)` gives the value x or which the probability for all va
|
||||||
lower than x is equal to prob. It is the inverse of `cdf`. In the literature, it
|
lower than x is equal to prob. It is the inverse of `cdf`. In the literature, it
|
||||||
is also known as the quantiles function.
|
is also known as the quantiles function.
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="quantile(normal(0,1),0.5)" />
|
<SquiggleEditor defaultCode="quantile(normal(0,1),0.5)" />
|
||||||
|
|
||||||
#### Validity
|
#### Validity
|
||||||
|
|
||||||
|
@ -196,29 +196,29 @@ is also known as the quantiles function.
|
||||||
|
|
||||||
The `mean(distribution)` function gives the mean (expected value) of a distribution.
|
The `mean(distribution)` function gives the mean (expected value) of a distribution.
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="mean(normal(5, 10))" />
|
<SquiggleEditor defaultCode="mean(normal(5, 10))" />
|
||||||
|
|
||||||
### Sampling a distribution
|
### Sampling a distribution
|
||||||
|
|
||||||
The `sample(distribution)` samples a given distribution.
|
The `sample(distribution)` samples a given distribution.
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="sample(normal(0, 10))" />
|
<SquiggleEditor defaultCode="sample(normal(0, 10))" />
|
||||||
|
|
||||||
## Converting between distribution formats
|
## Converting between distribution formats
|
||||||
|
|
||||||
Recall the [three formats of distributions](https://develop--squiggle-documentation.netlify.app/docs/Discussions/Three-Types-Of-Distributions). We can force any distribution into `SampleSet` format
|
Recall the [three formats of distributions](https://develop--squiggle-documentation.netlify.app/docs/Discussions/Three-Types-Of-Distributions). We can force any distribution into `SampleSet` format
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="toSampleSet(normal(5, 10))" />
|
<SquiggleEditor defaultCode="toSampleSet(normal(5, 10))" />
|
||||||
|
|
||||||
Or `PointSet` format
|
Or `PointSet` format
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="toPointSet(normal(5, 10))" />
|
<SquiggleEditor defaultCode="toPointSet(normal(5, 10))" />
|
||||||
|
|
||||||
### `toSampleSet` has two signatures
|
### `toSampleSet` has two signatures
|
||||||
|
|
||||||
Above, we saw the unary `toSampleSet`, which uses an internal hardcoded number of samples. If you'd like to provide the number of samples, it has a binary signature as well (floored)
|
Above, we saw the unary `toSampleSet`, which uses an internal hardcoded number of samples. If you'd like to provide the number of samples, it has a binary signature as well (floored)
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="[toSampleSet(0.1 to 1, 100.1), toSampleSet(0.1 to 1, 5000), toSampleSet(0.1 to 1, 20000)]" />
|
<SquiggleEditor defaultCode="[toSampleSet(0.1 to 1, 100.1), toSampleSet(0.1 to 1, 5000), toSampleSet(0.1 to 1, 20000)]" />
|
||||||
|
|
||||||
#### Validity
|
#### Validity
|
||||||
|
|
||||||
|
@ -230,13 +230,13 @@ Some distribution operations (like horizontal shift) return an unnormalized dist
|
||||||
|
|
||||||
We provide a `normalize` function
|
We provide a `normalize` function
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="normalize((0.1 to 1) + triangular(0.1, 1, 10))" />
|
<SquiggleEditor defaultCode="normalize((0.1 to 1) + triangular(0.1, 1, 10))" />
|
||||||
|
|
||||||
#### Validity - Input to `normalize` must be a dist
|
#### Validity - Input to `normalize` must be a dist
|
||||||
|
|
||||||
We provide a predicate `isNormalized`, for when we have simple control flow
|
We provide a predicate `isNormalized`, for when we have simple control flow
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="isNormalized((0.1 to 1) * triangular(0.1, 1, 10))" />
|
<SquiggleEditor defaultCode="isNormalized((0.1 to 1) * triangular(0.1, 1, 10))" />
|
||||||
|
|
||||||
#### Validity
|
#### Validity
|
||||||
|
|
||||||
|
@ -246,7 +246,7 @@ We provide a predicate `isNormalized`, for when we have simple control flow
|
||||||
|
|
||||||
You may like to debug by right clicking your browser and using the _inspect_ functionality on the webpage, and viewing the _console_ tab. Then, wrap your squiggle output with `inspect` to log an internal representation.
|
You may like to debug by right clicking your browser and using the _inspect_ functionality on the webpage, and viewing the _console_ tab. Then, wrap your squiggle output with `inspect` to log an internal representation.
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="inspect(toSampleSet(0.1 to 1, 100))" />
|
<SquiggleEditor defaultCode="inspect(toSampleSet(0.1 to 1, 100))" />
|
||||||
|
|
||||||
Save for a logging side effect, `inspect` does nothing to input and returns it.
|
Save for a logging side effect, `inspect` does nothing to input and returns it.
|
||||||
|
|
||||||
|
@ -254,12 +254,12 @@ Save for a logging side effect, `inspect` does nothing to input and returns it.
|
||||||
|
|
||||||
You can cut off from the left
|
You can cut off from the left
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="truncateLeft(0.1 to 1, 0.5)" />
|
<SquiggleEditor defaultCode="truncateLeft(0.1 to 1, 0.5)" />
|
||||||
|
|
||||||
You can cut off from the right
|
You can cut off from the right
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="truncateRight(0.1 to 1, 0.5)" />
|
<SquiggleEditor defaultCode="truncateRight(0.1 to 1, 0.5)" />
|
||||||
|
|
||||||
You can cut off from both sides
|
You can cut off from both sides
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="truncate(0.1 to 1, 0.5, 1.5)" />
|
<SquiggleEditor defaultCode="truncate(0.1 to 1, 0.5, 1.5)" />
|
||||||
|
|
|
@ -9,22 +9,22 @@ import { SquiggleEditor } from "../../src/components/SquiggleEditor";
|
||||||
|
|
||||||
### Distributions
|
### Distributions
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString={`mixture(1 to 2, 3, [0.3, 0.7])`} />
|
<SquiggleEditor defaultCode={`mixture(1 to 2, 3, [0.3, 0.7])`} />
|
||||||
|
|
||||||
### Numbers
|
### Numbers
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="4.32" />
|
<SquiggleEditor defaultCode="4.32" />
|
||||||
|
|
||||||
### Arrays
|
### Arrays
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`[beta(1,10), 4, isNormalized(toSampleSet(1 to 2))]`}
|
defaultCode={`[beta(1,10), 4, isNormalized(toSampleSet(1 to 2))]`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
### Records
|
### Records
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`d = {dist: triangular(0, 1, 2), weight: 0.25}
|
defaultCode={`d = {dist: triangular(0, 1, 2), weight: 0.25}
|
||||||
d.dist`}
|
d.dist`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ d.dist`}
|
||||||
A statement assigns expressions to names. It looks like `<symbol> = <expression>`
|
A statement assigns expressions to names. It looks like `<symbol> = <expression>`
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`value_of_work = 10 to 70
|
defaultCode={`value_of_work = 10 to 70
|
||||||
5 + value_of_work / 75`}
|
5 + value_of_work / 75`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ A statement assigns expressions to names. It looks like `<symbol> = <expression>
|
||||||
We can define functions
|
We can define functions
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`ozzie_estimate(t) = lognormal(t^(1.1), 0.5)
|
defaultCode={`ozzie_estimate(t) = lognormal(t^(1.1), 0.5)
|
||||||
nuno_estimate(t, m) = mixture(normal(-5, 1), lognormal(m, t / 1.25))
|
nuno_estimate(t, m) = mixture(normal(-5, 1), lognormal(m, t / 1.25))
|
||||||
ozzie_estimate(1) * nuno_estimate(1, 1)`}
|
ozzie_estimate(1) * nuno_estimate(1, 1)`}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -10,7 +10,7 @@ Squiggle is an _estimation language_, and a syntax for _calculating and expressi
|
||||||
- [Gallery](./Discussions/Gallery)
|
- [Gallery](./Discussions/Gallery)
|
||||||
- [Squiggle playground](/playground)
|
- [Squiggle playground](/playground)
|
||||||
- [Language basics](./Guides/Language)
|
- [Language basics](./Guides/Language)
|
||||||
- [Squiggle functions source of truth](./docs/Guides/Functions)
|
- [Squiggle functions source of truth](./Guides/Functions)
|
||||||
- [Known bugs](./Discussions/Bugs)
|
- [Known bugs](./Discussions/Bugs)
|
||||||
- [Original lesswrong sequence](https://www.lesswrong.com/s/rDe8QE5NvXcZYzgZ3)
|
- [Original lesswrong sequence](https://www.lesswrong.com/s/rDe8QE5NvXcZYzgZ3)
|
||||||
- [Author your squiggle models as Observable notebooks](https://observablehq.com/@hazelfire/squiggle)
|
- [Author your squiggle models as Observable notebooks](https://observablehq.com/@hazelfire/squiggle)
|
||||||
|
|
|
@ -37,7 +37,7 @@ function setHashData(data) {
|
||||||
|
|
||||||
export default function PlaygroundPage() {
|
export default function PlaygroundPage() {
|
||||||
const playgroundProps = {
|
const playgroundProps = {
|
||||||
initialSquiggleString: "normal(0,1)",
|
defaultCode: "normal(0,1)",
|
||||||
height: 700,
|
height: 700,
|
||||||
showTypes: true,
|
showTypes: true,
|
||||||
...getHashData(),
|
...getHashData(),
|
||||||
|
|
113
yarn.lock
113
yarn.lock
|
@ -1802,6 +1802,18 @@
|
||||||
url-loader "^4.1.1"
|
url-loader "^4.1.1"
|
||||||
webpack "^5.72.1"
|
webpack "^5.72.1"
|
||||||
|
|
||||||
|
"@emotion/is-prop-valid@^0.8.2":
|
||||||
|
version "0.8.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a"
|
||||||
|
integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==
|
||||||
|
dependencies:
|
||||||
|
"@emotion/memoize" "0.7.4"
|
||||||
|
|
||||||
|
"@emotion/memoize@0.7.4":
|
||||||
|
version "0.7.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb"
|
||||||
|
integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==
|
||||||
|
|
||||||
"@eslint/eslintrc@^1.3.0":
|
"@eslint/eslintrc@^1.3.0":
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f"
|
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f"
|
||||||
|
@ -2237,6 +2249,59 @@
|
||||||
resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b"
|
resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b"
|
||||||
integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==
|
integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==
|
||||||
|
|
||||||
|
"@motionone/animation@^10.10.1":
|
||||||
|
version "10.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@motionone/animation/-/animation-10.10.1.tgz#d3d3ecb11c6d7507a104b080f31b07be9bc7056d"
|
||||||
|
integrity sha512-iX839/Ir5wT7hVX0yCZYjcDhHAOkVR5hIhVBTf37qEUD693uVwrxC2i1BI9vMVPc1rIoFtftYjOtwoO9Oq/aog==
|
||||||
|
dependencies:
|
||||||
|
"@motionone/easing" "^10.9.0"
|
||||||
|
"@motionone/types" "^10.9.0"
|
||||||
|
"@motionone/utils" "^10.9.0"
|
||||||
|
tslib "^2.3.1"
|
||||||
|
|
||||||
|
"@motionone/dom@^10.11.0":
|
||||||
|
version "10.11.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@motionone/dom/-/dom-10.11.0.tgz#dc2e46b0e21044cc9ae89a994cd6725eac09e48b"
|
||||||
|
integrity sha512-ST56HBslkeoeDwqRFWafkD+JT5FEwlHqB2K2KGaQh6wo6zfKQ9xwjQcqgDiBv2gg6s8ycjHAdFS6dnMHQ5hXKw==
|
||||||
|
dependencies:
|
||||||
|
"@motionone/animation" "^10.10.1"
|
||||||
|
"@motionone/generators" "^10.9.0"
|
||||||
|
"@motionone/types" "^10.9.0"
|
||||||
|
"@motionone/utils" "^10.9.0"
|
||||||
|
hey-listen "^1.0.8"
|
||||||
|
tslib "^2.3.1"
|
||||||
|
|
||||||
|
"@motionone/easing@^10.9.0":
|
||||||
|
version "10.9.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@motionone/easing/-/easing-10.9.0.tgz#42910c70dd30e1bbba27a9612ce03bca022d0da7"
|
||||||
|
integrity sha512-FYIr3HlQEb7aE5LOpY6BPQUaPyKeJt6VfGA+npy73+JIGqoVOjbrdZ1ZQxzTXqO76mG3UZvv1+twrDamRQsxFw==
|
||||||
|
dependencies:
|
||||||
|
"@motionone/utils" "^10.9.0"
|
||||||
|
tslib "^2.3.1"
|
||||||
|
|
||||||
|
"@motionone/generators@^10.9.0":
|
||||||
|
version "10.9.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@motionone/generators/-/generators-10.9.0.tgz#46f3e706f45a9566db7e0ce62d677c884813cdaa"
|
||||||
|
integrity sha512-BOkHx4qQswJV+z/6k05qdvRENE4hG606NI5cIPTsLtSuksnRn83utuj/15VTNoFeYHuTdhwzxvIPvlPVayIGTg==
|
||||||
|
dependencies:
|
||||||
|
"@motionone/types" "^10.9.0"
|
||||||
|
"@motionone/utils" "^10.9.0"
|
||||||
|
tslib "^2.3.1"
|
||||||
|
|
||||||
|
"@motionone/types@^10.9.0":
|
||||||
|
version "10.9.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@motionone/types/-/types-10.9.0.tgz#7caa9c1b746dd30bcf6104ce9c82a5a928385da2"
|
||||||
|
integrity sha512-ZcEDfsrS2ym9+vExV7+59avkzEO/PLkNj16uaDvbWhi0Q/vOZ72j2LQTrtDLWVyZRIeUaB/i8DJP017Gj6UYQw==
|
||||||
|
|
||||||
|
"@motionone/utils@^10.9.0":
|
||||||
|
version "10.9.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@motionone/utils/-/utils-10.9.0.tgz#a68fe41fe37e4365b07dfc676f014a0e43b8beb2"
|
||||||
|
integrity sha512-5IgmwQ8TdH1HsQ9d2QZeBCu9+HkqjoYRYItRpmusoyiedPMZaKdU3pr3qFP5nbAj68Ww2sTUxgEZEOF20qJA6w==
|
||||||
|
dependencies:
|
||||||
|
"@motionone/types" "^10.9.0"
|
||||||
|
hey-listen "^1.0.8"
|
||||||
|
tslib "^2.3.1"
|
||||||
|
|
||||||
"@mrmlnc/readdir-enhanced@^2.2.1":
|
"@mrmlnc/readdir-enhanced@^2.2.1":
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
|
resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
|
||||||
|
@ -4316,7 +4381,7 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
|
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
|
||||||
integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
|
integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
|
||||||
|
|
||||||
"@types/react-dom@^18.0.0", "@types/react-dom@^18.0.5":
|
"@types/react-dom@^18.0.0":
|
||||||
version "18.0.5"
|
version "18.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.5.tgz#330b2d472c22f796e5531446939eacef8378444a"
|
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.5.tgz#330b2d472c22f796e5531446939eacef8378444a"
|
||||||
integrity sha512-OWPWTUrY/NIrjsAPkAk1wW9LZeIjSvkXRhclsFO8CZcZGCOg2G0YZy4ft+rOyYxy8B7ui5iZzi9OkDebZ7/QSA==
|
integrity sha512-OWPWTUrY/NIrjsAPkAk1wW9LZeIjSvkXRhclsFO8CZcZGCOg2G0YZy4ft+rOyYxy8B7ui5iZzi9OkDebZ7/QSA==
|
||||||
|
@ -9149,6 +9214,27 @@ fragment-cache@^0.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
map-cache "^0.2.2"
|
map-cache "^0.2.2"
|
||||||
|
|
||||||
|
framer-motion@^6.4.1:
|
||||||
|
version "6.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-6.4.1.tgz#d351a96d80bea5736af4175e6307bc63bb4daed1"
|
||||||
|
integrity sha512-JiVnG3p0mO9yWxjNx3xxJaKP4hTWdm6oIbzfMJZEMtoOahSNoDTRZA/mFPzfVNj2foKwFPOLFv/lw8UUZjyUqA==
|
||||||
|
dependencies:
|
||||||
|
"@motionone/dom" "^10.11.0"
|
||||||
|
framesync "6.0.1"
|
||||||
|
hey-listen "^1.0.8"
|
||||||
|
popmotion "11.0.3"
|
||||||
|
style-value-types "5.0.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
optionalDependencies:
|
||||||
|
"@emotion/is-prop-valid" "^0.8.2"
|
||||||
|
|
||||||
|
framesync@6.0.1:
|
||||||
|
version "6.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/framesync/-/framesync-6.0.1.tgz#5e32fc01f1c42b39c654c35b16440e07a25d6f20"
|
||||||
|
integrity sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
fresh@0.5.2:
|
fresh@0.5.2:
|
||||||
version "0.5.2"
|
version "0.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
||||||
|
@ -9816,6 +9902,11 @@ he@^1.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||||
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
|
||||||
|
|
||||||
|
hey-listen@^1.0.8:
|
||||||
|
version "1.0.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68"
|
||||||
|
integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==
|
||||||
|
|
||||||
highlight.js@^10.4.1, highlight.js@~10.7.0:
|
highlight.js@^10.4.1, highlight.js@~10.7.0:
|
||||||
version "10.7.3"
|
version "10.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531"
|
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531"
|
||||||
|
@ -13390,6 +13481,16 @@ polished@^4.2.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.17.8"
|
"@babel/runtime" "^7.17.8"
|
||||||
|
|
||||||
|
popmotion@11.0.3:
|
||||||
|
version "11.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-11.0.3.tgz#565c5f6590bbcddab7a33a074bb2ba97e24b0cc9"
|
||||||
|
integrity sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==
|
||||||
|
dependencies:
|
||||||
|
framesync "6.0.1"
|
||||||
|
hey-listen "^1.0.8"
|
||||||
|
style-value-types "5.0.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
posix-character-classes@^0.1.0:
|
posix-character-classes@^0.1.0:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
|
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
|
||||||
|
@ -16410,6 +16511,14 @@ style-to-object@0.3.0, style-to-object@^0.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
inline-style-parser "0.1.1"
|
inline-style-parser "0.1.1"
|
||||||
|
|
||||||
|
style-value-types@5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/style-value-types/-/style-value-types-5.0.0.tgz#76c35f0e579843d523187989da866729411fc8ad"
|
||||||
|
integrity sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==
|
||||||
|
dependencies:
|
||||||
|
hey-listen "^1.0.8"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
stylehacks@^5.1.0:
|
stylehacks@^5.1.0:
|
||||||
version "5.1.0"
|
version "5.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.0.tgz#a40066490ca0caca04e96c6b02153ddc39913520"
|
resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.0.tgz#a40066490ca0caca04e96c6b02153ddc39913520"
|
||||||
|
@ -16967,7 +17076,7 @@ tslib@^1.8.1:
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||||
|
|
||||||
tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0:
|
tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0:
|
||||||
version "2.4.0"
|
version "2.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
|
||||||
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
|
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
|
||||||
|
|
Loading…
Reference in New Issue
Block a user