Merge branch 'develop' into error-locations
This commit is contained in:
commit
298492b3b8
17
.github/workflows/ci.yml
vendored
17
.github/workflows/ci.yml
vendored
|
@ -11,6 +11,7 @@ on:
|
||||||
- develop
|
- develop
|
||||||
- reducer-dev
|
- reducer-dev
|
||||||
- epic-reducer-project
|
- epic-reducer-project
|
||||||
|
- epic-0.5.0
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pre_check:
|
pre_check:
|
||||||
|
@ -25,27 +26,27 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- id: skip_lang_check
|
- id: skip_lang_check
|
||||||
name: Check if the changes are about squiggle-lang src files
|
name: Check if the changes are about squiggle-lang src files
|
||||||
uses: fkirc/skip-duplicate-actions@v4.0.0
|
uses: fkirc/skip-duplicate-actions@v5.2.0
|
||||||
with:
|
with:
|
||||||
paths: '["packages/squiggle-lang/**"]'
|
paths: '["packages/squiggle-lang/**"]'
|
||||||
- id: skip_components_check
|
- id: skip_components_check
|
||||||
name: Check if the changes are about components src files
|
name: Check if the changes are about components src files
|
||||||
uses: fkirc/skip-duplicate-actions@v4.0.0
|
uses: fkirc/skip-duplicate-actions@v5.2.0
|
||||||
with:
|
with:
|
||||||
paths: '["packages/components/**"]'
|
paths: '["packages/components/**"]'
|
||||||
- id: skip_website_check
|
- id: skip_website_check
|
||||||
name: Check if the changes are about website src files
|
name: Check if the changes are about website src files
|
||||||
uses: fkirc/skip-duplicate-actions@v4.0.0
|
uses: fkirc/skip-duplicate-actions@v5.2.0
|
||||||
with:
|
with:
|
||||||
paths: '["packages/website/**"]'
|
paths: '["packages/website/**"]'
|
||||||
- id: skip_vscodeext_check
|
- id: skip_vscodeext_check
|
||||||
name: Check if the changes are about vscode extension src files
|
name: Check if the changes are about vscode extension src files
|
||||||
uses: fkirc/skip-duplicate-actions@v4.0.0
|
uses: fkirc/skip-duplicate-actions@v5.2.0
|
||||||
with:
|
with:
|
||||||
paths: '["packages/vscode-ext/**"]'
|
paths: '["packages/vscode-ext/**"]'
|
||||||
- id: skip_cli_check
|
- id: skip_cli_check
|
||||||
name: Check if the changes are about cli src files
|
name: Check if the changes are about cli src files
|
||||||
uses: fkirc/skip-duplicate-actions@v4.0.0
|
uses: fkirc/skip-duplicate-actions@v5.2.0
|
||||||
with:
|
with:
|
||||||
paths: '["packages/cli/**"]'
|
paths: '["packages/cli/**"]'
|
||||||
|
|
||||||
|
@ -115,8 +116,8 @@ jobs:
|
||||||
dry: true
|
dry: true
|
||||||
prettier_options: --check packages/components --ignore-path packages/components/.prettierignore
|
prettier_options: --check packages/components --ignore-path packages/components/.prettierignore
|
||||||
|
|
||||||
components-bundle-build:
|
components-bundle-build-test:
|
||||||
name: Components bundle and build
|
name: Components bundle, build and test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: pre_check
|
needs: pre_check
|
||||||
if: ${{ (needs.pre_check.outputs.should_skip_components != 'true') || (needs.pre_check.outputs.should_skip_lang != 'true') }}
|
if: ${{ (needs.pre_check.outputs.should_skip_components != 'true') || (needs.pre_check.outputs.should_skip_lang != 'true') }}
|
||||||
|
@ -134,6 +135,8 @@ jobs:
|
||||||
run: yarn bundle
|
run: yarn bundle
|
||||||
- name: Build storybook
|
- name: Build storybook
|
||||||
run: yarn build
|
run: yarn build
|
||||||
|
- name: Test components
|
||||||
|
run: yarn test
|
||||||
|
|
||||||
website-lint:
|
website-lint:
|
||||||
name: Website lint
|
name: Website lint
|
||||||
|
|
10
.github/workflows/release-please.yml
vendored
10
.github/workflows/release-please.yml
vendored
|
@ -18,27 +18,27 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- id: skip_lang_check
|
- id: skip_lang_check
|
||||||
name: Check if the changes are about squiggle-lang src files
|
name: Check if the changes are about squiggle-lang src files
|
||||||
uses: fkirc/skip-duplicate-actions@v4.0.0
|
uses: fkirc/skip-duplicate-actions@v5.2.0
|
||||||
with:
|
with:
|
||||||
paths: '["packages/squiggle-lang/**"]'
|
paths: '["packages/squiggle-lang/**"]'
|
||||||
- id: skip_components_check
|
- id: skip_components_check
|
||||||
name: Check if the changes are about components src files
|
name: Check if the changes are about components src files
|
||||||
uses: fkirc/skip-duplicate-actions@v4.0.0
|
uses: fkirc/skip-duplicate-actions@v5.2.0
|
||||||
with:
|
with:
|
||||||
paths: '["packages/components/**"]'
|
paths: '["packages/components/**"]'
|
||||||
- id: skip_website_check
|
- id: skip_website_check
|
||||||
name: Check if the changes are about website src files
|
name: Check if the changes are about website src files
|
||||||
uses: fkirc/skip-duplicate-actions@v4.0.0
|
uses: fkirc/skip-duplicate-actions@v5.2.0
|
||||||
with:
|
with:
|
||||||
paths: '["packages/website/**"]'
|
paths: '["packages/website/**"]'
|
||||||
- id: skip_vscodeext_check
|
- id: skip_vscodeext_check
|
||||||
name: Check if the changes are about vscode extension src files
|
name: Check if the changes are about vscode extension src files
|
||||||
uses: fkirc/skip-duplicate-actions@v4.0.0
|
uses: fkirc/skip-duplicate-actions@v5.2.0
|
||||||
with:
|
with:
|
||||||
paths: '["packages/vscode-ext/**"]'
|
paths: '["packages/vscode-ext/**"]'
|
||||||
- id: skip_cli_check
|
- id: skip_cli_check
|
||||||
name: Check if the changes are about cli src files
|
name: Check if the changes are about cli src files
|
||||||
uses: fkirc/skip-duplicate-actions@v4.0.0
|
uses: fkirc/skip-duplicate-actions@v5.2.0
|
||||||
with:
|
with:
|
||||||
paths: '["packages/cli/**"]'
|
paths: '["packages/cli/**"]'
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chalk": "^5.0.1",
|
"chalk": "^5.0.1",
|
||||||
"chokidar": "^3.5.3",
|
"chokidar": "^3.5.3",
|
||||||
"commander": "^9.4.0",
|
"commander": "^9.4.1",
|
||||||
"fs": "^0.0.1-security",
|
"fs": "^0.0.1-security",
|
||||||
"glob": "^8.0.3",
|
"glob": "^8.0.3",
|
||||||
"indent-string": "^5.0.0"
|
"indent-string": "^5.0.0"
|
||||||
|
|
6
packages/components/jest.config.js
Normal file
6
packages/components/jest.config.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
||||||
|
module.exports = {
|
||||||
|
preset: "ts-jest",
|
||||||
|
setupFilesAfterEnv: ["<rootDir>/test/setup.js"],
|
||||||
|
testEnvironment: "jsdom",
|
||||||
|
};
|
|
@ -1,21 +1,21 @@
|
||||||
{
|
{
|
||||||
"name": "@quri/squiggle-components",
|
"name": "@quri/squiggle-components",
|
||||||
"version": "0.5.0-alpha.2",
|
"version": "0.5.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@floating-ui/react-dom": "^1.0.0",
|
"@floating-ui/react-dom": "^1.0.0",
|
||||||
"@floating-ui/react-dom-interactions": "^0.10.1",
|
"@floating-ui/react-dom-interactions": "^0.10.1",
|
||||||
"@headlessui/react": "^1.7.2",
|
"@headlessui/react": "^1.7.3",
|
||||||
"@heroicons/react": "^1.0.6",
|
"@heroicons/react": "^1.0.6",
|
||||||
"@hookform/resolvers": "^2.9.8",
|
"@hookform/resolvers": "^2.9.8",
|
||||||
"@quri/squiggle-lang": "^0.5.0-alpha.2",
|
"@quri/squiggle-lang": "^0.5.0",
|
||||||
"@react-hook/size": "^2.1.2",
|
"@react-hook/size": "^2.1.2",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"framer-motion": "^7.3.5",
|
"framer-motion": "^7.5.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"react": "^18.1.0",
|
"react": "^18.1.0",
|
||||||
"react-ace": "^10.1.0",
|
"react-ace": "^10.1.0",
|
||||||
"react-hook-form": "^7.35.0",
|
"react-hook-form": "^7.36.1",
|
||||||
"react-use": "^17.4.0",
|
"react-use": "^17.4.0",
|
||||||
"react-vega": "^7.6.0",
|
"react-vega": "^7.6.0",
|
||||||
"vega": "^5.22.1",
|
"vega": "^5.22.1",
|
||||||
|
@ -38,12 +38,16 @@
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^14.4.3",
|
"@testing-library/user-event": "^14.4.3",
|
||||||
"@types/jest": "^27.5.0",
|
"@types/jest": "^27.5.0",
|
||||||
"@types/lodash": "^4.14.185",
|
"@types/lodash": "^4.14.186",
|
||||||
"@types/node": "^18.7.18",
|
"@types/node": "^18.8.0",
|
||||||
"@types/react": "^18.0.18",
|
"@types/react": "^18.0.21",
|
||||||
"@types/styled-components": "^5.1.26",
|
"@types/styled-components": "^5.1.26",
|
||||||
"@types/webpack": "^5.28.0",
|
"@types/webpack": "^5.28.0",
|
||||||
|
"canvas": "^2.10.1",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
|
"jest": "^29.0.3",
|
||||||
|
"jest-environment-jsdom": "^29.0.3",
|
||||||
|
"jsdom": "^20.0.0",
|
||||||
"mini-css-extract-plugin": "^2.6.1",
|
"mini-css-extract-plugin": "^2.6.1",
|
||||||
"postcss-cli": "^10.0.0",
|
"postcss-cli": "^10.0.0",
|
||||||
"postcss-import": "^15.0.0",
|
"postcss-import": "^15.0.0",
|
||||||
|
@ -53,13 +57,14 @@
|
||||||
"react-scripts": "^5.0.1",
|
"react-scripts": "^5.0.1",
|
||||||
"style-loader": "^3.3.1",
|
"style-loader": "^3.3.1",
|
||||||
"tailwindcss": "^3.1.8",
|
"tailwindcss": "^3.1.8",
|
||||||
"ts-loader": "^9.4.0",
|
"ts-jest": "^29.0.2",
|
||||||
|
"ts-loader": "^9.4.1",
|
||||||
"tsconfig-paths-webpack-plugin": "^4.0.0",
|
"tsconfig-paths-webpack-plugin": "^4.0.0",
|
||||||
"typescript": "^4.8.3",
|
"typescript": "^4.8.4",
|
||||||
"web-vitals": "^3.0.2",
|
"web-vitals": "^3.0.2",
|
||||||
"webpack": "^5.74.0",
|
"webpack": "^5.74.0",
|
||||||
"webpack-cli": "^4.10.0",
|
"webpack-cli": "^4.10.0",
|
||||||
"webpack-dev-server": "^4.11.0"
|
"webpack-dev-server": "^4.11.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^16.8.0 || ^17 || ^18",
|
"react": "^16.8.0 || ^17 || ^18",
|
||||||
|
@ -75,7 +80,9 @@
|
||||||
"all": "yarn bundle && yarn build",
|
"all": "yarn bundle && yarn build",
|
||||||
"lint": "prettier --check .",
|
"lint": "prettier --check .",
|
||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
"prepack": "yarn run build:cjs && yarn run bundle"
|
"prepack": "yarn run build:cjs && yarn run bundle",
|
||||||
|
"test": "jest",
|
||||||
|
"test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": [
|
"extends": [
|
||||||
|
|
|
@ -83,18 +83,32 @@ export const DistributionChart: React.FC<DistributionChartProps> = (props) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const spec = buildVegaSpec(props);
|
const domain = shapes.value.flatMap((shape) =>
|
||||||
|
shape.discrete.concat(shape.continuous)
|
||||||
|
);
|
||||||
|
|
||||||
let widthProp = width ? width : size.width;
|
const spec = buildVegaSpec({
|
||||||
|
...props,
|
||||||
|
minX: props.minX ?? Math.min(...domain.map((x) => x.x)),
|
||||||
|
maxX: props.minX ?? Math.max(...domain.map((x) => x.x)),
|
||||||
|
maxY: Math.max(...domain.map((x) => x.y)),
|
||||||
|
});
|
||||||
|
|
||||||
|
// I think size.width is sometimes not finite due to the component not being in a visible context
|
||||||
|
// This occurs during testing
|
||||||
|
let widthProp = width
|
||||||
|
? width
|
||||||
|
: Number.isFinite(size.width)
|
||||||
|
? size.width
|
||||||
|
: 400;
|
||||||
if (widthProp < 20) {
|
if (widthProp < 20) {
|
||||||
console.warn(
|
console.warn(
|
||||||
`Width of Distribution is set to ${widthProp}, which is too small`
|
`Width of Distribution is set to ${widthProp}, which is too small`
|
||||||
);
|
);
|
||||||
widthProp = 20;
|
widthProp = 20;
|
||||||
}
|
}
|
||||||
const domain = shapes.value.flatMap((shape) =>
|
|
||||||
shape.discrete.concat(shape.continuous)
|
const vegaData = { data: shapes.value, samples };
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ width: widthProp }}>
|
<div style={{ width: widthProp }}>
|
||||||
|
@ -105,7 +119,7 @@ export const DistributionChart: React.FC<DistributionChartProps> = (props) => {
|
||||||
) : (
|
) : (
|
||||||
<Vega
|
<Vega
|
||||||
spec={spec}
|
spec={spec}
|
||||||
data={{ data: shapes.value, domain, samples }}
|
data={vegaData}
|
||||||
width={widthProp - 10}
|
width={widthProp - 10}
|
||||||
height={height}
|
height={height}
|
||||||
actions={actions}
|
actions={actions}
|
||||||
|
|
|
@ -299,7 +299,7 @@ export const ExpressionViewer: React.FC<Props> = ({ value, width }) => {
|
||||||
<div>
|
<div>
|
||||||
<span>No display for type: </span>{" "}
|
<span>No display for type: </span>{" "}
|
||||||
<span className="font-semibold text-slate-600">
|
<span className="font-semibold text-slate-600">
|
||||||
{(value as any).tag}
|
{(value as { tag: string }).tag}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -26,7 +26,6 @@ export const linearXScale: LinearScale = {
|
||||||
range: "width",
|
range: "width",
|
||||||
zero: false,
|
zero: false,
|
||||||
nice: false,
|
nice: false,
|
||||||
domain: { data: "domain", field: "x" },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const logXScale: LogScale = {
|
export const logXScale: LogScale = {
|
||||||
|
@ -37,7 +36,6 @@ export const logXScale: LogScale = {
|
||||||
base: 10,
|
base: 10,
|
||||||
nice: false,
|
nice: false,
|
||||||
clamp: true,
|
clamp: true,
|
||||||
domain: { data: "domain", field: "x" },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const timeXScale: TimeScale = {
|
export const timeXScale: TimeScale = {
|
||||||
|
@ -46,7 +44,6 @@ export const timeXScale: TimeScale = {
|
||||||
type: "time",
|
type: "time",
|
||||||
range: "width",
|
range: "width",
|
||||||
nice: false,
|
nice: false,
|
||||||
domain: { data: "domain", field: "x" },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Y Scales */
|
/** Y Scales */
|
||||||
|
@ -55,7 +52,6 @@ export const linearYScale: LinearScale = {
|
||||||
type: "linear",
|
type: "linear",
|
||||||
range: "height",
|
range: "height",
|
||||||
zero: true,
|
zero: true,
|
||||||
domain: { data: "domain", field: "y" },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const expYScale: PowScale = {
|
export const expYScale: PowScale = {
|
||||||
|
@ -65,7 +61,6 @@ export const expYScale: PowScale = {
|
||||||
range: "height",
|
range: "height",
|
||||||
zero: true,
|
zero: true,
|
||||||
nice: false,
|
nice: false,
|
||||||
domain: { data: "domain", field: "y" },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const defaultTickFormat = ".9~s";
|
export const defaultTickFormat = ".9~s";
|
||||||
|
@ -73,9 +68,17 @@ export const timeTickFormat = "%b %d, %Y %H:%M";
|
||||||
const width = 500;
|
const width = 500;
|
||||||
|
|
||||||
export function buildVegaSpec(
|
export function buildVegaSpec(
|
||||||
specOptions: DistributionChartSpecOptions
|
specOptions: DistributionChartSpecOptions & { maxY: number }
|
||||||
): VisualizationSpec {
|
): VisualizationSpec {
|
||||||
const { title, minX, maxX, logX, expY, xAxisType = "number" } = specOptions;
|
const {
|
||||||
|
title,
|
||||||
|
minX,
|
||||||
|
maxX,
|
||||||
|
logX,
|
||||||
|
expY,
|
||||||
|
xAxisType = "number",
|
||||||
|
maxY,
|
||||||
|
} = specOptions;
|
||||||
|
|
||||||
const dateTime = xAxisType === "dateTime";
|
const dateTime = xAxisType === "dateTime";
|
||||||
|
|
||||||
|
@ -88,13 +91,15 @@ export function buildVegaSpec(
|
||||||
|
|
||||||
let xScale = dateTime ? timeXScale : logX ? logXScale : linearXScale;
|
let xScale = dateTime ? timeXScale : logX ? logXScale : linearXScale;
|
||||||
|
|
||||||
if (minX !== undefined && Number.isFinite(minX)) {
|
xScale = {
|
||||||
xScale = { ...xScale, domainMin: minX };
|
...xScale,
|
||||||
}
|
domain: [minX ?? 0, maxX ?? 1],
|
||||||
|
domainMin: minX,
|
||||||
|
domainMax: maxX,
|
||||||
|
};
|
||||||
|
|
||||||
if (maxX !== undefined && Number.isFinite(maxX)) {
|
let yScale = expY ? expYScale : linearYScale;
|
||||||
xScale = { ...xScale, domainMax: maxX };
|
yScale = { ...yScale, domain: [0, maxY ?? 1], domainMin: 0, domainMax: maxY };
|
||||||
}
|
|
||||||
|
|
||||||
const spec: VisualizationSpec = {
|
const spec: VisualizationSpec = {
|
||||||
$schema: "https://vega.github.io/schema/vega/v5.json",
|
$schema: "https://vega.github.io/schema/vega/v5.json",
|
||||||
|
@ -128,7 +133,7 @@ export function buildVegaSpec(
|
||||||
],
|
],
|
||||||
scales: [
|
scales: [
|
||||||
xScale,
|
xScale,
|
||||||
expY ? expYScale : linearYScale,
|
yScale,
|
||||||
{
|
{
|
||||||
name: "color",
|
name: "color",
|
||||||
type: "ordinal",
|
type: "ordinal",
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
import { SquigglePartial, SquiggleEditor } from "../components/SquiggleEditor";
|
|
||||||
import { useState } from "react";
|
|
||||||
import { Canvas, Meta, Story, Props } from "@storybook/addon-docs";
|
|
||||||
|
|
||||||
<Meta title="Squiggle/SquigglePartial" component={SquigglePartial} />
|
|
||||||
|
|
||||||
export const Template = (props) => <SquigglePartial {...props} />;
|
|
||||||
|
|
||||||
# Squiggle Partial
|
|
||||||
|
|
||||||
A Squiggle Partial is an editor that does not return a graph to the user, but
|
|
||||||
instead returns bindings that can be used by further Squiggle Editors.
|
|
||||||
|
|
||||||
<Canvas>
|
|
||||||
<Story
|
|
||||||
name="Standalone"
|
|
||||||
args={{
|
|
||||||
defaultCode: "x = normal(5,2)",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{Template.bind({})}
|
|
||||||
</Story>
|
|
||||||
</Canvas>
|
|
||||||
|
|
||||||
<Canvas>
|
|
||||||
<Story
|
|
||||||
name="With Editor"
|
|
||||||
args={{
|
|
||||||
initialPartialString: "x = normal(5,2)",
|
|
||||||
initialEditorString: "x",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{(props) => {
|
|
||||||
let [bindings, setBindings] = useState({});
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<SquigglePartial
|
|
||||||
{...props}
|
|
||||||
defaultCode={props.initialPartialString}
|
|
||||||
onChange={setBindings}
|
|
||||||
/>
|
|
||||||
<SquiggleEditor
|
|
||||||
{...props}
|
|
||||||
defaultCode={props.initialEditorString}
|
|
||||||
bindings={bindings}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Story>
|
|
||||||
</Canvas>
|
|
13
packages/components/test/basic.test.tsx
Normal file
13
packages/components/test/basic.test.tsx
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import { render } from "@testing-library/react";
|
||||||
|
import React from "react";
|
||||||
|
import "@testing-library/jest-dom";
|
||||||
|
import { SquiggleChart } from "../src/index";
|
||||||
|
|
||||||
|
test("Logs no warnings or errors", async () => {
|
||||||
|
debugger;
|
||||||
|
const { unmount } = render(<SquiggleChart code={"normal(0, 1)"} />);
|
||||||
|
unmount();
|
||||||
|
|
||||||
|
expect(console.warn).not.toBeCalled();
|
||||||
|
expect(console.error).not.toBeCalled();
|
||||||
|
});
|
8
packages/components/test/setup.js
Normal file
8
packages/components/test/setup.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
global.console = {
|
||||||
|
...console,
|
||||||
|
log: jest.fn(console.log),
|
||||||
|
debug: jest.fn(console.debug),
|
||||||
|
info: jest.fn(console.info),
|
||||||
|
warn: jest.fn(console.warn),
|
||||||
|
error: jest.fn(console.error),
|
||||||
|
};
|
|
@ -182,7 +182,7 @@ describe("Peggy parse", () => {
|
||||||
"a.p1 to a.p2",
|
"a.p1 to a.p2",
|
||||||
"{(:credibleIntervalToDistribution (:$_atIndex_$ :a 'p1') (:$_atIndex_$ :a 'p2'))}",
|
"{(:credibleIntervalToDistribution (:$_atIndex_$ :a 'p1') (:$_atIndex_$ :a 'p2'))}",
|
||||||
) // lower than post
|
) // lower than post
|
||||||
testParse("1 to 2 + 3", "{(:add (:credibleIntervalToDistribution 1 2) 3)}") // higher than binary operators
|
testParse("1 to 2 + 3", "{(:credibleIntervalToDistribution 1 (:add 2 3))}")
|
||||||
testParse(
|
testParse(
|
||||||
"1->add(2) to 3->add(4) -> add(4)",
|
"1->add(2) to 3->add(4) -> add(4)",
|
||||||
"{(:credibleIntervalToDistribution (:add 1 2) (:add (:add 3 4) 4))}",
|
"{(:credibleIntervalToDistribution (:add 1 2) (:add (:add 3 4) 4))}",
|
||||||
|
|
|
@ -112,6 +112,25 @@ describe("project2", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("removing sources", () => {
|
||||||
|
let project = Project.createProject()
|
||||||
|
Project.setContinues(project, "main", ["second"])
|
||||||
|
Project.setContinues(project, "second", ["first"])
|
||||||
|
Project.setSource(project, "first", "x=1")
|
||||||
|
Project.setSource(project, "second", "y=2")
|
||||||
|
Project.setSource(project, "main", "y")
|
||||||
|
|
||||||
|
Project.removeSource(project, "main")
|
||||||
|
|
||||||
|
test("project doesn't have source", () => {
|
||||||
|
expect(Project.getSource(project, "main")) == None
|
||||||
|
})
|
||||||
|
|
||||||
|
test("dependents get updated", () => {
|
||||||
|
expect(Project.getDependents(project, "second")) == []
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("project with include", () => {
|
describe("project with include", () => {
|
||||||
let project = Project.createProject()
|
let project = Project.createProject()
|
||||||
Project.setContinues(project, "main", ["second"])
|
Project.setContinues(project, "main", ["second"])
|
||||||
|
|
|
@ -98,6 +98,7 @@ describe("eval on distribution functions", () => {
|
||||||
"log(normal(5,2), normal(10,1))",
|
"log(normal(5,2), normal(10,1))",
|
||||||
"Error(Distribution Math Error: Logarithm of input error: First input must be completely greater than 0)",
|
"Error(Distribution Math Error: Logarithm of input error: First input must be completely greater than 0)",
|
||||||
)
|
)
|
||||||
|
testEval("log(2, SampleSet.fromDist(0.0001 to 5))", "Ok(Sample Set Distribution)") // log with low values, see https://github.com/quantified-uncertainty/squiggle/issues/1098
|
||||||
testEval("log(uniform(5,8))", "Ok(Sample Set Distribution)")
|
testEval("log(uniform(5,8))", "Ok(Sample Set Distribution)")
|
||||||
testEval("log10(uniform(5,8))", "Ok(Sample Set Distribution)")
|
testEval("log10(uniform(5,8))", "Ok(Sample Set Distribution)")
|
||||||
})
|
})
|
||||||
|
|
|
@ -82,7 +82,10 @@ describe("FunctionRegistry Library", () => {
|
||||||
)
|
)
|
||||||
|
|
||||||
testEvalToBe("Dict.merge({a: 1, b: 2}, {b: 3, c: 4, d: 5})", "Ok({a: 1,b: 3,c: 4,d: 5})")
|
testEvalToBe("Dict.merge({a: 1, b: 2}, {b: 3, c: 4, d: 5})", "Ok({a: 1,b: 3,c: 4,d: 5})")
|
||||||
testEvalToBe("Dict.mergeMany([{a: 1, b: 2}, {c: 3, d: 4}, {c: 5, e: 6}])", "Ok({a: 1,b: 2,c: 5,d: 4,e: 6})")
|
testEvalToBe(
|
||||||
|
"Dict.mergeMany([{a: 1, b: 2}, {c: 3, d: 4}, {c: 5, e: 6}])",
|
||||||
|
"Ok({a: 1,b: 2,c: 5,d: 4,e: 6})",
|
||||||
|
)
|
||||||
testEvalToBe("Dict.keys({a: 1, b: 2})", "Ok(['a','b'])")
|
testEvalToBe("Dict.keys({a: 1, b: 2})", "Ok(['a','b'])")
|
||||||
testEvalToBe("Dict.values({a: 1, b: 2})", "Ok([1,2])")
|
testEvalToBe("Dict.values({a: 1, b: 2})", "Ok([1,2])")
|
||||||
testEvalToBe("Dict.toList({a: 1, b: 2})", "Ok([['a',1],['b',2]])")
|
testEvalToBe("Dict.toList({a: 1, b: 2})", "Ok([['a',1],['b',2]])")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@quri/squiggle-lang",
|
"name": "@quri/squiggle-lang",
|
||||||
"version": "0.5.0-alpha.2",
|
"version": "0.5.0",
|
||||||
"homepage": "https://squiggle-language.com",
|
"homepage": "https://squiggle-language.com",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
"bisect_ppx": "^2.7.1",
|
"bisect_ppx": "^2.7.1",
|
||||||
"chalk": "^5.0.1",
|
"chalk": "^5.0.1",
|
||||||
"codecov": "^3.8.3",
|
"codecov": "^3.8.3",
|
||||||
"fast-check": "^3.1.3",
|
"fast-check": "^3.1.4",
|
||||||
"gentype": "^4.5.0",
|
"gentype": "^4.5.0",
|
||||||
"jest": "^27.5.1",
|
"jest": "^27.5.1",
|
||||||
"moduleserve": "^0.9.1",
|
"moduleserve": "^0.9.1",
|
||||||
|
@ -68,9 +68,9 @@
|
||||||
"rescript-fast-check": "^1.1.1",
|
"rescript-fast-check": "^1.1.1",
|
||||||
"rescript-js-map": "^1.1.0",
|
"rescript-js-map": "^1.1.0",
|
||||||
"ts-jest": "^27.1.4",
|
"ts-jest": "^27.1.4",
|
||||||
"ts-loader": "^9.4.0",
|
"ts-loader": "^9.4.1",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "^4.8.3",
|
"typescript": "^4.8.4",
|
||||||
"webpack": "^5.74.0",
|
"webpack": "^5.74.0",
|
||||||
"webpack-cli": "^4.10.0"
|
"webpack-cli": "^4.10.0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -22,6 +22,10 @@ export class SqProject {
|
||||||
return RSProject.setSource(this._value, sourceId, value);
|
return RSProject.setSource(this._value, sourceId, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeSource(sourceId: string) {
|
||||||
|
RSProject.removeSource(this._value, sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
getSource(sourceId: string) {
|
getSource(sourceId: string) {
|
||||||
return RSProject.getSource(this._value, sourceId);
|
return RSProject.getSource(this._value, sourceId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,7 @@ let toFloatOperation = (
|
||||||
| (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), #Min) => SampleSetDist.min(sampleSet)->Some
|
||||||
| (SampleSet(sampleSet), #Max) => SampleSetDist.max(sampleSet)->Some
|
| (SampleSet(sampleSet), #Max) => SampleSetDist.max(sampleSet)->Some
|
||||||
|
| (SampleSet(sampleSet), #Cdf(r)) => SampleSetDist.cdf(sampleSet, r)->Some
|
||||||
| _ => None
|
| _ => None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,22 +278,14 @@ module AlgebraicCombination = {
|
||||||
Right now we don't yet have a way of getting probability mass, so I'll leave this for later.
|
Right now we don't yet have a way of getting probability mass, so I'll leave this for later.
|
||||||
*/
|
*/
|
||||||
let getLogarithmInputError = (t1: t, t2: t, ~toPointSetFn: toPointSetFn): option<error> => {
|
let getLogarithmInputError = (t1: t, t2: t, ~toPointSetFn: toPointSetFn): option<error> => {
|
||||||
let firstOperandIsGreaterThanZero =
|
let isDistGreaterThanZero = t =>
|
||||||
toFloatOperation(
|
toFloatOperation(
|
||||||
t1,
|
t,
|
||||||
~toPointSetFn,
|
~toPointSetFn,
|
||||||
~distToFloatOperation=#Cdf(MagicNumbers.Epsilon.ten),
|
~distToFloatOperation=#Cdf(MagicNumbers.Epsilon.ten),
|
||||||
) |> E.R.fmap(r => r > 0.)
|
)->E.R2.fmap(r => r > 0.)
|
||||||
let secondOperandIsGreaterThanZero =
|
|
||||||
toFloatOperation(
|
let items = E.A.R.firstErrorOrOpen([isDistGreaterThanZero(t1), isDistGreaterThanZero(t2)])
|
||||||
t2,
|
|
||||||
~toPointSetFn,
|
|
||||||
~distToFloatOperation=#Cdf(MagicNumbers.Epsilon.ten),
|
|
||||||
) |> E.R.fmap(r => r > 0.)
|
|
||||||
let items = E.A.R.firstErrorOrOpen([
|
|
||||||
firstOperandIsGreaterThanZero,
|
|
||||||
secondOperandIsGreaterThanZero,
|
|
||||||
])
|
|
||||||
switch items {
|
switch items {
|
||||||
| Error(r) => Some(r)
|
| Error(r) => Some(r)
|
||||||
| Ok([true, _]) =>
|
| Ok([true, _]) =>
|
||||||
|
|
|
@ -131,6 +131,10 @@ let max = t => T.get(t)->E.A.Floats.max
|
||||||
let stdev = t => T.get(t)->E.A.Floats.stdev
|
let stdev = t => T.get(t)->E.A.Floats.stdev
|
||||||
let variance = t => T.get(t)->E.A.Floats.variance
|
let variance = t => T.get(t)->E.A.Floats.variance
|
||||||
let percentile = (t, f) => T.get(t)->E.A.Floats.percentile(f)
|
let percentile = (t, f) => T.get(t)->E.A.Floats.percentile(f)
|
||||||
|
let cdf = (t: t, f: float) => {
|
||||||
|
let countBelowF = t->E.A.reduce(0, (acc, x) => acc + (x <= f ? 1 : 0))
|
||||||
|
countBelowF->Js.Int.toFloat /. t->length->Js.Int.toFloat
|
||||||
|
}
|
||||||
|
|
||||||
let mixture = (values: array<(t, float)>, intendedLength: int) => {
|
let mixture = (values: array<(t, float)>, intendedLength: int) => {
|
||||||
let totalWeight = values->E.A2.fmap(E.Tuple2.second)->E.A.Floats.sum
|
let totalWeight = values->E.A2.fmap(E.Tuple2.second)->E.A.Floats.sum
|
||||||
|
|
|
@ -51,6 +51,13 @@ Sets the source for a given source Id.
|
||||||
let setSource = (project: reducerProject, sourceId: string, value: string): unit =>
|
let setSource = (project: reducerProject, sourceId: string, value: string): unit =>
|
||||||
project->Private.setSource(sourceId, value)
|
project->Private.setSource(sourceId, value)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Removes the source for a given source Id.
|
||||||
|
*/
|
||||||
|
@genType
|
||||||
|
let removeSource = (project: reducerProject, sourceId: string): unit =>
|
||||||
|
project->Private.removeSource(sourceId)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Gets the source for a given source id.
|
Gets the source for a given source id.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -98,12 +98,20 @@ equality
|
||||||
equalityOp "operator" = '=='/'!='
|
equalityOp "operator" = '=='/'!='
|
||||||
|
|
||||||
relational
|
relational
|
||||||
= left:additive _ operator:relationalOp _nl right:additive
|
= left:credibleInterval _ operator:relationalOp _nl right:credibleInterval
|
||||||
{ return h.makeFunctionCall(h.toFunction[operator], [left, right], location())}
|
{ return h.makeFunctionCall(h.toFunction[operator], [left, right], location())}
|
||||||
/ additive
|
/ credibleInterval
|
||||||
|
|
||||||
relationalOp "operator" = '<='/'<'/'>='/'>'
|
relationalOp "operator" = '<='/'<'/'>='/'>'
|
||||||
|
|
||||||
|
credibleInterval
|
||||||
|
= head:additive tail:(__ operator:credibleIntervalOp __nl arg:additive {return {operator: operator, right: arg}})*
|
||||||
|
{ return tail.reduce(function(result, element) {
|
||||||
|
return h.makeFunctionCall(h.toFunction[element.operator], [result, element.right], location())
|
||||||
|
}, head)}
|
||||||
|
|
||||||
|
credibleIntervalOp "operator" = 'to'
|
||||||
|
|
||||||
additive
|
additive
|
||||||
= head:multiplicative tail:(_ operator:additiveOp _nl arg:multiplicative {return {operator: operator, right: arg}})*
|
= head:multiplicative tail:(_ operator:additiveOp _nl arg:multiplicative {return {operator: operator, right: arg}})*
|
||||||
{ return tail.reduce(function(result, element) {
|
{ return tail.reduce(function(result, element) {
|
||||||
|
@ -121,21 +129,13 @@ multiplicative
|
||||||
multiplicativeOp "operator" = '*' / '/' / '.*' / './'
|
multiplicativeOp "operator" = '*' / '/' / '.*' / './'
|
||||||
|
|
||||||
power
|
power
|
||||||
= head:credibleInterval tail:(_ operator:powerOp _nl arg:credibleInterval {return {operator: operator, right: arg}})*
|
= head:chainFunctionCall tail:(_ operator:powerOp _nl arg:chainFunctionCall {return {operator: operator, right: arg}})*
|
||||||
{ return tail.reduce(function(result, element) {
|
{ return tail.reduce(function(result, element) {
|
||||||
return h.makeFunctionCall(h.toFunction[element.operator], [result, element.right], location())
|
return h.makeFunctionCall(h.toFunction[element.operator], [result, element.right], location())
|
||||||
}, head)}
|
}, head)}
|
||||||
|
|
||||||
powerOp "operator" = '^' / '.^'
|
powerOp "operator" = '^' / '.^'
|
||||||
|
|
||||||
credibleInterval
|
|
||||||
= head:chainFunctionCall tail:(__ operator:credibleIntervalOp __nl arg:chainFunctionCall {return {operator: operator, right: arg}})*
|
|
||||||
{ return tail.reduce(function(result, element) {
|
|
||||||
return h.makeFunctionCall(h.toFunction[element.operator], [result, element.right], location())
|
|
||||||
}, head)}
|
|
||||||
|
|
||||||
credibleIntervalOp "operator" = 'to'
|
|
||||||
|
|
||||||
chainFunctionCall
|
chainFunctionCall
|
||||||
= head:unary tail:(_ ('->'/'|>') _nl chained:chainedFunction {return chained})*
|
= head:unary tail:(_ ('->'/'|>') _nl chained:chainedFunction {return chained})*
|
||||||
{ return tail.reduce(function(result, element) {
|
{ return tail.reduce(function(result, element) {
|
||||||
|
|
|
@ -60,6 +60,10 @@ let setSource = (project: t, sourceId: string, value: string): unit => {
|
||||||
touchDependents(project, sourceId)
|
touchDependents(project, sourceId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let removeSource = (project: t, sourceId: string): unit => {
|
||||||
|
Belt.MutableMap.String.remove(project.items, sourceId)
|
||||||
|
}
|
||||||
|
|
||||||
let clean = (project: t, sourceId: string): unit => {
|
let clean = (project: t, sourceId: string): unit => {
|
||||||
let newItem = project->getItem(sourceId)->ProjectItem.clean
|
let newItem = project->getItem(sourceId)->ProjectItem.clean
|
||||||
project->setItem(sourceId, newItem)
|
project->setItem(sourceId, newItem)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"displayName": "Squiggle",
|
"displayName": "Squiggle",
|
||||||
"description": "Squiggle language support",
|
"description": "Squiggle language support",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "0.5.0-alpha.2",
|
"version": "0.5.0",
|
||||||
"publisher": "QURI",
|
"publisher": "QURI",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -131,7 +131,7 @@
|
||||||
"@types/vscode": "^1.70.0",
|
"@types/vscode": "^1.70.0",
|
||||||
"glob": "^8.0.3",
|
"glob": "^8.0.3",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"typescript": "^4.8.3",
|
"typescript": "^4.8.4",
|
||||||
"vsce-yarn-patch": "^1.66.2"
|
"vsce-yarn-patch": "^1.66.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
@ -12,7 +12,7 @@ All regular distribution function work on sample set distributions. In addition,
|
||||||
### fromDist
|
### fromDist
|
||||||
|
|
||||||
```
|
```
|
||||||
SampleSet.fromDist: (list<number>) => sampleSet
|
SampleSet.fromDist: (distribution) => sampleSet
|
||||||
```
|
```
|
||||||
|
|
||||||
### fromList
|
### fromList
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
---
|
|
||||||
sidebar_position: 6
|
|
||||||
title: Function
|
|
||||||
---
|
|
||||||
|
|
||||||
## declare (experimental)
|
|
||||||
|
|
||||||
Adds metadata to a function of the input ranges. Works now for numeric and date inputs. This is useful when making formal predictions. It allows you to limit the domain that your prediction will be used and scored within.
|
|
||||||
|
|
||||||
The one function that declarations currently have is that they impact plotting. If you `declare` a single-variable function within a specific range, this specific range will be plotted.
|
|
||||||
|
|
||||||
Declarations are currently experimental and will likely be removed or changed in the future.
|
|
||||||
|
|
||||||
```
|
|
||||||
Function.declare: (dict<{fn: lambda, inputs: array<dict<{min: number, max: number}>>}>) => declaration
|
|
||||||
```
|
|
||||||
|
|
||||||
**Examples**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
Function.declare({
|
|
||||||
fn: {|a| a+10 },
|
|
||||||
inputs: [
|
|
||||||
{min: 30, max: 100}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
```
|
|
|
@ -52,29 +52,30 @@ const config = {
|
||||||
themeConfig:
|
themeConfig:
|
||||||
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
|
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
|
||||||
({
|
({
|
||||||
algolia: {
|
// TODO - disabled until we fix algolia search
|
||||||
// The application ID provided by Algolia
|
// algolia: {
|
||||||
appId: "KBED3M1CMD",
|
// // The application ID provided by Algolia
|
||||||
|
// appId: "KBED3M1CMD",
|
||||||
|
|
||||||
// Public API key: it is safe to commit it
|
// // Public API key: it is safe to commit it
|
||||||
apiKey: "c61bc7603893cf287ed6971983af8bad",
|
// apiKey: "c61bc7603893cf287ed6971983af8bad",
|
||||||
|
|
||||||
indexName: "squiggle_docs",
|
// indexName: "squiggle_docs",
|
||||||
|
|
||||||
// Optional: see doc section below
|
// // Optional: see doc section below
|
||||||
contextualSearch: true,
|
// contextualSearch: true,
|
||||||
|
|
||||||
// Optional: Specify domains where the navigation should occur through window.location instead on history.push. Useful when our Algolia config crawls multiple documentation sites and we want to navigate with window.location.href to them.
|
// // Optional: Specify domains where the navigation should occur through window.location instead on history.push. Useful when our Algolia config crawls multiple documentation sites and we want to navigate with window.location.href to them.
|
||||||
// externalUrlRegex: 'external\\.com|domain\\.com',
|
// // externalUrlRegex: 'external\\.com|domain\\.com',
|
||||||
|
|
||||||
// Optional: Algolia search parameters
|
// // Optional: Algolia search parameters
|
||||||
searchParameters: {},
|
// searchParameters: {},
|
||||||
|
|
||||||
// Optional: path for search page that enabled by default (`false` to disable it)
|
// // Optional: path for search page that enabled by default (`false` to disable it)
|
||||||
searchPagePath: "search",
|
// searchPagePath: "search",
|
||||||
|
|
||||||
//... other Algolia params
|
// //... other Algolia params
|
||||||
},
|
// },
|
||||||
navbar: {
|
navbar: {
|
||||||
title: "Squiggle",
|
title: "Squiggle",
|
||||||
hideOnScroll: true,
|
hideOnScroll: true,
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
"@docusaurus/core": "2.1.0",
|
"@docusaurus/core": "2.1.0",
|
||||||
"@docusaurus/preset-classic": "2.1.0",
|
"@docusaurus/preset-classic": "2.1.0",
|
||||||
"@heroicons/react": "^1.0.6",
|
"@heroicons/react": "^1.0.6",
|
||||||
"@quri/squiggle-components": "^0.5.0-alpha.2",
|
"@quri/squiggle-components": "^0.5.0",
|
||||||
"base64-js": "^1.5.1",
|
"base64-js": "^1.5.1",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"hast-util-is-element": "2.1.2",
|
"hast-util-is-element": "2.1.2",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user