Merge branch 'develop' into Umur-reducer-dev
This commit is contained in:
		
						commit
						2dc204e222
					
				
							
								
								
									
										2
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| 
						 | 
					@ -154,5 +154,7 @@ jobs:
 | 
				
			||||||
        run: cd ../../ && yarn
 | 
					        run: cd ../../ && yarn
 | 
				
			||||||
      - name: Build rescript in squiggle-lang
 | 
					      - name: Build rescript in squiggle-lang
 | 
				
			||||||
        run: cd ../squiggle-lang && yarn build
 | 
					        run: cd ../squiggle-lang && yarn build
 | 
				
			||||||
 | 
					      - name: Build components
 | 
				
			||||||
 | 
					        run: cd ../components && yarn build
 | 
				
			||||||
      - name: Build website assets
 | 
					      - name: Build website assets
 | 
				
			||||||
        run: yarn build
 | 
					        run: yarn build
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "@headlessui/react": "^1.6.4",
 | 
					    "@headlessui/react": "^1.6.4",
 | 
				
			||||||
    "@heroicons/react": "^1.0.6",
 | 
					    "@heroicons/react": "^1.0.6",
 | 
				
			||||||
    "@hookform/resolvers": "^2.8.10",
 | 
					    "@hookform/resolvers": "^2.9.0",
 | 
				
			||||||
    "@quri/squiggle-lang": "^0.2.8",
 | 
					    "@quri/squiggle-lang": "^0.2.8",
 | 
				
			||||||
    "@react-hook/size": "^2.1.2",
 | 
					    "@react-hook/size": "^2.1.2",
 | 
				
			||||||
    "lodash": "^4.17.21",
 | 
					    "lodash": "^4.17.21",
 | 
				
			||||||
| 
						 | 
					@ -22,40 +22,42 @@
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@babel/plugin-proposal-private-property-in-object": "^7.17.12",
 | 
					    "@babel/plugin-proposal-private-property-in-object": "^7.17.12",
 | 
				
			||||||
    "@storybook/addon-actions": "^6.5.6",
 | 
					    "@storybook/addon-actions": "^6.5.7",
 | 
				
			||||||
    "@storybook/addon-essentials": "^6.5.6",
 | 
					    "@storybook/addon-essentials": "^6.5.7",
 | 
				
			||||||
    "@storybook/addon-links": "^6.5.6",
 | 
					    "@storybook/addon-links": "^6.5.7",
 | 
				
			||||||
    "@storybook/builder-webpack5": "^6.5.6",
 | 
					    "@storybook/builder-webpack5": "^6.5.7",
 | 
				
			||||||
    "@storybook/manager-webpack5": "^6.5.6",
 | 
					    "@storybook/manager-webpack5": "^6.5.7",
 | 
				
			||||||
    "@storybook/node-logger": "^6.5.6",
 | 
					    "@storybook/node-logger": "^6.5.6",
 | 
				
			||||||
    "@storybook/preset-create-react-app": "^4.1.1",
 | 
					    "@storybook/preset-create-react-app": "^4.1.2",
 | 
				
			||||||
    "@storybook/react": "^6.5.6",
 | 
					    "@storybook/react": "^6.5.7",
 | 
				
			||||||
    "@tailwindcss/forms": "^0.5.2",
 | 
					    "@tailwindcss/forms": "^0.5.2",
 | 
				
			||||||
    "@testing-library/jest-dom": "^5.16.4",
 | 
					    "@testing-library/jest-dom": "^5.16.4",
 | 
				
			||||||
    "@testing-library/react": "^13.3.0",
 | 
					    "@testing-library/react": "^13.3.0",
 | 
				
			||||||
    "@testing-library/user-event": "^14.2.0",
 | 
					    "@testing-library/user-event": "^14.2.0",
 | 
				
			||||||
    "@types/jest": "^27.5.0",
 | 
					    "@types/jest": "^27.5.0",
 | 
				
			||||||
    "@types/lodash": "^4.14.182",
 | 
					    "@types/lodash": "^4.14.182",
 | 
				
			||||||
    "@types/node": "^17.0.36",
 | 
					    "@types/node": "^17.0.40",
 | 
				
			||||||
    "@types/react": "^18.0.9",
 | 
					    "@types/react": "^18.0.9",
 | 
				
			||||||
    "@types/react-dom": "^18.0.5",
 | 
					    "@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",
 | 
				
			||||||
 | 
					    "mini-css-extract-plugin": "^2.6.0",
 | 
				
			||||||
 | 
					    "postcss-loader": "^7.0.0",
 | 
				
			||||||
    "react-scripts": "^5.0.1",
 | 
					    "react-scripts": "^5.0.1",
 | 
				
			||||||
    "style-loader": "^3.3.1",
 | 
					    "style-loader": "^3.3.1",
 | 
				
			||||||
    "tailwindcss": "^3.0.24",
 | 
					    "tailwindcss": "^3.0.24",
 | 
				
			||||||
    "ts-loader": "^9.3.0",
 | 
					    "ts-loader": "^9.3.0",
 | 
				
			||||||
    "tsconfig-paths-webpack-plugin": "^3.5.2",
 | 
					    "tsconfig-paths-webpack-plugin": "^3.5.2",
 | 
				
			||||||
    "typescript": "^4.7.2",
 | 
					    "typescript": "^4.7.3",
 | 
				
			||||||
    "web-vitals": "^2.1.4",
 | 
					    "web-vitals": "^2.1.4",
 | 
				
			||||||
    "webpack": "^5.72.1",
 | 
					    "webpack": "^5.73.0",
 | 
				
			||||||
    "webpack-cli": "^4.9.2",
 | 
					    "webpack-cli": "^4.9.2",
 | 
				
			||||||
    "webpack-dev-server": "^4.9.0"
 | 
					    "webpack-dev-server": "^4.9.0"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
    "start": "cross-env REACT_APP_FAST_REFRESH=false && start-storybook -p 6006 -s public",
 | 
					    "start": "cross-env REACT_APP_FAST_REFRESH=false && start-storybook -p 6006 -s public",
 | 
				
			||||||
    "build": "tsc -b && build-storybook -s public",
 | 
					    "build": "tsc -b && tailwindcss -i ./src/tailwind.css -o ./dist/main.css && build-storybook -s public",
 | 
				
			||||||
    "bundle": "webpack",
 | 
					    "bundle": "webpack",
 | 
				
			||||||
    "all": "yarn bundle && yarn build",
 | 
					    "all": "yarn bundle && yarn build",
 | 
				
			||||||
    "lint": "prettier --check .",
 | 
					    "lint": "prettier --check .",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										7
									
								
								packages/components/postcss.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								packages/components/postcss.config.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,7 @@
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
					  plugins: {
 | 
				
			||||||
 | 
					    tailwindcss: {},
 | 
				
			||||||
 | 
					    autoprefixer: {},
 | 
				
			||||||
 | 
					    cssnano: {},
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -10,23 +10,32 @@ export const Alert: React.FC<{
 | 
				
			||||||
  backgroundColor: string;
 | 
					  backgroundColor: string;
 | 
				
			||||||
  headingColor: string;
 | 
					  headingColor: string;
 | 
				
			||||||
  bodyColor: string;
 | 
					  bodyColor: string;
 | 
				
			||||||
  icon: React.ReactNode;
 | 
					  icon: (props: React.ComponentProps<"svg">) => JSX.Element;
 | 
				
			||||||
  children: React.ReactNode;
 | 
					  iconColor: string;
 | 
				
			||||||
 | 
					  children?: React.ReactNode;
 | 
				
			||||||
}> = ({
 | 
					}> = ({
 | 
				
			||||||
  heading = "Error",
 | 
					  heading = "Error",
 | 
				
			||||||
  backgroundColor,
 | 
					  backgroundColor,
 | 
				
			||||||
  headingColor,
 | 
					  headingColor,
 | 
				
			||||||
  bodyColor,
 | 
					  bodyColor,
 | 
				
			||||||
  icon,
 | 
					  icon: Icon,
 | 
				
			||||||
 | 
					  iconColor,
 | 
				
			||||||
  children,
 | 
					  children,
 | 
				
			||||||
}) => {
 | 
					}) => {
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className={`rounded-md p-4 ${backgroundColor}`}>
 | 
					    <div className={`rounded-md p-4 ${backgroundColor}`}>
 | 
				
			||||||
      <div className="flex">
 | 
					      <div className="flex">
 | 
				
			||||||
        <div className="flex-shrink-0">{icon}</div>
 | 
					        <Icon
 | 
				
			||||||
 | 
					          className={`h-5 w-5 flex-shrink-0 ${iconColor}`}
 | 
				
			||||||
 | 
					          aria-hidden="true"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
        <div className="ml-3">
 | 
					        <div className="ml-3">
 | 
				
			||||||
          <h3 className={`text-sm font-medium ${headingColor}`}>{heading}</h3>
 | 
					          <header className={`text-sm font-medium ${headingColor}`}>
 | 
				
			||||||
 | 
					            {heading}
 | 
				
			||||||
 | 
					          </header>
 | 
				
			||||||
 | 
					          {children && React.Children.count(children) ? (
 | 
				
			||||||
            <div className={`mt-2 text-sm ${bodyColor}`}>{children}</div>
 | 
					            <div className={`mt-2 text-sm ${bodyColor}`}>{children}</div>
 | 
				
			||||||
 | 
					          ) : null}
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
| 
						 | 
					@ -35,49 +44,42 @@ export const Alert: React.FC<{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ErrorAlert: React.FC<{
 | 
					export const ErrorAlert: React.FC<{
 | 
				
			||||||
  heading: string;
 | 
					  heading: string;
 | 
				
			||||||
  children: React.ReactNode;
 | 
					  children?: React.ReactNode;
 | 
				
			||||||
}> = ({ heading = "Error", children }) => (
 | 
					}> = (props) => (
 | 
				
			||||||
  <Alert
 | 
					  <Alert
 | 
				
			||||||
    heading={heading}
 | 
					    {...props}
 | 
				
			||||||
    children={children}
 | 
					 | 
				
			||||||
    backgroundColor="bg-red-100"
 | 
					    backgroundColor="bg-red-100"
 | 
				
			||||||
    headingColor="text-red-800"
 | 
					    headingColor="text-red-800"
 | 
				
			||||||
    bodyColor="text-red-700"
 | 
					    bodyColor="text-red-700"
 | 
				
			||||||
    icon={<XCircleIcon className="h-5 w-5 text-red-400" aria-hidden="true" />}
 | 
					    icon={XCircleIcon}
 | 
				
			||||||
 | 
					    iconColor="text-red-400"
 | 
				
			||||||
  />
 | 
					  />
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const MessageAlert: React.FC<{
 | 
					export const MessageAlert: React.FC<{
 | 
				
			||||||
  heading: string;
 | 
					  heading: string;
 | 
				
			||||||
  children: React.ReactNode;
 | 
					  children?: React.ReactNode;
 | 
				
			||||||
}> = ({ heading = "Error", children }) => (
 | 
					}> = (props) => (
 | 
				
			||||||
  <Alert
 | 
					  <Alert
 | 
				
			||||||
    heading={heading}
 | 
					    {...props}
 | 
				
			||||||
    children={children}
 | 
					 | 
				
			||||||
    backgroundColor="bg-slate-100"
 | 
					    backgroundColor="bg-slate-100"
 | 
				
			||||||
    headingColor="text-slate-700"
 | 
					    headingColor="text-slate-700"
 | 
				
			||||||
    bodyColor="text-slate-700"
 | 
					    bodyColor="text-slate-700"
 | 
				
			||||||
    icon={
 | 
					    icon={InformationCircleIcon}
 | 
				
			||||||
      <InformationCircleIcon
 | 
					    iconColor="text-slate-400"
 | 
				
			||||||
        className="h-5 w-5 text-slate-400"
 | 
					 | 
				
			||||||
        aria-hidden="true"
 | 
					 | 
				
			||||||
      />
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  />
 | 
					  />
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const SuccessAlert: React.FC<{
 | 
					export const SuccessAlert: React.FC<{
 | 
				
			||||||
  heading: string;
 | 
					  heading: string;
 | 
				
			||||||
  children: React.ReactNode;
 | 
					  children?: React.ReactNode;
 | 
				
			||||||
}> = ({ heading = "Error", children }) => (
 | 
					}> = (props) => (
 | 
				
			||||||
  <Alert
 | 
					  <Alert
 | 
				
			||||||
    heading={heading}
 | 
					    {...props}
 | 
				
			||||||
    children={children}
 | 
					 | 
				
			||||||
    backgroundColor="bg-green-50"
 | 
					    backgroundColor="bg-green-50"
 | 
				
			||||||
    headingColor="text-green-800"
 | 
					    headingColor="text-green-800"
 | 
				
			||||||
    bodyColor="text-green-700"
 | 
					    bodyColor="text-green-700"
 | 
				
			||||||
    icon={
 | 
					    icon={CheckCircleIcon}
 | 
				
			||||||
      <CheckCircleIcon className="h-5 w-5 text-green-400" aria-hidden="true" />
 | 
					    iconColor="text-green-400"
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  />
 | 
					  />
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,13 +14,13 @@ interface CodeEditorProps {
 | 
				
			||||||
  showGutter?: boolean;
 | 
					  showGutter?: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export let CodeEditor: FC<CodeEditorProps> = ({
 | 
					export const CodeEditor: FC<CodeEditorProps> = ({
 | 
				
			||||||
  value,
 | 
					  value,
 | 
				
			||||||
  onChange,
 | 
					  onChange,
 | 
				
			||||||
  oneLine = false,
 | 
					  oneLine = false,
 | 
				
			||||||
  showGutter = false,
 | 
					  showGutter = false,
 | 
				
			||||||
  height,
 | 
					  height,
 | 
				
			||||||
}: CodeEditorProps) => {
 | 
					}) => {
 | 
				
			||||||
  let lineCount = value.split("\n").length;
 | 
					  let lineCount = value.split("\n").length;
 | 
				
			||||||
  let id = _.uniqueId();
 | 
					  let id = _.uniqueId();
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
| 
						 | 
					@ -48,4 +48,3 @@ export let CodeEditor: FC<CodeEditorProps> = ({
 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
export default CodeEditor;
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,4 @@
 | 
				
			||||||
import * as React from "react";
 | 
					import * as React from "react";
 | 
				
			||||||
import _ from "lodash";
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  Distribution,
 | 
					  Distribution,
 | 
				
			||||||
  result,
 | 
					  result,
 | 
				
			||||||
| 
						 | 
					@ -34,16 +33,24 @@ export const DistributionChart: React.FC<DistributionChartProps> = ({
 | 
				
			||||||
  showSummary,
 | 
					  showSummary,
 | 
				
			||||||
  width,
 | 
					  width,
 | 
				
			||||||
  showControls = false,
 | 
					  showControls = false,
 | 
				
			||||||
}: DistributionChartProps) => {
 | 
					}) => {
 | 
				
			||||||
  let [isLogX, setLogX] = React.useState(false);
 | 
					  const [isLogX, setLogX] = React.useState(false);
 | 
				
			||||||
  let [isExpY, setExpY] = React.useState(false);
 | 
					  const [isExpY, setExpY] = React.useState(false);
 | 
				
			||||||
  let shape = distribution.pointSet();
 | 
					  const shape = distribution.pointSet();
 | 
				
			||||||
  const [sized, _] = useSize((size) => {
 | 
					  const [sized] = useSize((size) => {
 | 
				
			||||||
    if (shape.tag === "Ok") {
 | 
					    if (shape.tag === "Error") {
 | 
				
			||||||
      let massBelow0 =
 | 
					      return (
 | 
				
			||||||
 | 
					        <ErrorAlert heading="Distribution Error">
 | 
				
			||||||
 | 
					          {distributionErrorToString(shape.value)}
 | 
				
			||||||
 | 
					        </ErrorAlert>
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const massBelow0 =
 | 
				
			||||||
      shape.value.continuous.some((x) => x.x <= 0) ||
 | 
					      shape.value.continuous.some((x) => x.x <= 0) ||
 | 
				
			||||||
      shape.value.discrete.some((x) => x.x <= 0);
 | 
					      shape.value.discrete.some((x) => x.x <= 0);
 | 
				
			||||||
      let spec = buildVegaSpec(isLogX, isExpY);
 | 
					    const spec = buildVegaSpec(isLogX, isExpY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let widthProp = width ? width : size.width;
 | 
					    let widthProp = width ? width : size.width;
 | 
				
			||||||
    if (widthProp < 20) {
 | 
					    if (widthProp < 20) {
 | 
				
			||||||
      console.warn(
 | 
					      console.warn(
 | 
				
			||||||
| 
						 | 
					@ -52,26 +59,8 @@ export const DistributionChart: React.FC<DistributionChartProps> = ({
 | 
				
			||||||
      widthProp = 20;
 | 
					      widthProp = 20;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Check whether we should disable the checkbox
 | 
					    return (
 | 
				
			||||||
      var logCheckbox = (
 | 
					      <div style={{ width: widthProp }}>
 | 
				
			||||||
        <CheckBox label="Log X scale" value={isLogX} onChange={setLogX} />
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
      if (massBelow0) {
 | 
					 | 
				
			||||||
        logCheckbox = (
 | 
					 | 
				
			||||||
          <CheckBox
 | 
					 | 
				
			||||||
            label="Log X scale"
 | 
					 | 
				
			||||||
            value={isLogX}
 | 
					 | 
				
			||||||
            onChange={setLogX}
 | 
					 | 
				
			||||||
            disabled={true}
 | 
					 | 
				
			||||||
            tooltip={
 | 
					 | 
				
			||||||
              "Your distribution has mass lower than or equal to 0. Log only works on strictly positive values."
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          />
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      var result = (
 | 
					 | 
				
			||||||
        <div style={{ width: widthProp + "px" }}>
 | 
					 | 
				
			||||||
        <Vega
 | 
					        <Vega
 | 
				
			||||||
          spec={spec}
 | 
					          spec={spec}
 | 
				
			||||||
          data={{ con: shape.value.continuous, dis: shape.value.discrete }}
 | 
					          data={{ con: shape.value.continuous, dis: shape.value.discrete }}
 | 
				
			||||||
| 
						 | 
					@ -84,21 +73,24 @@ export const DistributionChart: React.FC<DistributionChartProps> = ({
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        {showControls && (
 | 
					        {showControls && (
 | 
				
			||||||
          <div>
 | 
					          <div>
 | 
				
			||||||
              {logCheckbox}
 | 
					            <CheckBox
 | 
				
			||||||
 | 
					              label="Log X scale"
 | 
				
			||||||
 | 
					              value={isLogX}
 | 
				
			||||||
 | 
					              onChange={setLogX}
 | 
				
			||||||
 | 
					              // Check whether we should disable the checkbox
 | 
				
			||||||
 | 
					              {...(massBelow0
 | 
				
			||||||
 | 
					                ? {
 | 
				
			||||||
 | 
					                    disabled: true,
 | 
				
			||||||
 | 
					                    tooltip:
 | 
				
			||||||
 | 
					                      "Your distribution has mass lower than or equal to 0. Log only works on strictly positive values.",
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                : {})}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
            <CheckBox label="Exp Y scale" value={isExpY} onChange={setExpY} />
 | 
					            <CheckBox label="Exp Y scale" value={isExpY} onChange={setExpY} />
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        )}
 | 
					        )}
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      var result = (
 | 
					 | 
				
			||||||
        <ErrorAlert heading="Distribution Error">
 | 
					 | 
				
			||||||
          {distributionErrorToString(shape.value)}
 | 
					 | 
				
			||||||
        </ErrorAlert>
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return result;
 | 
					 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  return sized;
 | 
					  return sized;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -121,13 +113,13 @@ interface CheckBoxProps {
 | 
				
			||||||
  tooltip?: string;
 | 
					  tooltip?: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const CheckBox = ({
 | 
					export const CheckBox: React.FC<CheckBoxProps> = ({
 | 
				
			||||||
  label,
 | 
					  label,
 | 
				
			||||||
  onChange,
 | 
					  onChange,
 | 
				
			||||||
  value,
 | 
					  value,
 | 
				
			||||||
  disabled = false,
 | 
					  disabled = false,
 | 
				
			||||||
  tooltip,
 | 
					  tooltip,
 | 
				
			||||||
}: CheckBoxProps) => {
 | 
					}) => {
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <span title={tooltip}>
 | 
					    <span title={tooltip}>
 | 
				
			||||||
      <input
 | 
					      <input
 | 
				
			||||||
| 
						 | 
					@ -141,22 +133,39 @@ export const CheckBox = ({
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const TableHeadCell: React.FC<{ children: React.ReactNode }> = ({
 | 
				
			||||||
 | 
					  children,
 | 
				
			||||||
 | 
					}) => (
 | 
				
			||||||
 | 
					  <th className="border border-slate-200 bg-slate-50 py-1 px-2 text-slate-500 font-semibold">
 | 
				
			||||||
 | 
					    {children}
 | 
				
			||||||
 | 
					  </th>
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Cell: React.FC<{ children: React.ReactNode }> = ({ children }) => (
 | 
				
			||||||
 | 
					  <td className="border border-slate-200 py-1 px-2 text-slate-900">
 | 
				
			||||||
 | 
					    {children}
 | 
				
			||||||
 | 
					  </td>
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type SummaryTableProps = {
 | 
					type SummaryTableProps = {
 | 
				
			||||||
  distribution: Distribution;
 | 
					  distribution: Distribution;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const SummaryTable: React.FC<SummaryTableProps> = ({
 | 
					const SummaryTable: React.FC<SummaryTableProps> = ({ distribution }) => {
 | 
				
			||||||
  distribution,
 | 
					  const mean = distribution.mean();
 | 
				
			||||||
}: SummaryTableProps) => {
 | 
					  const stdev = distribution.stdev();
 | 
				
			||||||
  let mean = distribution.mean();
 | 
					  const p5 = distribution.inv(0.05);
 | 
				
			||||||
  let p5 = distribution.inv(0.05);
 | 
					  const p10 = distribution.inv(0.1);
 | 
				
			||||||
  let p10 = distribution.inv(0.1);
 | 
					  const p25 = distribution.inv(0.25);
 | 
				
			||||||
  let p25 = distribution.inv(0.25);
 | 
					  const p50 = distribution.inv(0.5);
 | 
				
			||||||
  let p50 = distribution.inv(0.5);
 | 
					  const p75 = distribution.inv(0.75);
 | 
				
			||||||
  let p75 = distribution.inv(0.75);
 | 
					  const p90 = distribution.inv(0.9);
 | 
				
			||||||
  let p90 = distribution.inv(0.9);
 | 
					  const p95 = distribution.inv(0.95);
 | 
				
			||||||
  let p95 = distribution.inv(0.95);
 | 
					
 | 
				
			||||||
  let unwrapResult = (
 | 
					  const hasResult = (x: result<number, distributionError>): boolean =>
 | 
				
			||||||
 | 
					    x.tag === "Ok";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const unwrapResult = (
 | 
				
			||||||
    x: result<number, distributionError>
 | 
					    x: result<number, distributionError>
 | 
				
			||||||
  ): React.ReactNode => {
 | 
					  ): React.ReactNode => {
 | 
				
			||||||
    if (x.tag === "Ok") {
 | 
					    if (x.tag === "Ok") {
 | 
				
			||||||
| 
						 | 
					@ -170,24 +179,12 @@ const SummaryTable: React.FC<SummaryTableProps> = ({
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let TableHeadCell: React.FC<{ children: React.ReactNode }> = ({
 | 
					 | 
				
			||||||
    children,
 | 
					 | 
				
			||||||
  }) => (
 | 
					 | 
				
			||||||
    <th className="border border-slate-200 bg-slate-50 py-1 px-2 text-slate-500 font-semibold">
 | 
					 | 
				
			||||||
      {children}
 | 
					 | 
				
			||||||
    </th>
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
  let Cell: React.FC<{ children: React.ReactNode }> = ({ children }) => (
 | 
					 | 
				
			||||||
    <td className="border border-slate-200 py-1 px-2 text-slate-900 ">
 | 
					 | 
				
			||||||
      {children}
 | 
					 | 
				
			||||||
    </td>
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <table className="border border-collapse border-slate-400">
 | 
					    <table className="border border-collapse border-slate-400">
 | 
				
			||||||
      <thead className="bg-slate-50">
 | 
					      <thead className="bg-slate-50">
 | 
				
			||||||
        <tr>
 | 
					        <tr>
 | 
				
			||||||
          <TableHeadCell>{"Mean"}</TableHeadCell>
 | 
					          <TableHeadCell>{"Mean"}</TableHeadCell>
 | 
				
			||||||
 | 
					          {hasResult(stdev) && <TableHeadCell>{"Stdev"}</TableHeadCell>}
 | 
				
			||||||
          <TableHeadCell>{"5%"}</TableHeadCell>
 | 
					          <TableHeadCell>{"5%"}</TableHeadCell>
 | 
				
			||||||
          <TableHeadCell>{"10%"}</TableHeadCell>
 | 
					          <TableHeadCell>{"10%"}</TableHeadCell>
 | 
				
			||||||
          <TableHeadCell>{"25%"}</TableHeadCell>
 | 
					          <TableHeadCell>{"25%"}</TableHeadCell>
 | 
				
			||||||
| 
						 | 
					@ -200,6 +197,7 @@ const SummaryTable: React.FC<SummaryTableProps> = ({
 | 
				
			||||||
      <tbody>
 | 
					      <tbody>
 | 
				
			||||||
        <tr>
 | 
					        <tr>
 | 
				
			||||||
          <Cell>{unwrapResult(mean)}</Cell>
 | 
					          <Cell>{unwrapResult(mean)}</Cell>
 | 
				
			||||||
 | 
					          {hasResult(stdev) && <Cell>{unwrapResult(stdev)}</Cell>}
 | 
				
			||||||
          <Cell>{unwrapResult(p5)}</Cell>
 | 
					          <Cell>{unwrapResult(p5)}</Cell>
 | 
				
			||||||
          <Cell>{unwrapResult(p10)}</Cell>
 | 
					          <Cell>{unwrapResult(p10)}</Cell>
 | 
				
			||||||
          <Cell>{unwrapResult(p25)}</Cell>
 | 
					          <Cell>{unwrapResult(p25)}</Cell>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ export const FunctionChart: React.FC<FunctionChartProps> = ({
 | 
				
			||||||
  chartSettings,
 | 
					  chartSettings,
 | 
				
			||||||
  environment,
 | 
					  environment,
 | 
				
			||||||
  height,
 | 
					  height,
 | 
				
			||||||
}: FunctionChartProps) => {
 | 
					}) => {
 | 
				
			||||||
  if (fn.parameters.length > 1) {
 | 
					  if (fn.parameters.length > 1) {
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <MessageAlert heading="Function Display Not Supported">
 | 
					      <MessageAlert heading="Function Display Not Supported">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -151,7 +151,7 @@ export const FunctionChart1Dist: React.FC<FunctionChart1DistProps> = ({
 | 
				
			||||||
  chartSettings,
 | 
					  chartSettings,
 | 
				
			||||||
  environment,
 | 
					  environment,
 | 
				
			||||||
  height,
 | 
					  height,
 | 
				
			||||||
}: FunctionChart1DistProps) => {
 | 
					}) => {
 | 
				
			||||||
  let [mouseOverlay, setMouseOverlay] = React.useState(0);
 | 
					  let [mouseOverlay, setMouseOverlay] = React.useState(0);
 | 
				
			||||||
  function handleHover(_name: string, value: unknown) {
 | 
					  function handleHover(_name: string, value: unknown) {
 | 
				
			||||||
    setMouseOverlay(value as number);
 | 
					    setMouseOverlay(value as number);
 | 
				
			||||||
| 
						 | 
					@ -170,16 +170,14 @@ export const FunctionChart1Dist: React.FC<FunctionChart1DistProps> = ({
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
  let showChart =
 | 
					  let showChart =
 | 
				
			||||||
    mouseItem.tag === "Ok" && mouseItem.value.tag == "distribution" ? (
 | 
					    mouseItem.tag === "Ok" && mouseItem.value.tag === "distribution" ? (
 | 
				
			||||||
      <DistributionChart
 | 
					      <DistributionChart
 | 
				
			||||||
        distribution={mouseItem.value.value}
 | 
					        distribution={mouseItem.value.value}
 | 
				
			||||||
        width={400}
 | 
					        width={400}
 | 
				
			||||||
        height={50}
 | 
					        height={50}
 | 
				
			||||||
        showSummary={false}
 | 
					        showSummary={false}
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
    ) : (
 | 
					    ) : null;
 | 
				
			||||||
      <></>
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let getPercentilesMemoized = React.useMemo(
 | 
					  let getPercentilesMemoized = React.useMemo(
 | 
				
			||||||
    () => getPercentiles({ chartSettings, fn, environment }),
 | 
					    () => getPercentiles({ chartSettings, fn, environment }),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,15 +14,15 @@ interface CodeEditorProps {
 | 
				
			||||||
  showGutter?: boolean;
 | 
					  showGutter?: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export let JsonEditor: FC<CodeEditorProps> = ({
 | 
					export const JsonEditor: FC<CodeEditorProps> = ({
 | 
				
			||||||
  value,
 | 
					  value,
 | 
				
			||||||
  onChange,
 | 
					  onChange,
 | 
				
			||||||
  oneLine = false,
 | 
					  oneLine = false,
 | 
				
			||||||
  showGutter = false,
 | 
					  showGutter = false,
 | 
				
			||||||
  height,
 | 
					  height,
 | 
				
			||||||
}: CodeEditorProps) => {
 | 
					}) => {
 | 
				
			||||||
  let lineCount = value.split("\n").length;
 | 
					  const lineCount = value.split("\n").length;
 | 
				
			||||||
  let id = _.uniqueId();
 | 
					  const id = _.uniqueId();
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <AceEditor
 | 
					    <AceEditor
 | 
				
			||||||
      value={value}
 | 
					      value={value}
 | 
				
			||||||
| 
						 | 
					@ -47,5 +47,3 @@ export let JsonEditor: FC<CodeEditorProps> = ({
 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					 | 
				
			||||||
export default JsonEditor;
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,4 @@
 | 
				
			||||||
import * as React from "react";
 | 
					import * as React from "react";
 | 
				
			||||||
import _ from "lodash";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const orderOfMagnitudeNum = (n: number) => {
 | 
					const orderOfMagnitudeNum = (n: number) => {
 | 
				
			||||||
  return Math.pow(10, n);
 | 
					  return Math.pow(10, n);
 | 
				
			||||||
| 
						 | 
					@ -74,25 +73,23 @@ export interface NumberShowerProps {
 | 
				
			||||||
  precision?: number;
 | 
					  precision?: number;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export let NumberShower: React.FC<NumberShowerProps> = ({
 | 
					export const NumberShower: React.FC<NumberShowerProps> = ({
 | 
				
			||||||
  number,
 | 
					  number,
 | 
				
			||||||
  precision = 2,
 | 
					  precision = 2,
 | 
				
			||||||
}: NumberShowerProps) => {
 | 
					}) => {
 | 
				
			||||||
  let numberWithPresentation = numberShow(number, precision);
 | 
					  const numberWithPresentation = numberShow(number, precision);
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <span>
 | 
					    <span>
 | 
				
			||||||
      {numberWithPresentation.value}
 | 
					      {numberWithPresentation.value}
 | 
				
			||||||
      {numberWithPresentation.symbol}
 | 
					      {numberWithPresentation.symbol}
 | 
				
			||||||
      {numberWithPresentation.power ? (
 | 
					      {numberWithPresentation.power ? (
 | 
				
			||||||
        <span>
 | 
					        <span>
 | 
				
			||||||
          {"\u00b710"}
 | 
					          {"\u00b7" /* dot symbol */}10
 | 
				
			||||||
          <span style={{ fontSize: "0.6em", verticalAlign: "super" }}>
 | 
					          <span style={{ fontSize: "0.6em", verticalAlign: "super" }}>
 | 
				
			||||||
            {numberWithPresentation.power}
 | 
					            {numberWithPresentation.power}
 | 
				
			||||||
          </span>
 | 
					          </span>
 | 
				
			||||||
        </span>
 | 
					        </span>
 | 
				
			||||||
      ) : (
 | 
					      ) : null}
 | 
				
			||||||
        <></>
 | 
					 | 
				
			||||||
      )}
 | 
					 | 
				
			||||||
    </span>
 | 
					    </span>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,4 @@
 | 
				
			||||||
import * as React from "react";
 | 
					import * as React from "react";
 | 
				
			||||||
import _ from "lodash";
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  run,
 | 
					  run,
 | 
				
			||||||
  errorValueToString,
 | 
					  errorValueToString,
 | 
				
			||||||
| 
						 | 
					@ -28,6 +27,7 @@ function getRange<a>(x: declaration<a>) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getChartSettings<a>(x: declaration<a>): FunctionChartSettings {
 | 
					function getChartSettings<a>(x: declaration<a>): FunctionChartSettings {
 | 
				
			||||||
  let range = getRange(x);
 | 
					  let range = getRange(x);
 | 
				
			||||||
  let min = range.floats ? range.floats.min : 0;
 | 
					  let min = range.floats ? range.floats.min : 0;
 | 
				
			||||||
| 
						 | 
					@ -49,12 +49,12 @@ export const VariableBox: React.FC<VariableBoxProps> = ({
 | 
				
			||||||
  heading = "Error",
 | 
					  heading = "Error",
 | 
				
			||||||
  children,
 | 
					  children,
 | 
				
			||||||
  showTypes = false,
 | 
					  showTypes = false,
 | 
				
			||||||
}: VariableBoxProps) => {
 | 
					}) => {
 | 
				
			||||||
  if (showTypes) {
 | 
					  if (showTypes) {
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div className="bg-white border border-grey-200 m-2">
 | 
					      <div className="bg-white border border-grey-200 m-2">
 | 
				
			||||||
        <div className="border-b border-grey-200 p-3">
 | 
					        <div className="border-b border-grey-200 p-3">
 | 
				
			||||||
          <h3 className="font-mono">{heading}</h3>
 | 
					          <header className="font-mono">{heading}</header>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div className="p-3">{children}</div>
 | 
					        <div className="p-3">{children}</div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
| 
						 | 
					@ -90,7 +90,7 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
 | 
				
			||||||
  showControls = false,
 | 
					  showControls = false,
 | 
				
			||||||
  chartSettings,
 | 
					  chartSettings,
 | 
				
			||||||
  environment,
 | 
					  environment,
 | 
				
			||||||
}: SquiggleItemProps) => {
 | 
					}) => {
 | 
				
			||||||
  switch (expression.tag) {
 | 
					  switch (expression.tag) {
 | 
				
			||||||
    case "number":
 | 
					    case "number":
 | 
				
			||||||
      return (
 | 
					      return (
 | 
				
			||||||
| 
						 | 
					@ -108,12 +108,8 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
 | 
				
			||||||
          showTypes={showTypes}
 | 
					          showTypes={showTypes}
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
          {distType === "Symbolic" && showTypes ? (
 | 
					          {distType === "Symbolic" && showTypes ? (
 | 
				
			||||||
            <>
 | 
					 | 
				
			||||||
            <div>{expression.value.toString()}</div>
 | 
					            <div>{expression.value.toString()}</div>
 | 
				
			||||||
            </>
 | 
					          ) : null}
 | 
				
			||||||
          ) : (
 | 
					 | 
				
			||||||
            <></>
 | 
					 | 
				
			||||||
          )}
 | 
					 | 
				
			||||||
          <DistributionChart
 | 
					          <DistributionChart
 | 
				
			||||||
            distribution={expression.value}
 | 
					            distribution={expression.value}
 | 
				
			||||||
            height={height}
 | 
					            height={height}
 | 
				
			||||||
| 
						 | 
					@ -157,11 +153,11 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
 | 
				
			||||||
      return (
 | 
					      return (
 | 
				
			||||||
        <VariableBox heading="Array" showTypes={showTypes}>
 | 
					        <VariableBox heading="Array" showTypes={showTypes}>
 | 
				
			||||||
          {expression.value.map((r, i) => (
 | 
					          {expression.value.map((r, i) => (
 | 
				
			||||||
            <div key={i} className="flex flex-row pt-1">
 | 
					            <div key={i} className="flex pt-1">
 | 
				
			||||||
              <div className="flex-none bg-slate-100 rounded-sm px-1">
 | 
					              <div className="flex-none bg-slate-100 rounded-sm px-1">
 | 
				
			||||||
                <h3 className="text-slate-400 font-mono">{i}</h3>
 | 
					                <header className="text-slate-400 font-mono">{i}</header>
 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
              <div className="px-2 mb-2 grow ">
 | 
					              <div className="px-2 mb-2 grow">
 | 
				
			||||||
                <SquiggleItem
 | 
					                <SquiggleItem
 | 
				
			||||||
                  key={i}
 | 
					                  key={i}
 | 
				
			||||||
                  expression={r}
 | 
					                  expression={r}
 | 
				
			||||||
| 
						 | 
					@ -181,12 +177,13 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
 | 
				
			||||||
    case "record":
 | 
					    case "record":
 | 
				
			||||||
      return (
 | 
					      return (
 | 
				
			||||||
        <VariableBox heading="Record" showTypes={showTypes}>
 | 
					        <VariableBox heading="Record" showTypes={showTypes}>
 | 
				
			||||||
 | 
					          <div className="space-y-3">
 | 
				
			||||||
            {Object.entries(expression.value).map(([key, r]) => (
 | 
					            {Object.entries(expression.value).map(([key, r]) => (
 | 
				
			||||||
            <div key={key} className="flex flex-row pt-1">
 | 
					              <div key={key} className="flex space-x-2">
 | 
				
			||||||
              <div className="flex-none pr-2">
 | 
					                <div className="flex-none">
 | 
				
			||||||
                <h3 className="text-slate-500 font-mono">{key}:</h3>
 | 
					                  <header className="text-slate-500 font-mono">{key}:</header>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
              <div className="pl-2 pr-2 mb-2 grow bg-gray-50 border border-gray-100 rounded-sm">
 | 
					                <div className="px-2 grow bg-gray-50 border border-gray-100 rounded-sm">
 | 
				
			||||||
                  <SquiggleItem
 | 
					                  <SquiggleItem
 | 
				
			||||||
                    expression={r}
 | 
					                    expression={r}
 | 
				
			||||||
                    width={width !== undefined ? width - 20 : width}
 | 
					                    width={width !== undefined ? width - 20 : width}
 | 
				
			||||||
| 
						 | 
					@ -200,6 +197,7 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
            ))}
 | 
					            ))}
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
        </VariableBox>
 | 
					        </VariableBox>
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    case "arraystring":
 | 
					    case "arraystring":
 | 
				
			||||||
| 
						 | 
					@ -285,7 +283,7 @@ export interface SquiggleChartProps {
 | 
				
			||||||
  showControls?: boolean;
 | 
					  showControls?: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let defaultChartSettings = { start: 0, stop: 10, count: 20 };
 | 
					const defaultChartSettings = { start: 0, stop: 10, count: 20 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const SquiggleChart: React.FC<SquiggleChartProps> = ({
 | 
					export const SquiggleChart: React.FC<SquiggleChartProps> = ({
 | 
				
			||||||
  squiggleString = "",
 | 
					  squiggleString = "",
 | 
				
			||||||
| 
						 | 
					@ -299,14 +297,20 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
 | 
				
			||||||
  showTypes = false,
 | 
					  showTypes = false,
 | 
				
			||||||
  showControls = false,
 | 
					  showControls = false,
 | 
				
			||||||
  chartSettings = defaultChartSettings,
 | 
					  chartSettings = defaultChartSettings,
 | 
				
			||||||
}: SquiggleChartProps) => {
 | 
					}) => {
 | 
				
			||||||
  let expressionResult = run(squiggleString, bindings, environment, jsImports);
 | 
					  let expressionResult = run(squiggleString, bindings, environment, jsImports);
 | 
				
			||||||
  let e = environment ? environment : defaultEnvironment;
 | 
					  if (expressionResult.tag !== "Ok") {
 | 
				
			||||||
  let internal: JSX.Element;
 | 
					    return (
 | 
				
			||||||
  if (expressionResult.tag === "Ok") {
 | 
					      <ErrorAlert heading={"Parse Error"}>
 | 
				
			||||||
 | 
					        {errorValueToString(expressionResult.value)}
 | 
				
			||||||
 | 
					      </ErrorAlert>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let e = environment ?? defaultEnvironment;
 | 
				
			||||||
  let expression = expressionResult.value;
 | 
					  let expression = expressionResult.value;
 | 
				
			||||||
  onChange(expression);
 | 
					  onChange(expression);
 | 
				
			||||||
    internal = (
 | 
					  return (
 | 
				
			||||||
    <SquiggleItem
 | 
					    <SquiggleItem
 | 
				
			||||||
      expression={expression}
 | 
					      expression={expression}
 | 
				
			||||||
      width={width}
 | 
					      width={width}
 | 
				
			||||||
| 
						 | 
					@ -318,12 +322,4 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
 | 
				
			||||||
      environment={e}
 | 
					      environment={e}
 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    internal = (
 | 
					 | 
				
			||||||
      <ErrorAlert heading={"Parse Error"}>
 | 
					 | 
				
			||||||
        {errorValueToString(expressionResult.value)}
 | 
					 | 
				
			||||||
      </ErrorAlert>
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return internal;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,8 +57,8 @@ export let SquiggleEditor: React.FC<SquiggleEditorProps> = ({
 | 
				
			||||||
  showControls = false,
 | 
					  showControls = false,
 | 
				
			||||||
  showSummary = false,
 | 
					  showSummary = false,
 | 
				
			||||||
}: SquiggleEditorProps) => {
 | 
					}: SquiggleEditorProps) => {
 | 
				
			||||||
  let [expression, setExpression] = React.useState(initialSquiggleString);
 | 
					  const [expression, setExpression] = React.useState(initialSquiggleString);
 | 
				
			||||||
  let chartSettings = {
 | 
					  const chartSettings = {
 | 
				
			||||||
    start: diagramStart,
 | 
					    start: diagramStart,
 | 
				
			||||||
    stop: diagramStop,
 | 
					    stop: diagramStop,
 | 
				
			||||||
    count: diagramCount,
 | 
					    count: diagramCount,
 | 
				
			||||||
| 
						 | 
					@ -150,17 +150,17 @@ export let SquigglePartial: React.FC<SquigglePartialProps> = ({
 | 
				
			||||||
  environment,
 | 
					  environment,
 | 
				
			||||||
  jsImports = defaultImports,
 | 
					  jsImports = defaultImports,
 | 
				
			||||||
}: SquigglePartialProps) => {
 | 
					}: SquigglePartialProps) => {
 | 
				
			||||||
  let [expression, setExpression] = React.useState(initialSquiggleString);
 | 
					  const [expression, setExpression] = React.useState(initialSquiggleString);
 | 
				
			||||||
  let [error, setError] = React.useState<string | null>(null);
 | 
					  const [error, setError] = React.useState<string | null>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let runSquiggleAndUpdateBindings = () => {
 | 
					  const runSquiggleAndUpdateBindings = () => {
 | 
				
			||||||
    let squiggleResult = runPartial(
 | 
					    const squiggleResult = runPartial(
 | 
				
			||||||
      expression,
 | 
					      expression,
 | 
				
			||||||
      bindings,
 | 
					      bindings,
 | 
				
			||||||
      environment,
 | 
					      environment,
 | 
				
			||||||
      jsImports
 | 
					      jsImports
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    if (squiggleResult.tag == "Ok") {
 | 
					    if (squiggleResult.tag === "Ok") {
 | 
				
			||||||
      if (onChange) onChange(squiggleResult.value);
 | 
					      if (onChange) onChange(squiggleResult.value);
 | 
				
			||||||
      setError(null);
 | 
					      setError(null);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
| 
						 | 
					@ -181,11 +181,7 @@ export let SquigglePartial: React.FC<SquigglePartialProps> = ({
 | 
				
			||||||
          height={20}
 | 
					          height={20}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      {error !== null ? (
 | 
					      {error !== null ? <ErrorAlert heading="Error">{error}</ErrorAlert> : null}
 | 
				
			||||||
        <ErrorAlert heading="Error">{error}</ErrorAlert>
 | 
					 | 
				
			||||||
      ) : (
 | 
					 | 
				
			||||||
        <></>
 | 
					 | 
				
			||||||
      )}
 | 
					 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,19 +1,21 @@
 | 
				
			||||||
import _ from "lodash";
 | 
					import React, { FC, Fragment, useState } from "react";
 | 
				
			||||||
import React, { FC, ReactElement, useState } from "react";
 | 
					 | 
				
			||||||
import ReactDOM from "react-dom";
 | 
					import ReactDOM from "react-dom";
 | 
				
			||||||
import { SquiggleChart } from "./SquiggleChart";
 | 
					import { Path, useForm, UseFormRegister, useWatch } from "react-hook-form";
 | 
				
			||||||
import CodeEditor from "./CodeEditor";
 | 
					 | 
				
			||||||
import JsonEditor from "./JsonEditor";
 | 
					 | 
				
			||||||
import { useForm, useWatch } from "react-hook-form";
 | 
					 | 
				
			||||||
import * as yup from "yup";
 | 
					import * as yup from "yup";
 | 
				
			||||||
import { yupResolver } from "@hookform/resolvers/yup";
 | 
					import { yupResolver } from "@hookform/resolvers/yup";
 | 
				
			||||||
import { defaultBindings, environment } from "@quri/squiggle-lang";
 | 
					 | 
				
			||||||
import { Tab } from "@headlessui/react";
 | 
					import { Tab } from "@headlessui/react";
 | 
				
			||||||
import { CodeIcon } from "@heroicons/react/solid";
 | 
					import {
 | 
				
			||||||
import { CogIcon } from "@heroicons/react/solid";
 | 
					  ChartSquareBarIcon,
 | 
				
			||||||
import { ChartSquareBarIcon } from "@heroicons/react/solid";
 | 
					  CodeIcon,
 | 
				
			||||||
import { CurrencyDollarIcon } from "@heroicons/react/solid";
 | 
					  CogIcon,
 | 
				
			||||||
import { Fragment } from "react";
 | 
					  CurrencyDollarIcon,
 | 
				
			||||||
 | 
					} from "@heroicons/react/solid";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { defaultBindings, environment } from "@quri/squiggle-lang";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { SquiggleChart } from "./SquiggleChart";
 | 
				
			||||||
 | 
					import { CodeEditor } from "./CodeEditor";
 | 
				
			||||||
 | 
					import { JsonEditor } from "./JsonEditor";
 | 
				
			||||||
import { ErrorAlert, SuccessAlert } from "./Alert";
 | 
					import { ErrorAlert, SuccessAlert } from "./Alert";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface PlaygroundProps {
 | 
					interface PlaygroundProps {
 | 
				
			||||||
| 
						 | 
					@ -85,49 +87,20 @@ const schema = yup
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
  .required();
 | 
					  .required();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type InputProps = {
 | 
					 | 
				
			||||||
  label: string;
 | 
					 | 
				
			||||||
  children: ReactElement;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const InputItem: React.FC<InputProps> = ({ label, children }) => (
 | 
					 | 
				
			||||||
  <div className="col-span-4">
 | 
					 | 
				
			||||||
    <label className="block text-sm font-medium text-gray-600">{label}</label>
 | 
					 | 
				
			||||||
    <div className="mt-1">{children}</div>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let numberStyle =
 | 
					 | 
				
			||||||
  "max-w-lg block w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:max-w-xs sm:text-sm border-gray-300 rounded-md";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function classNames(...classes: string[]) {
 | 
					function classNames(...classes: string[]) {
 | 
				
			||||||
  return classes.filter(Boolean).join(" ");
 | 
					  return classes.filter(Boolean).join(" ");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type StyledTabProps = {
 | 
					type StyledTabProps = {
 | 
				
			||||||
  name: string;
 | 
					  name: string;
 | 
				
			||||||
  iconName: string;
 | 
					  icon: (props: React.ComponentProps<"svg">) => JSX.Element;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledTab: React.FC<StyledTabProps> = ({ name, iconName }) => {
 | 
					const StyledTab: React.FC<StyledTabProps> = ({ name, icon: Icon }) => {
 | 
				
			||||||
  let iconStyle = (isSelected: boolean) =>
 | 
					 | 
				
			||||||
    classNames(
 | 
					 | 
				
			||||||
      "-ml-0.5 mr-2 h-4 w-4 ",
 | 
					 | 
				
			||||||
      isSelected ? "text-slate-500" : "text-gray-400 group-hover:text-gray-900"
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  let icon = (selected: boolean) =>
 | 
					 | 
				
			||||||
    ({
 | 
					 | 
				
			||||||
      code: <CodeIcon className={iconStyle(selected)} />,
 | 
					 | 
				
			||||||
      cog: <CogIcon className={iconStyle(selected)} />,
 | 
					 | 
				
			||||||
      squareBar: <ChartSquareBarIcon className={iconStyle(selected)} />,
 | 
					 | 
				
			||||||
      dollar: <CurrencyDollarIcon className={iconStyle(selected)} />,
 | 
					 | 
				
			||||||
    }[iconName]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <Tab key={name} as={Fragment}>
 | 
					    <Tab key={name} as={Fragment}>
 | 
				
			||||||
      {({ selected }) => (
 | 
					      {({ selected }) => (
 | 
				
			||||||
        <button className="flex rounded-md focus:outline-none focus-visible:ring-offset-gray-100 ">
 | 
					        <button className="group flex rounded-md focus:outline-none focus-visible:ring-offset-gray-100">
 | 
				
			||||||
          <span
 | 
					          <span
 | 
				
			||||||
            className={classNames(
 | 
					            className={classNames(
 | 
				
			||||||
              "p-1 pl-2.5 pr-3.5 rounded-md flex items-center text-sm font-medium",
 | 
					              "p-1 pl-2.5 pr-3.5 rounded-md flex items-center text-sm font-medium",
 | 
				
			||||||
| 
						 | 
					@ -136,7 +109,14 @@ const StyledTab: React.FC<StyledTabProps> = ({ name, iconName }) => {
 | 
				
			||||||
                : ""
 | 
					                : ""
 | 
				
			||||||
            )}
 | 
					            )}
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {icon(selected)}
 | 
					            <Icon
 | 
				
			||||||
 | 
					              className={classNames(
 | 
				
			||||||
 | 
					                "-ml-0.5 mr-2 h-4 w-4",
 | 
				
			||||||
 | 
					                selected
 | 
				
			||||||
 | 
					                  ? "text-slate-500"
 | 
				
			||||||
 | 
					                  : "text-gray-400 group-hover:text-gray-900"
 | 
				
			||||||
 | 
					              )}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
            <span
 | 
					            <span
 | 
				
			||||||
              className={
 | 
					              className={
 | 
				
			||||||
                selected
 | 
					                selected
 | 
				
			||||||
| 
						 | 
					@ -153,17 +133,77 @@ const StyledTab: React.FC<StyledTabProps> = ({ name, iconName }) => {
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let SquigglePlayground: FC<PlaygroundProps> = ({
 | 
					const HeadedSection: FC<{ title: string; children: React.ReactNode }> = ({
 | 
				
			||||||
 | 
					  title,
 | 
				
			||||||
 | 
					  children,
 | 
				
			||||||
 | 
					}) => (
 | 
				
			||||||
 | 
					  <div>
 | 
				
			||||||
 | 
					    <header className="text-lg leading-6 font-medium text-gray-900">
 | 
				
			||||||
 | 
					      {title}
 | 
				
			||||||
 | 
					    </header>
 | 
				
			||||||
 | 
					    <div className="mt-4">{children}</div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Text: FC<{ children: React.ReactNode }> = ({ children }) => (
 | 
				
			||||||
 | 
					  <p className="text-sm text-gray-500">{children}</p>
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function InputItem<T>({
 | 
				
			||||||
 | 
					  name,
 | 
				
			||||||
 | 
					  label,
 | 
				
			||||||
 | 
					  type,
 | 
				
			||||||
 | 
					  register,
 | 
				
			||||||
 | 
					}: {
 | 
				
			||||||
 | 
					  name: Path<T>;
 | 
				
			||||||
 | 
					  label: string;
 | 
				
			||||||
 | 
					  type: "number";
 | 
				
			||||||
 | 
					  register: UseFormRegister<T>;
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
					  const numberStyle =
 | 
				
			||||||
 | 
					    "max-w-lg block w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:max-w-xs sm:text-sm border-gray-300 rounded-md";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <label className="block">
 | 
				
			||||||
 | 
					      <div className="text-sm font-medium text-gray-600 mb-1">{label}</div>
 | 
				
			||||||
 | 
					      <input type={type} {...register(name)} className={numberStyle} />
 | 
				
			||||||
 | 
					    </label>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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="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>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const SquigglePlayground: FC<PlaygroundProps> = ({
 | 
				
			||||||
  initialSquiggleString = "",
 | 
					  initialSquiggleString = "",
 | 
				
			||||||
  height = 500,
 | 
					  height = 500,
 | 
				
			||||||
  showTypes = false,
 | 
					  showTypes = false,
 | 
				
			||||||
  showControls = false,
 | 
					  showControls = false,
 | 
				
			||||||
  showSummary = false,
 | 
					  showSummary = false,
 | 
				
			||||||
}: PlaygroundProps) => {
 | 
					}) => {
 | 
				
			||||||
  let [squiggleString, setSquiggleString] = useState(initialSquiggleString);
 | 
					  const [squiggleString, setSquiggleString] = useState(initialSquiggleString);
 | 
				
			||||||
  let [importString, setImportString] = useState("{}");
 | 
					  const [importString, setImportString] = useState("{}");
 | 
				
			||||||
  let [imports, setImports] = useState({});
 | 
					  const [imports, setImports] = useState({});
 | 
				
			||||||
  let [importsAreValid, setImportsAreValid] = useState(true);
 | 
					  const [importsAreValid, setImportsAreValid] = useState(true);
 | 
				
			||||||
  const { register, control } = useForm({
 | 
					  const { register, control } = useForm({
 | 
				
			||||||
    resolver: yupResolver(schema),
 | 
					    resolver: yupResolver(schema),
 | 
				
			||||||
    defaultValues: {
 | 
					    defaultValues: {
 | 
				
			||||||
| 
						 | 
					@ -183,16 +223,16 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
 | 
				
			||||||
  const vars = useWatch({
 | 
					  const vars = useWatch({
 | 
				
			||||||
    control,
 | 
					    control,
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  let chartSettings = {
 | 
					  const chartSettings = {
 | 
				
			||||||
    start: Number(vars.diagramStart),
 | 
					    start: Number(vars.diagramStart),
 | 
				
			||||||
    stop: Number(vars.diagramStop),
 | 
					    stop: Number(vars.diagramStop),
 | 
				
			||||||
    count: Number(vars.diagramCount),
 | 
					    count: Number(vars.diagramCount),
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  let env: environment = {
 | 
					  const env: environment = {
 | 
				
			||||||
    sampleCount: Number(vars.sampleCount),
 | 
					    sampleCount: Number(vars.sampleCount),
 | 
				
			||||||
    xyPointLength: Number(vars.xyPointLength),
 | 
					    xyPointLength: Number(vars.xyPointLength),
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  let getChangeJson = (r: string) => {
 | 
					  const getChangeJson = (r: string) => {
 | 
				
			||||||
    setImportString(r);
 | 
					    setImportString(r);
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      setImports(JSON.parse(r));
 | 
					      setImports(JSON.parse(r));
 | 
				
			||||||
| 
						 | 
					@ -202,149 +242,118 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let samplingSettings = (
 | 
					  const samplingSettings = (
 | 
				
			||||||
    <div className="space-y-6 p-3 max-w-xl">
 | 
					    <div className="space-y-6 p-3 max-w-xl">
 | 
				
			||||||
      <InputItem label="Sample Count">
 | 
					      <div>
 | 
				
			||||||
        <>
 | 
					        <InputItem
 | 
				
			||||||
          <input
 | 
					          name="sampleCount"
 | 
				
			||||||
          type="number"
 | 
					          type="number"
 | 
				
			||||||
            {...register("sampleCount")}
 | 
					          label="Sample Count"
 | 
				
			||||||
            className={numberStyle}
 | 
					          register={register}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
          <p className="mt-2 text-sm text-gray-500">
 | 
					        <div className="mt-2">
 | 
				
			||||||
 | 
					          <Text>
 | 
				
			||||||
            How many samples to use for Monte Carlo simulations. This can
 | 
					            How many samples to use for Monte Carlo simulations. This can
 | 
				
			||||||
            occasionally be overridden by specific Squiggle programs.
 | 
					            occasionally be overridden by specific Squiggle programs.
 | 
				
			||||||
          </p>
 | 
					          </Text>
 | 
				
			||||||
        </>
 | 
					        </div>
 | 
				
			||||||
      </InputItem>
 | 
					      </div>
 | 
				
			||||||
      <InputItem label="Coordinate Count (For PointSet Shapes)">
 | 
					      <div>
 | 
				
			||||||
        <>
 | 
					        <InputItem
 | 
				
			||||||
          <input
 | 
					          name="xyPointLength"
 | 
				
			||||||
          type="number"
 | 
					          type="number"
 | 
				
			||||||
            {...register("xyPointLength")}
 | 
					          register={register}
 | 
				
			||||||
            className={numberStyle}
 | 
					          label="Coordinate Count (For PointSet Shapes)"
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
          <p className="mt-2 text-sm text-gray-500">
 | 
					        <div className="mt-2">
 | 
				
			||||||
 | 
					          <Text>
 | 
				
			||||||
            When distributions are converted into PointSet shapes, we need to
 | 
					            When distributions are converted into PointSet shapes, we need to
 | 
				
			||||||
            know how many coordinates to use.
 | 
					            know how many coordinates to use.
 | 
				
			||||||
          </p>
 | 
					          </Text>
 | 
				
			||||||
        </>
 | 
					        </div>
 | 
				
			||||||
      </InputItem>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let viewSettings = (
 | 
					  const viewSettings = (
 | 
				
			||||||
    <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">
 | 
				
			||||||
 | 
					        <div className="space-y-4">
 | 
				
			||||||
 | 
					          <InputItem
 | 
				
			||||||
 | 
					            name="chartHeight"
 | 
				
			||||||
 | 
					            type="number"
 | 
				
			||||||
 | 
					            register={register}
 | 
				
			||||||
 | 
					            label="Chart Height (in pixels)"
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					          <Checkbox
 | 
				
			||||||
 | 
					            name="showTypes"
 | 
				
			||||||
 | 
					            register={register}
 | 
				
			||||||
 | 
					            label="Show information about displayed types"
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </HeadedSection>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <div className="pt-8">
 | 
				
			||||||
 | 
					        <HeadedSection title="Distribution Display Settings">
 | 
				
			||||||
          <div className="space-y-2">
 | 
					          <div className="space-y-2">
 | 
				
			||||||
        <h3 className="text-lg leading-6 font-medium text-gray-900 pb-2">
 | 
					            <Checkbox
 | 
				
			||||||
          General Display Settings
 | 
					              register={register}
 | 
				
			||||||
        </h3>
 | 
					              name="showControls"
 | 
				
			||||||
        <InputItem label="Chart Height (in pixels)">
 | 
					              label="Show toggles to adjust scale of x and y axes"
 | 
				
			||||||
          <input
 | 
					 | 
				
			||||||
            type="number"
 | 
					 | 
				
			||||||
            {...register("chartHeight")}
 | 
					 | 
				
			||||||
            className={numberStyle}
 | 
					 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
        </InputItem>
 | 
					            <Checkbox
 | 
				
			||||||
        <div className="relative flex items-start pt-3">
 | 
					              register={register}
 | 
				
			||||||
          <div className="flex items-center h-5">
 | 
					              name="showSummary"
 | 
				
			||||||
            <input
 | 
					              label="Show summary statistics"
 | 
				
			||||||
              type="checkbox"
 | 
					 | 
				
			||||||
              {...register("showTypes")}
 | 
					 | 
				
			||||||
              className="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
 | 
					 | 
				
			||||||
            />
 | 
					            />
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
          <div className="ml-3 text-sm">
 | 
					        </HeadedSection>
 | 
				
			||||||
            <label className="font-medium text-gray-700">
 | 
					 | 
				
			||||||
              Show information about displayed types.
 | 
					 | 
				
			||||||
            </label>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div className="space-y-2 pt-8">
 | 
					      <div className="pt-8">
 | 
				
			||||||
        <h3 className="text-lg leading-6 font-medium text-gray-900 pb-2">
 | 
					        <HeadedSection title="Function Display Settings">
 | 
				
			||||||
          Distribution Display Settings
 | 
					          <div className="space-y-6">
 | 
				
			||||||
        </h3>
 | 
					            <Text>
 | 
				
			||||||
 | 
					              When displaying functions of single variables that return numbers
 | 
				
			||||||
        <div className="relative flex items-start">
 | 
					              or distributions, we need to use defaults for the x-axis. We need
 | 
				
			||||||
          <div className="flex items-center h-5">
 | 
					              to select a minimum and maximum value of x to sample, and a number
 | 
				
			||||||
            <input
 | 
					              n of the number of points to sample.
 | 
				
			||||||
              type="checkbox"
 | 
					            </Text>
 | 
				
			||||||
              {...register("showControls")}
 | 
					            <div className="space-y-4">
 | 
				
			||||||
              className="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
 | 
					              <InputItem
 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
          <div className="ml-3 text-sm">
 | 
					 | 
				
			||||||
            <label className="font-medium text-gray-700">
 | 
					 | 
				
			||||||
              Show toggles to adjust scale of x and y axes
 | 
					 | 
				
			||||||
            </label>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        <div className="relative flex items-start">
 | 
					 | 
				
			||||||
          <div className="flex items-center h-5">
 | 
					 | 
				
			||||||
            <input
 | 
					 | 
				
			||||||
              type="checkbox"
 | 
					 | 
				
			||||||
              {...register("showSummary")}
 | 
					 | 
				
			||||||
              className="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
 | 
					 | 
				
			||||||
            />
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
          <div className="ml-3 text-sm">
 | 
					 | 
				
			||||||
            <label className="font-medium text-gray-700">
 | 
					 | 
				
			||||||
              Show summary statistics
 | 
					 | 
				
			||||||
            </label>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      <div className="space-y-2 pt-8">
 | 
					 | 
				
			||||||
        <h3 className="text-lg leading-6 font-medium text-gray-900 pb-2">
 | 
					 | 
				
			||||||
          Function Display Settings
 | 
					 | 
				
			||||||
        </h3>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <p className="mt-2 text-sm text-gray-500">
 | 
					 | 
				
			||||||
          When displaying functions of single variables that return numbers or
 | 
					 | 
				
			||||||
          distributions, we need to use defaults for the x-axis. We need to
 | 
					 | 
				
			||||||
          select a minimum and maximum value of x to sample, and a number n of
 | 
					 | 
				
			||||||
          the number of points to sample.
 | 
					 | 
				
			||||||
        </p>
 | 
					 | 
				
			||||||
        <div className="pt-4 grid grid-cols-1 gap-y-4 gap-x-4">
 | 
					 | 
				
			||||||
          <InputItem label="Min X Value">
 | 
					 | 
				
			||||||
            <input
 | 
					 | 
				
			||||||
                type="number"
 | 
					                type="number"
 | 
				
			||||||
              {...register("diagramStart")}
 | 
					                name="diagramStart"
 | 
				
			||||||
              className={numberStyle}
 | 
					                register={register}
 | 
				
			||||||
 | 
					                label="Min X Value"
 | 
				
			||||||
              />
 | 
					              />
 | 
				
			||||||
          </InputItem>
 | 
					              <InputItem
 | 
				
			||||||
          <InputItem label="Max X Value">
 | 
					 | 
				
			||||||
            <input
 | 
					 | 
				
			||||||
                type="number"
 | 
					                type="number"
 | 
				
			||||||
              {...register("diagramStop")}
 | 
					                name="diagramStop"
 | 
				
			||||||
              className={numberStyle}
 | 
					                register={register}
 | 
				
			||||||
 | 
					                label="Max X Value"
 | 
				
			||||||
              />
 | 
					              />
 | 
				
			||||||
          </InputItem>
 | 
					              <InputItem
 | 
				
			||||||
          <InputItem label="Points between X min and X max to sample">
 | 
					 | 
				
			||||||
            <input
 | 
					 | 
				
			||||||
                type="number"
 | 
					                type="number"
 | 
				
			||||||
              {...register("diagramCount")}
 | 
					                name="diagramCount"
 | 
				
			||||||
              className={numberStyle}
 | 
					                register={register}
 | 
				
			||||||
 | 
					                label="Points between X min and X max to sample"
 | 
				
			||||||
              />
 | 
					              />
 | 
				
			||||||
          </InputItem>
 | 
					 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
 | 
					        </HeadedSection>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let inputVariableSettings = (
 | 
					  const inputVariableSettings = (
 | 
				
			||||||
    <div className="space-y-6 p-3 max-w-3xl">
 | 
					    <div className="p-3 max-w-3xl">
 | 
				
			||||||
      <h3 className="text-lg leading-6 font-medium text-gray-900">
 | 
					      <HeadedSection title="Import Variables from JSON">
 | 
				
			||||||
        Import Variables from JSON
 | 
					        <div className="space-y-6">
 | 
				
			||||||
      </h3>
 | 
					          <Text>
 | 
				
			||||||
      <p className="mt-2 text-sm text-gray-500">
 | 
					            You can import variables from JSON into your Squiggle code.
 | 
				
			||||||
        You can import variables from JSON into your Squiggle code. Variables
 | 
					            Variables are accessed with dollar signs. For example, "timeNow"
 | 
				
			||||||
        are accessed with dollar signs. For example, "timeNow" would be accessed
 | 
					            would be accessed as "$timeNow".
 | 
				
			||||||
        as "$timeNow".
 | 
					          </Text>
 | 
				
			||||||
      </p>
 | 
					 | 
				
			||||||
          <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}
 | 
				
			||||||
| 
						 | 
					@ -356,30 +365,29 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
          <div className="p-1 pt-2">
 | 
					          <div className="p-1 pt-2">
 | 
				
			||||||
            {importsAreValid ? (
 | 
					            {importsAreValid ? (
 | 
				
			||||||
          <SuccessAlert heading="Valid Json">
 | 
					              <SuccessAlert heading="Valid JSON" />
 | 
				
			||||||
            <></>
 | 
					 | 
				
			||||||
          </SuccessAlert>
 | 
					 | 
				
			||||||
            ) : (
 | 
					            ) : (
 | 
				
			||||||
              <ErrorAlert heading="Invalid JSON">
 | 
					              <ErrorAlert heading="Invalid JSON">
 | 
				
			||||||
            You must use valid json in this editor.
 | 
					                You must use valid JSON in this editor.
 | 
				
			||||||
              </ErrorAlert>
 | 
					              </ErrorAlert>
 | 
				
			||||||
            )}
 | 
					            )}
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					      </HeadedSection>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <Tab.Group>
 | 
					    <Tab.Group>
 | 
				
			||||||
      <div className=" flex-col flex">
 | 
					 | 
				
			||||||
      <div className="pb-4">
 | 
					      <div className="pb-4">
 | 
				
			||||||
          <Tab.List className="p-0.5 rounded-md bg-slate-100 hover:bg-slate-200 inline-flex">
 | 
					        <Tab.List className="flex w-fit p-0.5 rounded-md bg-slate-100 hover:bg-slate-200">
 | 
				
			||||||
            <StyledTab name="Code" iconName="code" />
 | 
					          <StyledTab name="Code" icon={CodeIcon} />
 | 
				
			||||||
            <StyledTab name="Sampling Settings" iconName="cog" />
 | 
					          <StyledTab name="Sampling Settings" icon={CogIcon} />
 | 
				
			||||||
            <StyledTab name="View Settings" iconName="squareBar" />
 | 
					          <StyledTab name="View Settings" icon={ChartSquareBarIcon} />
 | 
				
			||||||
            <StyledTab name="Input Variables" iconName="dollar" />
 | 
					          <StyledTab name="Input Variables" icon={CurrencyDollarIcon} />
 | 
				
			||||||
        </Tab.List>
 | 
					        </Tab.List>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
        <div className="flex" style={{ height: height + "px" }}>
 | 
					      <div className="flex" style={{ height }}>
 | 
				
			||||||
        <div className="w-1/2">
 | 
					        <div className="w-1/2">
 | 
				
			||||||
          <Tab.Panels>
 | 
					          <Tab.Panels>
 | 
				
			||||||
            <Tab.Panel>
 | 
					            <Tab.Panel>
 | 
				
			||||||
| 
						 | 
					@ -400,7 +408,7 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div className="w-1/2 p-2 pl-4">
 | 
					        <div className="w-1/2 p-2 pl-4">
 | 
				
			||||||
            <div style={{ maxHeight: height + "px" }}>
 | 
					          <div style={{ maxHeight: height }}>
 | 
				
			||||||
            <SquiggleChart
 | 
					            <SquiggleChart
 | 
				
			||||||
              squiggleString={squiggleString}
 | 
					              squiggleString={squiggleString}
 | 
				
			||||||
              environment={env}
 | 
					              environment={env}
 | 
				
			||||||
| 
						 | 
					@ -415,13 +423,12 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </Tab.Group>
 | 
					    </Tab.Group>
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
export default SquigglePlayground;
 | 
					export default SquigglePlayground;
 | 
				
			||||||
export function renderSquigglePlaygroundToDom(props: PlaygroundProps) {
 | 
					export function renderSquigglePlaygroundToDom(props: PlaygroundProps) {
 | 
				
			||||||
  let parent = document.createElement("div");
 | 
					  const parent = document.createElement("div");
 | 
				
			||||||
  ReactDOM.render(<SquigglePlayground {...props} />, parent);
 | 
					  ReactDOM.render(<SquigglePlayground {...props} />, parent);
 | 
				
			||||||
  return parent;
 | 
					  return parent;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,9 +5,9 @@ export {
 | 
				
			||||||
  renderSquiggleEditorToDom,
 | 
					  renderSquiggleEditorToDom,
 | 
				
			||||||
  renderSquigglePartialToDom,
 | 
					  renderSquigglePartialToDom,
 | 
				
			||||||
} from "./components/SquiggleEditor";
 | 
					} from "./components/SquiggleEditor";
 | 
				
			||||||
import SquigglePlayground, {
 | 
					export {
 | 
				
			||||||
 | 
					  default as SquigglePlayground,
 | 
				
			||||||
  renderSquigglePlaygroundToDom,
 | 
					  renderSquigglePlaygroundToDom,
 | 
				
			||||||
} from "./components/SquigglePlayground";
 | 
					} from "./components/SquigglePlayground";
 | 
				
			||||||
export { SquigglePlayground, renderSquigglePlaygroundToDom };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export { mergeBindings } from "@quri/squiggle-lang";
 | 
					export { mergeBindings } from "@quri/squiggle-lang";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
{"version":3,"file":"SquiggleChart.stories.js","sourceRoot":"","sources":["SquiggleChart.stories.tsx"],"names":[],"mappings":";;;AAAA,6BAA8B;AAC9B,iDAA+C;AAG/C,qBAAe;IACb,KAAK,EAAE,uBAAuB;IAC9B,SAAS,EAAE,6BAAa;CACzB,CAAA;AAED,IAAM,QAAQ,GAAG,UAAC,EAAgB;QAAf,cAAc,oBAAA;IAAM,OAAA,oBAAC,6BAAa,IAAC,cAAc,EAAE,cAAc,GAAI;AAAjD,CAAiD,CAAA;AAE3E,QAAA,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AACxC,eAAO,CAAC,IAAI,GAAG;IACb,cAAc,EAAE,cAAc;CAC/B,CAAC"}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,24 +1,26 @@
 | 
				
			||||||
const path = require("path");
 | 
					const path = require("path");
 | 
				
			||||||
 | 
					const MiniCssExtractPlugin = require("mini-css-extract-plugin");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
  mode: "production",
 | 
					  mode: "production",
 | 
				
			||||||
  devtool: "source-map",
 | 
					  devtool: "source-map",
 | 
				
			||||||
  profile: true,
 | 
					  profile: true,
 | 
				
			||||||
  entry: "./src/index.ts",
 | 
					  entry: ["./src/index.ts", "./src/tailwind.css"],
 | 
				
			||||||
  module: {
 | 
					  module: {
 | 
				
			||||||
    rules: [
 | 
					    rules: [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        test: /\.tsx?$/,
 | 
					        test: /\.tsx?$/,
 | 
				
			||||||
        loader: "ts-loader",
 | 
					        loader: "ts-loader",
 | 
				
			||||||
        options: { projectReferences: true, transpileOnly: true },
 | 
					        options: { projectReferences: true },
 | 
				
			||||||
        exclude: /node_modules/,
 | 
					        exclude: /node_modules/,
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        test: /\.css$/i,
 | 
					        test: /\.css$/i,
 | 
				
			||||||
        use: ["style-loader", "css-loader"],
 | 
					        use: [MiniCssExtractPlugin.loader, "css-loader", "postcss-loader"],
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					  plugins: [new MiniCssExtractPlugin()],
 | 
				
			||||||
  resolve: {
 | 
					  resolve: {
 | 
				
			||||||
    extensions: [".js", ".tsx", ".ts"],
 | 
					    extensions: [".js", ".tsx", ".ts"],
 | 
				
			||||||
    alias: {
 | 
					    alias: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -232,6 +232,7 @@ describe("Peggy parse", () => {
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
  describe("unit", () => {
 | 
					  describe("unit", () => {
 | 
				
			||||||
    testParse("1m", "{(::fromUnit_m 1)}")
 | 
					    testParse("1m", "{(::fromUnit_m 1)}")
 | 
				
			||||||
 | 
					    testParse("1M", "{(::fromUnit_M 1)}")
 | 
				
			||||||
    testParse("1m+2cm", "{(::add (::fromUnit_m 1) (::fromUnit_cm 2))}")
 | 
					    testParse("1m+2cm", "{(::add (::fromUnit_m 1) (::fromUnit_cm 2))}")
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,14 +56,14 @@
 | 
				
			||||||
    "lodash": "^4.17.21",
 | 
					    "lodash": "^4.17.21",
 | 
				
			||||||
    "moduleserve": "^0.9.1",
 | 
					    "moduleserve": "^0.9.1",
 | 
				
			||||||
    "nyc": "^15.1.0",
 | 
					    "nyc": "^15.1.0",
 | 
				
			||||||
    "peggy": "^2.0.0",
 | 
					    "peggy": "^2.0.1",
 | 
				
			||||||
    "reanalyze": "^2.22.0",
 | 
					    "reanalyze": "^2.22.0",
 | 
				
			||||||
    "rescript-fast-check": "^1.1.1",
 | 
					    "rescript-fast-check": "^1.1.1",
 | 
				
			||||||
    "ts-jest": "^27.1.4",
 | 
					    "ts-jest": "^27.1.4",
 | 
				
			||||||
    "ts-loader": "^9.3.0",
 | 
					    "ts-loader": "^9.3.0",
 | 
				
			||||||
    "ts-node": "^10.8.0",
 | 
					    "ts-node": "^10.8.1",
 | 
				
			||||||
    "typescript": "^4.7.2",
 | 
					    "typescript": "^4.7.3",
 | 
				
			||||||
    "webpack": "^5.72.1",
 | 
					    "webpack": "^5.73.0",
 | 
				
			||||||
    "webpack-cli": "^4.9.2"
 | 
					    "webpack-cli": "^4.9.2"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "source": "./src/js/index.ts",
 | 
					  "source": "./src/js/index.ts",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,7 @@ import {
 | 
				
			||||||
import { result, resultMap, Ok } from "./types";
 | 
					import { result, resultMap, Ok } from "./types";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  Constructors_mean,
 | 
					  Constructors_mean,
 | 
				
			||||||
 | 
					  Constructors_stdev,
 | 
				
			||||||
  Constructors_sample,
 | 
					  Constructors_sample,
 | 
				
			||||||
  Constructors_pdf,
 | 
					  Constructors_pdf,
 | 
				
			||||||
  Constructors_cdf,
 | 
					  Constructors_cdf,
 | 
				
			||||||
| 
						 | 
					@ -69,6 +70,10 @@ export class Distribution {
 | 
				
			||||||
    return Constructors_mean({ env: this.env }, this.t);
 | 
					    return Constructors_mean({ env: this.env }, this.t);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  stdev(): result<number, distributionError> {
 | 
				
			||||||
 | 
					    return Constructors_stdev({ env: this.env }, this.t);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  sample(): result<number, distributionError> {
 | 
					  sample(): result<number, distributionError> {
 | 
				
			||||||
    return Constructors_sample({ env: this.env }, this.t);
 | 
					    return Constructors_sample({ env: this.env }, this.t);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -265,6 +265,8 @@ module Constructors = {
 | 
				
			||||||
  module C = DistributionTypes.Constructors.UsingDists
 | 
					  module C = DistributionTypes.Constructors.UsingDists
 | 
				
			||||||
  open OutputLocal
 | 
					  open OutputLocal
 | 
				
			||||||
  let mean = (~env, dist) => C.mean(dist)->run(~env)->toFloatR
 | 
					  let mean = (~env, dist) => C.mean(dist)->run(~env)->toFloatR
 | 
				
			||||||
 | 
					  let stdev = (~env, dist) => C.stdev(dist)->run(~env)->toFloatR
 | 
				
			||||||
 | 
					  let variance = (~env, dist) => C.variance(dist)->run(~env)->toFloatR
 | 
				
			||||||
  let sample = (~env, dist) => C.sample(dist)->run(~env)->toFloatR
 | 
					  let sample = (~env, dist) => C.sample(dist)->run(~env)->toFloatR
 | 
				
			||||||
  let cdf = (~env, dist, f) => C.cdf(dist, f)->run(~env)->toFloatR
 | 
					  let cdf = (~env, dist, f) => C.cdf(dist, f)->run(~env)->toFloatR
 | 
				
			||||||
  let inv = (~env, dist, f) => C.inv(dist, f)->run(~env)->toFloatR
 | 
					  let inv = (~env, dist, f) => C.inv(dist, f)->run(~env)->toFloatR
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,10 @@ module Constructors: {
 | 
				
			||||||
  @genType
 | 
					  @genType
 | 
				
			||||||
  let mean: (~env: env, genericDist) => result<float, error>
 | 
					  let mean: (~env: env, genericDist) => result<float, error>
 | 
				
			||||||
  @genType
 | 
					  @genType
 | 
				
			||||||
 | 
					  let stdev: (~env: env, genericDist) => result<float, error>
 | 
				
			||||||
 | 
					  @genType
 | 
				
			||||||
 | 
					  let variance: (~env: env, genericDist) => result<float, error>
 | 
				
			||||||
 | 
					  @genType
 | 
				
			||||||
  let sample: (~env: env, genericDist) => result<float, error>
 | 
					  let sample: (~env: env, genericDist) => result<float, error>
 | 
				
			||||||
  @genType
 | 
					  @genType
 | 
				
			||||||
  let cdf: (~env: env, genericDist, float) => result<float, error>
 | 
					  let cdf: (~env: env, genericDist, float) => result<float, error>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,9 +30,9 @@ module Error = {
 | 
				
			||||||
  @genType
 | 
					  @genType
 | 
				
			||||||
  let toString = (err: error): string =>
 | 
					  let toString = (err: error): string =>
 | 
				
			||||||
    switch err {
 | 
					    switch err {
 | 
				
			||||||
    | NotYetImplemented => "Function Not Yet Implemented"
 | 
					    | NotYetImplemented => "Function not yet implemented"
 | 
				
			||||||
    | Unreachable => "Unreachable"
 | 
					    | Unreachable => "Unreachable"
 | 
				
			||||||
    | DistributionVerticalShiftIsInvalid => "Distribution Vertical Shift is Invalid"
 | 
					    | DistributionVerticalShiftIsInvalid => "Distribution vertical shift is invalid"
 | 
				
			||||||
    | ArgumentError(s) => `Argument Error ${s}`
 | 
					    | ArgumentError(s) => `Argument Error ${s}`
 | 
				
			||||||
    | LogarithmOfDistributionError(s) => `Logarithm of input error: ${s}`
 | 
					    | LogarithmOfDistributionError(s) => `Logarithm of input error: ${s}`
 | 
				
			||||||
    | SampleSetError(TooFewSamples) => "Too Few Samples"
 | 
					    | SampleSetError(TooFewSamples) => "Too Few Samples"
 | 
				
			||||||
| 
						 | 
					@ -68,6 +68,11 @@ module DistributionOperation = {
 | 
				
			||||||
    | #Mean
 | 
					    | #Mean
 | 
				
			||||||
    | #Sample
 | 
					    | #Sample
 | 
				
			||||||
    | #IntegralSum
 | 
					    | #IntegralSum
 | 
				
			||||||
 | 
					    | #Mode
 | 
				
			||||||
 | 
					    | #Stdev
 | 
				
			||||||
 | 
					    | #Min
 | 
				
			||||||
 | 
					    | #Max
 | 
				
			||||||
 | 
					    | #Variance
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  type toScaleFn = [
 | 
					  type toScaleFn = [
 | 
				
			||||||
| 
						 | 
					@ -117,6 +122,11 @@ module DistributionOperation = {
 | 
				
			||||||
    | ToFloat(#Cdf(r)) => `cdf(${E.Float.toFixed(r)})`
 | 
					    | ToFloat(#Cdf(r)) => `cdf(${E.Float.toFixed(r)})`
 | 
				
			||||||
    | ToFloat(#Inv(r)) => `inv(${E.Float.toFixed(r)})`
 | 
					    | ToFloat(#Inv(r)) => `inv(${E.Float.toFixed(r)})`
 | 
				
			||||||
    | ToFloat(#Mean) => `mean`
 | 
					    | ToFloat(#Mean) => `mean`
 | 
				
			||||||
 | 
					    | ToFloat(#Min) => `min`
 | 
				
			||||||
 | 
					    | ToFloat(#Max) => `max`
 | 
				
			||||||
 | 
					    | ToFloat(#Stdev) => `stdev`
 | 
				
			||||||
 | 
					    | ToFloat(#Variance) => `variance`
 | 
				
			||||||
 | 
					    | ToFloat(#Mode) => `mode`
 | 
				
			||||||
    | ToFloat(#Pdf(r)) => `pdf(${E.Float.toFixed(r)})`
 | 
					    | ToFloat(#Pdf(r)) => `pdf(${E.Float.toFixed(r)})`
 | 
				
			||||||
    | ToFloat(#Sample) => `sample`
 | 
					    | ToFloat(#Sample) => `sample`
 | 
				
			||||||
    | ToFloat(#IntegralSum) => `integralSum`
 | 
					    | ToFloat(#IntegralSum) => `integralSum`
 | 
				
			||||||
| 
						 | 
					@ -151,6 +161,8 @@ module Constructors = {
 | 
				
			||||||
  module UsingDists = {
 | 
					  module UsingDists = {
 | 
				
			||||||
    @genType
 | 
					    @genType
 | 
				
			||||||
    let mean = (dist): t => FromDist(ToFloat(#Mean), dist)
 | 
					    let mean = (dist): t => FromDist(ToFloat(#Mean), dist)
 | 
				
			||||||
 | 
					    let stdev = (dist): t => FromDist(ToFloat(#Stdev), dist)
 | 
				
			||||||
 | 
					    let variance = (dist): t => FromDist(ToFloat(#Variance), dist)
 | 
				
			||||||
    let sample = (dist): t => FromDist(ToFloat(#Sample), dist)
 | 
					    let sample = (dist): t => FromDist(ToFloat(#Sample), dist)
 | 
				
			||||||
    let cdf = (dist, x): t => FromDist(ToFloat(#Cdf(x)), dist)
 | 
					    let cdf = (dist, x): t => FromDist(ToFloat(#Cdf(x)), dist)
 | 
				
			||||||
    let inv = (dist, x): t => FromDist(ToFloat(#Inv(x)), dist)
 | 
					    let inv = (dist, x): t => FromDist(ToFloat(#Inv(x)), dist)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,7 +108,7 @@ let toFloatOperation = (
 | 
				
			||||||
) => {
 | 
					) => {
 | 
				
			||||||
  switch distToFloatOperation {
 | 
					  switch distToFloatOperation {
 | 
				
			||||||
  | #IntegralSum => Ok(integralEndY(t))
 | 
					  | #IntegralSum => Ok(integralEndY(t))
 | 
				
			||||||
  | (#Pdf(_) | #Cdf(_) | #Inv(_) | #Mean | #Sample) as op => {
 | 
					  | (#Pdf(_) | #Cdf(_) | #Inv(_) | #Mean | #Sample | #Min | #Max) as op => {
 | 
				
			||||||
      let trySymbolicSolution = switch (t: t) {
 | 
					      let trySymbolicSolution = switch (t: t) {
 | 
				
			||||||
      | Symbolic(r) => SymbolicDist.T.operate(op, r)->E.R.toOption
 | 
					      | Symbolic(r) => SymbolicDist.T.operate(op, r)->E.R.toOption
 | 
				
			||||||
      | _ => None
 | 
					      | _ => None
 | 
				
			||||||
| 
						 | 
					@ -118,6 +118,8 @@ let toFloatOperation = (
 | 
				
			||||||
      | (SampleSet(sampleSet), #Mean) => SampleSetDist.mean(sampleSet)->Some
 | 
					      | (SampleSet(sampleSet), #Mean) => SampleSetDist.mean(sampleSet)->Some
 | 
				
			||||||
      | (SampleSet(sampleSet), #Sample) => SampleSetDist.sample(sampleSet)->Some
 | 
					      | (SampleSet(sampleSet), #Sample) => SampleSetDist.sample(sampleSet)->Some
 | 
				
			||||||
      | (SampleSet(sampleSet), #Inv(r)) => SampleSetDist.percentile(sampleSet, r)->Some
 | 
					      | (SampleSet(sampleSet), #Inv(r)) => SampleSetDist.percentile(sampleSet, r)->Some
 | 
				
			||||||
 | 
					      | (SampleSet(sampleSet), #Min) => SampleSetDist.min(sampleSet)->Some
 | 
				
			||||||
 | 
					      | (SampleSet(sampleSet), #Max) => SampleSetDist.max(sampleSet)->Some
 | 
				
			||||||
      | _ => None
 | 
					      | _ => None
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -130,6 +132,16 @@ let toFloatOperation = (
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  | (#Stdev | #Variance | #Mode) as op =>
 | 
				
			||||||
 | 
					    switch t {
 | 
				
			||||||
 | 
					    | SampleSet(s) =>
 | 
				
			||||||
 | 
					      switch op {
 | 
				
			||||||
 | 
					      | #Stdev => SampleSetDist.stdev(s)->Ok
 | 
				
			||||||
 | 
					      | #Variance => SampleSetDist.variance(s)->Ok
 | 
				
			||||||
 | 
					      | #Mode => SampleSetDist.mode(s)->Ok
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    | _ => Error(DistributionTypes.NotYetImplemented)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -254,6 +254,8 @@ let operate = (distToFloatOp: Operation.distToFloatOperation, s): float =>
 | 
				
			||||||
  | #Inv(f) => inv(f, s)
 | 
					  | #Inv(f) => inv(f, s)
 | 
				
			||||||
  | #Sample => sample(s)
 | 
					  | #Sample => sample(s)
 | 
				
			||||||
  | #Mean => T.mean(s)
 | 
					  | #Mean => T.mean(s)
 | 
				
			||||||
 | 
					  | #Min => T.minX(s)
 | 
				
			||||||
 | 
					  | #Max => T.maxX(s)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let toSparkline = (t: t, bucketCount): result<string, PointSetTypes.sparklineError> =>
 | 
					let toSparkline = (t: t, bucketCount): result<string, PointSetTypes.sparklineError> =>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -449,6 +449,8 @@ module T = {
 | 
				
			||||||
    | #Cdf(f) => Ok(cdf(f, s))
 | 
					    | #Cdf(f) => Ok(cdf(f, s))
 | 
				
			||||||
    | #Pdf(f) => Ok(pdf(f, s))
 | 
					    | #Pdf(f) => Ok(pdf(f, s))
 | 
				
			||||||
    | #Inv(f) => Ok(inv(f, s))
 | 
					    | #Inv(f) => Ok(inv(f, s))
 | 
				
			||||||
 | 
					    | #Min => Ok(min(s))
 | 
				
			||||||
 | 
					    | #Max => Ok(max(s))
 | 
				
			||||||
    | #Sample => Ok(sample(s))
 | 
					    | #Sample => Ok(sample(s))
 | 
				
			||||||
    | #Mean => mean(s)
 | 
					    | #Mean => mean(s)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -264,6 +264,9 @@ basicLiteral
 | 
				
			||||||
identifier 'identifier'
 | 
					identifier 'identifier'
 | 
				
			||||||
  = ([_a-z]+[_a-z0-9]i*) {return nodeIdentifier(text())} 
 | 
					  = ([_a-z]+[_a-z0-9]i*) {return nodeIdentifier(text())} 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unitIdentifier 'identifier'
 | 
				
			||||||
 | 
					  = ([_a-zA-Z]+[_a-z0-9]i*) {return nodeIdentifier(text())} 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dollarIdentifier '$identifier'
 | 
					dollarIdentifier '$identifier'
 | 
				
			||||||
  = ([\$_a-z]+[\$_a-z0-9]i*) {return nodeIdentifier(text())} 
 | 
					  = ([\$_a-z]+[\$_a-z0-9]i*) {return nodeIdentifier(text())} 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -271,7 +274,7 @@ string 'string'
 | 
				
			||||||
  = characters:("'" @([^'])* "'") {return nodeString(characters.join(''))} 
 | 
					  = characters:("'" @([^'])* "'") {return nodeString(characters.join(''))} 
 | 
				
			||||||
  / characters:('"' @([^"])* '"') {return nodeString(characters.join(''))}
 | 
					  / characters:('"' @([^"])* '"') {return nodeString(characters.join(''))}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
number = number:(float / integer) unit:identifier?
 | 
					number = number:(float / integer) unit:unitIdentifier?
 | 
				
			||||||
  { 
 | 
					  { 
 | 
				
			||||||
    if (unit === null)
 | 
					    if (unit === null)
 | 
				
			||||||
      { return number }
 | 
					      { return number }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,27 @@
 | 
				
			||||||
 | 
					module EV = ReducerInterface_ExpressionValue
 | 
				
			||||||
 | 
					type expressionValue = EV.expressionValue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
 | 
				
			||||||
 | 
					  result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
 | 
				
			||||||
 | 
					> => {
 | 
				
			||||||
 | 
					  switch call {
 | 
				
			||||||
 | 
					  | ("toString", [EvDate(t)]) => EV.EvString(DateTime.Date.toString(t))->Ok->Some
 | 
				
			||||||
 | 
					  | ("makeDateFromYear", [EvNumber(year)]) =>
 | 
				
			||||||
 | 
					    switch DateTime.Date.makeFromYear(year) {
 | 
				
			||||||
 | 
					    | Ok(t) => EV.EvDate(t)->Ok->Some
 | 
				
			||||||
 | 
					    | Error(e) => Reducer_ErrorValue.RETodo(e)->Error->Some
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  | ("dateFromNumber", [EvNumber(f)]) => EV.EvDate(DateTime.Date.fromFloat(f))->Ok->Some
 | 
				
			||||||
 | 
					  | ("toNumber", [EvDate(f)]) => EV.EvNumber(DateTime.Date.toFloat(f))->Ok->Some
 | 
				
			||||||
 | 
					  | ("subtract", [EvDate(d1), EvDate(d2)]) =>
 | 
				
			||||||
 | 
					    switch DateTime.Date.subtract(d1, d2) {
 | 
				
			||||||
 | 
					    | Ok(d) => EV.EvTimeDuration(d)->Ok
 | 
				
			||||||
 | 
					    | Error(e) => Error(RETodo(e))
 | 
				
			||||||
 | 
					    }->Some
 | 
				
			||||||
 | 
					  | ("subtract", [EvDate(d1), EvTimeDuration(d2)]) =>
 | 
				
			||||||
 | 
					    EV.EvDate(DateTime.Date.subtractDuration(d1, d2))->Ok->Some
 | 
				
			||||||
 | 
					  | ("add", [EvDate(d1), EvTimeDuration(d2)]) =>
 | 
				
			||||||
 | 
					    EV.EvDate(DateTime.Date.addDuration(d1, d2))->Ok->Some
 | 
				
			||||||
 | 
					  | _ => None
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,32 +1,7 @@
 | 
				
			||||||
module EV = ReducerInterface_ExpressionValue
 | 
					module EV = ReducerInterface_ExpressionValue
 | 
				
			||||||
type expressionValue = EV.expressionValue
 | 
					type expressionValue = EV.expressionValue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let dateDispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
 | 
					let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
 | 
				
			||||||
  result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
 | 
					 | 
				
			||||||
> => {
 | 
					 | 
				
			||||||
  switch call {
 | 
					 | 
				
			||||||
  | ("toString", [EvDate(t)]) => EV.EvString(DateTime.Date.toString(t))->Ok->Some
 | 
					 | 
				
			||||||
  | ("makeDateFromYear", [EvNumber(year)]) =>
 | 
					 | 
				
			||||||
    switch DateTime.Date.makeFromYear(year) {
 | 
					 | 
				
			||||||
    | Ok(t) => EV.EvDate(t)->Ok->Some
 | 
					 | 
				
			||||||
    | Error(e) => Reducer_ErrorValue.RETodo(e)->Error->Some
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  | ("dateFromNumber", [EvNumber(f)]) => EV.EvDate(DateTime.Date.fromFloat(f))->Ok->Some
 | 
					 | 
				
			||||||
  | ("toNumber", [EvDate(f)]) => EV.EvNumber(DateTime.Date.toFloat(f))->Ok->Some
 | 
					 | 
				
			||||||
  | ("subtract", [EvDate(d1), EvDate(d2)]) =>
 | 
					 | 
				
			||||||
    switch DateTime.Date.subtract(d1, d2) {
 | 
					 | 
				
			||||||
    | Ok(d) => EV.EvTimeDuration(d)->Ok
 | 
					 | 
				
			||||||
    | Error(e) => Error(RETodo(e))
 | 
					 | 
				
			||||||
    }->Some
 | 
					 | 
				
			||||||
  | ("subtract", [EvDate(d1), EvTimeDuration(d2)]) =>
 | 
					 | 
				
			||||||
    EV.EvDate(DateTime.Date.subtractDuration(d1, d2))->Ok->Some
 | 
					 | 
				
			||||||
  | ("add", [EvDate(d1), EvTimeDuration(d2)]) =>
 | 
					 | 
				
			||||||
    EV.EvDate(DateTime.Date.addDuration(d1, d2))->Ok->Some
 | 
					 | 
				
			||||||
  | _ => None
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let durationDispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
 | 
					 | 
				
			||||||
  result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
 | 
					  result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
 | 
				
			||||||
> => {
 | 
					> => {
 | 
				
			||||||
  switch call {
 | 
					  switch call {
 | 
				
			||||||
| 
						 | 
					@ -55,16 +30,3 @@ let durationDispatch = (call: EV.functionCall, _: DistributionOperation.env): op
 | 
				
			||||||
  | _ => None
 | 
					  | _ => None
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
let dispatch = (call: EV.functionCall, env: DistributionOperation.env): option<
 | 
					 | 
				
			||||||
  result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
 | 
					 | 
				
			||||||
> => {
 | 
					 | 
				
			||||||
  switch dateDispatch(call, env) {
 | 
					 | 
				
			||||||
  | Some(r) => Some(r)
 | 
					 | 
				
			||||||
  | None =>
 | 
					 | 
				
			||||||
    switch durationDispatch(call, env) {
 | 
					 | 
				
			||||||
    | Some(r) => Some(r)
 | 
					 | 
				
			||||||
    | None => None
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -14,15 +14,27 @@ type expressionValue = ExpressionValue.expressionValue
 | 
				
			||||||
  Map external calls of Reducer
 | 
					  Map external calls of Reducer
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// I expect that it's important to build this first, so it doesn't get recalculated for each tryRegistry() call.
 | 
				
			||||||
 | 
					let registry = FunctionRegistry_Library.registry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let tryRegistry = ((fnName, args): ExpressionValue.functionCall, env) => {
 | 
				
			||||||
 | 
					  FunctionRegistry_Core.Registry.matchAndRun(~registry, ~fnName, ~args, ~env)->E.O2.fmap(
 | 
				
			||||||
 | 
					    E.R2.errMap(_, s => Reducer_ErrorValue.RETodo(s)),
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let dispatch = (call: ExpressionValue.functionCall, environment, chain): result<
 | 
					let dispatch = (call: ExpressionValue.functionCall, environment, chain): result<
 | 
				
			||||||
  expressionValue,
 | 
					  expressionValue,
 | 
				
			||||||
  'e,
 | 
					  'e,
 | 
				
			||||||
> =>
 | 
					> => {
 | 
				
			||||||
  switch ReducerInterface_GenericDistribution.dispatch(call, environment) {
 | 
					  E.A.O.firstSomeFn([
 | 
				
			||||||
  | Some(r) => r
 | 
					    () => ReducerInterface_GenericDistribution.dispatch(call, environment),
 | 
				
			||||||
  | None =>
 | 
					    () => ReducerInterface_Date.dispatch(call, environment),
 | 
				
			||||||
    ReducerInterface_DateTime.dispatch(call, environment) |> E.O.default(chain(call, environment))
 | 
					    () => ReducerInterface_Duration.dispatch(call, environment),
 | 
				
			||||||
  }
 | 
					    () => ReducerInterface_Number.dispatch(call, environment),
 | 
				
			||||||
 | 
					    () => tryRegistry(call, environment),
 | 
				
			||||||
 | 
					  ])->E.O2.default(chain(call, environment))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
If your dispatch is too big you can divide it into smaller dispatches and pass the call so that it gets called finally.
 | 
					If your dispatch is too big you can divide it into smaller dispatches and pass the call so that it gets called finally.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -209,7 +209,18 @@ let dispatchToGenericOutput = (
 | 
				
			||||||
  | ("sample", [EvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist, ~env)
 | 
					  | ("sample", [EvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist, ~env)
 | 
				
			||||||
  | ("sampleN", [EvDistribution(dist), EvNumber(n)]) =>
 | 
					  | ("sampleN", [EvDistribution(dist), EvNumber(n)]) =>
 | 
				
			||||||
    Some(FloatArray(GenericDist.sampleN(dist, Belt.Int.fromFloat(n))))
 | 
					    Some(FloatArray(GenericDist.sampleN(dist, Belt.Int.fromFloat(n))))
 | 
				
			||||||
  | ("mean", [EvDistribution(dist)]) => Helpers.toFloatFn(#Mean, dist, ~env)
 | 
					  | (("mean" | "stdev" | "variance" | "min" | "max" | "mode") as op, [EvDistribution(dist)]) => {
 | 
				
			||||||
 | 
					      let fn = switch op {
 | 
				
			||||||
 | 
					      | "mean" => #Mean
 | 
				
			||||||
 | 
					      | "stdev" => #Stdev
 | 
				
			||||||
 | 
					      | "variance" => #Variance
 | 
				
			||||||
 | 
					      | "min" => #Min
 | 
				
			||||||
 | 
					      | "max" => #Max
 | 
				
			||||||
 | 
					      | "mode" => #Mode
 | 
				
			||||||
 | 
					      | _ => #Mean
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      Helpers.toFloatFn(fn, dist, ~env)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  | ("integralSum", [EvDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist, ~env)
 | 
					  | ("integralSum", [EvDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist, ~env)
 | 
				
			||||||
  | ("toString", [EvDistribution(dist)]) => Helpers.toStringFn(ToString, dist, ~env)
 | 
					  | ("toString", [EvDistribution(dist)]) => Helpers.toStringFn(ToString, dist, ~env)
 | 
				
			||||||
  | ("toSparkline", [EvDistribution(dist)]) =>
 | 
					  | ("toSparkline", [EvDistribution(dist)]) =>
 | 
				
			||||||
| 
						 | 
					@ -350,20 +361,5 @@ let genericOutputToReducerValue = (o: DistributionOperation.outputType): result<
 | 
				
			||||||
  | GenDistError(err) => Error(REDistributionError(err))
 | 
					  | GenDistError(err) => Error(REDistributionError(err))
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// I expect that it's important to build this first, so it doesn't get recalculated for each tryRegistry() call.
 | 
					let dispatch = (call: ExpressionValue.functionCall, environment) =>
 | 
				
			||||||
let registry = FunctionRegistry_Library.registry
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let tryRegistry = ((fnName, args): ExpressionValue.functionCall, env) => {
 | 
					 | 
				
			||||||
  FunctionRegistry_Core.Registry.matchAndRun(~registry, ~fnName, ~args, ~env)->E.O2.fmap(
 | 
					 | 
				
			||||||
    E.R2.errMap(_, s => Reducer_ErrorValue.RETodo(s)),
 | 
					 | 
				
			||||||
  )
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
let dispatch = (call: ExpressionValue.functionCall, environment) => {
 | 
					 | 
				
			||||||
  let regularDispatch =
 | 
					 | 
				
			||||||
  dispatchToGenericOutput(call, environment)->E.O2.fmap(genericOutputToReducerValue)
 | 
					  dispatchToGenericOutput(call, environment)->E.O2.fmap(genericOutputToReducerValue)
 | 
				
			||||||
  switch regularDispatch {
 | 
					 | 
				
			||||||
  | Some(x) => Some(x)
 | 
					 | 
				
			||||||
  | None => tryRegistry(call, environment)
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,45 @@
 | 
				
			||||||
 | 
					module EV = ReducerInterface_ExpressionValue
 | 
				
			||||||
 | 
					type expressionValue = EV.expressionValue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module ScientificUnit = {
 | 
				
			||||||
 | 
					  let nameToMultiplier = str =>
 | 
				
			||||||
 | 
					    switch str {
 | 
				
			||||||
 | 
					    | "n" => Some(1E-9)
 | 
				
			||||||
 | 
					    | "m" => Some(1E-3)
 | 
				
			||||||
 | 
					    | "k" => Some(1E3)
 | 
				
			||||||
 | 
					    | "M" => Some(1E6)
 | 
				
			||||||
 | 
					    | "B" => Some(1E9)
 | 
				
			||||||
 | 
					    | "G" => Some(1E9)
 | 
				
			||||||
 | 
					    | "T" => Some(1E12)
 | 
				
			||||||
 | 
					    | "P" => Some(1E15)
 | 
				
			||||||
 | 
					    | _ => None
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let getMultiplier = (r: string) => {
 | 
				
			||||||
 | 
					    let match = Js.String2.match_(r, %re(`/fromUnit_([_a-zA-Z]*)/`))
 | 
				
			||||||
 | 
					    switch match {
 | 
				
			||||||
 | 
					    | Some([_, unit]) => nameToMultiplier(unit)
 | 
				
			||||||
 | 
					    | _ => None
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
 | 
				
			||||||
 | 
					  result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
 | 
				
			||||||
 | 
					> => {
 | 
				
			||||||
 | 
					  switch call {
 | 
				
			||||||
 | 
					  | (
 | 
				
			||||||
 | 
					      ("fromUnit_n"
 | 
				
			||||||
 | 
					      | "fromUnit_m"
 | 
				
			||||||
 | 
					      | "fromUnit_k"
 | 
				
			||||||
 | 
					      | "fromUnit_M"
 | 
				
			||||||
 | 
					      | "fromUnit_B"
 | 
				
			||||||
 | 
					      | "fromUnit_G"
 | 
				
			||||||
 | 
					      | "fromUnit_T"
 | 
				
			||||||
 | 
					      | "fromUnit_P") as op,
 | 
				
			||||||
 | 
					      [EvNumber(f)],
 | 
				
			||||||
 | 
					    ) =>
 | 
				
			||||||
 | 
					    op->ScientificUnit.getMultiplier->E.O2.fmap(multiplier => EV.EvNumber(f *. multiplier)->Ok)
 | 
				
			||||||
 | 
					  | _ => None
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,8 @@ type distToFloatOperation = [
 | 
				
			||||||
  | #Inv(float)
 | 
					  | #Inv(float)
 | 
				
			||||||
  | #Mean
 | 
					  | #Mean
 | 
				
			||||||
  | #Sample
 | 
					  | #Sample
 | 
				
			||||||
 | 
					  | #Min
 | 
				
			||||||
 | 
					  | #Max
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module Convolution = {
 | 
					module Convolution = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,27 +19,7 @@ const config = {
 | 
				
			||||||
  organizationName: "quantified-uncertainty", // Usually your GitHub org/user name.
 | 
					  organizationName: "quantified-uncertainty", // Usually your GitHub org/user name.
 | 
				
			||||||
  projectName: "squiggle", // Usually your repo name.
 | 
					  projectName: "squiggle", // Usually your repo name.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  plugins: [
 | 
					  plugins: [],
 | 
				
			||||||
    "docusaurus-tailwindcss",
 | 
					 | 
				
			||||||
    () => ({
 | 
					 | 
				
			||||||
      configureWebpack(config, isServer, utils, content) {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
          resolve: {
 | 
					 | 
				
			||||||
            alias: {
 | 
					 | 
				
			||||||
              "@quri/squiggle-components": path.resolve(
 | 
					 | 
				
			||||||
                __dirname,
 | 
					 | 
				
			||||||
                "../components/src"
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
              "@quri/squiggle-lang": path.resolve(
 | 
					 | 
				
			||||||
                __dirname,
 | 
					 | 
				
			||||||
                "../squiggle-lang/src/js"
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
          },
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    }),
 | 
					 | 
				
			||||||
  ],
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  presets: [
 | 
					  presets: [
 | 
				
			||||||
    [
 | 
					    [
 | 
				
			||||||
| 
						 | 
					@ -61,7 +41,10 @@ const config = {
 | 
				
			||||||
            "https://github.com/quantified-uncertainty/squiggle/tree/develop/packages/website/",
 | 
					            "https://github.com/quantified-uncertainty/squiggle/tree/develop/packages/website/",
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        theme: {
 | 
					        theme: {
 | 
				
			||||||
          customCss: require.resolve("./src/css/custom.css"),
 | 
					          customCss: [
 | 
				
			||||||
 | 
					            require.resolve("./src/css/custom.css"),
 | 
				
			||||||
 | 
					            require.resolve("@quri/squiggle-components/dist/main.css"),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      }),
 | 
					      }),
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
[build]
 | 
					[build]
 | 
				
			||||||
    base = "packages/website/"
 | 
					    base = "packages/website/"
 | 
				
			||||||
    command = "cd ../squiggle-lang && yarn build && cd ../website && yarn build"
 | 
					    command = "cd ../squiggle-lang && yarn build && cd ../components && yarn build && cd ../website && yarn build"
 | 
				
			||||||
    publish = "build/"
 | 
					    publish = "build/"
 | 
				
			||||||
    ignore = "node -e 'process.exitCode = process.env.BRANCH.includes(\"dependabot\") ? 0 : 1' && git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF ../"
 | 
					    ignore = "node -e 'process.exitCode = process.env.BRANCH.includes(\"dependabot\") ? 0 : 1' && git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF ../"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,10 +4,6 @@
 | 
				
			||||||
 * work well for content-centric websites.
 | 
					 * work well for content-centric websites.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@tailwind base;
 | 
					 | 
				
			||||||
@tailwind components;
 | 
					 | 
				
			||||||
@tailwind utilities;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* You can override the default Infima variables here. */
 | 
					/* You can override the default Infima variables here. */
 | 
				
			||||||
:root {
 | 
					:root {
 | 
				
			||||||
  --ifm-color-primary: #2488df;
 | 
					  --ifm-color-primary: #2488df;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										7
									
								
								packages/website/tailwind.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								packages/website/tailwind.config.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,7 @@
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
					  content: ["./src/**/*.{html,tsx,ts,js,jsx}"],
 | 
				
			||||||
 | 
					  theme: {
 | 
				
			||||||
 | 
					    extend: {},
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  plugins: [require("@tailwindcss/forms")],
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										1
									
								
								packages/website/webpack.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								packages/website/webpack.config.js
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					module.exports = {};
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user