Run prettier on monorepo + fix crashing playground

This commit is contained in:
Sam Nolan 2022-04-12 15:41:36 +10:00
parent 26433c5289
commit 440bfabffa
36 changed files with 452 additions and 388 deletions

View File

@ -1,14 +1,13 @@
---
name: Developer friction when contributing to Squiggle
about: Did your yarn scripts fail? Did the CI diverge from a README? Have a testing-related task? Etc.
labels: 'ops & testing'
labels: "ops & testing"
---
# Description:
# The OS and version, yarn version, etc. in which this came up
_delete this section if testing task_
# Desired behavior

View File

@ -2,6 +2,5 @@
name: Idea or feature request
about: Where would you like to see Squiggle go over the next few months, several months, or few years?
---
# Description

View File

@ -1,14 +1,13 @@
---
name: Regarding the programming language
about: Interpreter, parser, syntax, semantics, and including distributions
labels: 'programming language'
labels: "programming language"
---
<!-- mark one with an x -->
- _ Is refactor
- _ Is new feature
- _ Concerns documentation
- \_ Is refactor
- \_ Is new feature
- \_ Concerns documentation
# Description of suggestion or shortcoming:

View File

@ -1,18 +1,17 @@
---
name: Bug reports for Squiggle users
about: Rendering oddly, trouble with the playground, something like this?
labels: 'bug'
labels: "bug"
---
# Description:
# Steps to reproduce:
1.
2.
3.
# Expected behavior:
# What I got instead:

View File

@ -1,14 +1,13 @@
name: Squiggle packages check
on:
push: # Delete this line if there becomes a scarcity of build minutes.
push: # Delete this line if there becomes a scarcity of build minutes.
pull_request:
branches:
- master
- staging
jobs:
pre_check:
name: Precheck for skipping redundant jobs
runs-on: ubuntu-latest
@ -43,15 +42,15 @@ jobs:
shell: bash
working-directory: packages/squiggle-lang
steps:
- uses: actions/checkout@v2
- name: Install dependencies from monorepo level
run: cd ../../ && yarn
- name: Build rescript codebase
run: yarn build
- name: Run tests
run: yarn test
- name: Run webpack
run: yarn bundle
- uses: actions/checkout@v2
- name: Install dependencies from monorepo level
run: cd ../../ && yarn
- name: Build rescript codebase
run: yarn build
- name: Run tests
run: yarn test
- name: Run webpack
run: yarn bundle
components-build-test:
name: Components build and test
@ -63,15 +62,15 @@ jobs:
shell: bash
working-directory: packages/components
steps:
- uses: actions/checkout@v2
- name: Install dependencies from monorepo level
run: cd ../../ && yarn
- name: Build rescript codebase in squiggle-lang
run: cd ../squiggle-lang && yarn build
- name: Run webpack
run: yarn bundle
- name: Build storybook
run: yarn build
- uses: actions/checkout@v2
- name: Install dependencies from monorepo level
run: cd ../../ && yarn
- name: Build rescript codebase in squiggle-lang
run: cd ../squiggle-lang && yarn build
- name: Run webpack
run: yarn bundle
- name: Build storybook
run: yarn build
website-build:
name: Website build
@ -83,10 +82,10 @@ jobs:
shell: bash
working-directory: packages/website
steps:
- uses: actions/checkout@v2
- name: Install dependencies from monorepo level
run: cd ../../ && yarn
- name: Build rescript in squiggle-lang
run: cd ../squiggle-lang && yarn build
- name: Build website assets
run: yarn build
- uses: actions/checkout@v2
- name: Install dependencies from monorepo level
run: cd ../../ && yarn
- name: Build rescript in squiggle-lang
run: cd ../squiggle-lang && yarn build
- name: Build website assets
run: yarn build

View File

@ -14,15 +14,15 @@ name: "CodeQL"
on:
push:
branches:
- master
- staging
- master
- staging
pull_request:
# The branches below must be a subset of the branches above
branches:
- master
- staging
- master
- staging
schedule:
- cron: '42 19 * * 0'
- cron: "42 19 * * 0"
jobs:
analyze:
@ -36,39 +36,39 @@ jobs:
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
language: ["javascript"]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

9
.prettierignore Normal file
View File

@ -0,0 +1,9 @@
.direnv
*.bs.js
*.gen.tsx
packages/*/dist
packages/components/storybook-static
node_modules
packages/*/node_modules
packages/website/.docusaurus
packages/squiggle-lang/lib

View File

@ -21,6 +21,7 @@ Anyone (with a github account) can file an issue at any time. Please allow Quinn
# Project structure
Squiggle is a **monorepo** with four **packages**.
- **components** is where we improve reactive interfacing with Squiggle
- **playground** is the site `playground.squiggle-language.com`
- **squiggle-lang** is where the magic happens: probability distributions, the interpreter, etc.
@ -41,6 +42,7 @@ We aspire for `ci.yaml` and `README.md`s to be in one-to-one correspondence.
## If you're on NixOS
You'll need to run a command like this in order to get `yarn build` to run, especially in `packages/squiggle-lang`.
```sh
patchelf --set-interpreter $(patchelf --print-interpreter $(which mkdir)) ./node_modules/gentype/gentype.exe
```

View File

@ -1,4 +1,5 @@
# Squiggle
![Packages check](https://github.com/QURIresearch/squiggle/actions/workflows/ci.yaml/badge.svg)
[![npm version](https://badge.fury.io/js/@quri%2Fsquiggle-lang.svg)](https://www.npmjs.com/package/@quri/squiggle-lang)
[![npm version](https://badge.fury.io/js/@quri%2Fsquiggle-components.svg)](https://www.npmjs.com/package/@quri/squiggle-components)
@ -12,17 +13,18 @@ This is an experimental DSL/language for making probabilistic estimates. The ful
- **old playground**: https://playground.squiggle-language.com
## Packages
This monorepo has several packages that can be used for various purposes. All
the packages can be found in `packages`.
- `@quri/squiggle-lang` in `packages/squiggle-lang` contains the core language, particularly
an interface to parse squiggle expressions and return descriptions of distributions
or results.
an interface to parse squiggle expressions and return descriptions of distributions
or results.
- `@quri/squiggle-components` in `packages/components` contains React components that
can be passed squiggle strings as props, and return a presentation of the result
of the calculation.
can be passed squiggle strings as props, and return a presentation of the result
of the calculation.
- `@quri/squiggle-website` in `packages/website` The main descriptive website for squiggle,
it is hosted at `squiggle-language.com`.
it is hosted at `squiggle-language.com`.
The playground depends on the components library which then depends on the language. This means that if you wish to work on the components library, you will need to build (no need to bundle) the language, and as of this writing playground doesn't really work.
@ -30,7 +32,7 @@ The playground depends on the components library which then depends on the langu
For any project in the repo, begin by running `yarn` in the top level (TODO: is this true?)
``` sh
```sh
yarn
```
@ -40,7 +42,7 @@ See `packages/*/README.md` to work with whatever project you're interested in.
If you have `nix` installed with `flakes` enabled, you can build a `codium` in this repo for `rescript` development, if you don't want to pollute your machine's global editor with another mode/extension.
``` sh
```sh
nix develop
codium
```
@ -48,4 +50,5 @@ codium
The `nix develop` shell also provides `yarn`.
# Contributing
See `CONTRIBUTING.md`.

View File

@ -8,7 +8,8 @@
"packages/*"
],
"resolutions": {
"@types/react": "^17.0.43"
"@types/react": "^18.0.1",
"react": "^18.0.0"
},
"packageManager": "yarn@1.22.17"
}

View File

@ -1,5 +0,0 @@
dist
build
node_modules
storybook-static
.storybook

View File

@ -1,31 +1,37 @@
//const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const custom = require('../webpack.config.js');
const custom = require("../webpack.config.js");
module.exports = {
webpackFinal: async (config) => {
webpackFinal: async (config) => {
config.resolve.alias = custom.resolve.alias;
return { ...config, module: { ...config.module, rules: config.module.rules.concat(custom.module.rules.filter(x => x.loader === "ts-loader")) } };
return {
...config,
module: {
...config.module,
rules: config.module.rules.concat(
custom.module.rules.filter((x) => x.loader === "ts-loader")
),
},
};
},
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.@(js|jsx|ts|tsx)"
],
"addons": [
stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/preset-create-react-app"
"@storybook/preset-create-react-app",
],
"framework": "@storybook/react",
"core": {
"builder": "webpack5"
framework: "@storybook/react",
core: {
builder: "webpack5",
},
typescript: {
check: false,
checkOptions: {},
reactDocgen: 'react-docgen-typescript',
reactDocgen: "react-docgen-typescript",
reactDocgenTypescriptOptions: {
shouldExtractLiteralValuesFromEnum: true,
propFilter: (prop) => (prop.parent ? !/node_modules/.test(prop.parent.fileName) : true),
propFilter: (prop) =>
prop.parent ? !/node_modules/.test(prop.parent.fileName) : true,
},
},
}
};

View File

@ -6,4 +6,4 @@ export const parameters = {
date: /Date$/,
},
},
}
};

View File

@ -15,10 +15,10 @@
"cross-env": "^7.0.3",
"lodash": "^4.17.21",
"react": "^18.0.0",
"react-ace": "9.5.0",
"react-dom": "^18.0.0",
"react-scripts": "5.0.0",
"react-vega": "^7.5.0",
"react-ace": "9.5.0",
"styled-components": "^5.3.5",
"tsconfig-paths-webpack-plugin": "^3.5.2",
"typescript": "^4.6.3",
@ -63,9 +63,6 @@
]
},
"devDependencies": {
"@types/styled-components": "^5.1.24",
"css-loader": "^6.7.1",
"style-loader": "^3.3.1",
"@babel/plugin-proposal-private-property-in-object": "^7.16.7",
"@storybook/addon-actions": "^6.4.20",
"@storybook/addon-essentials": "^6.4.20",
@ -75,9 +72,13 @@
"@storybook/node-logger": "^6.4.20",
"@storybook/preset-create-react-app": "^4.1.0",
"@storybook/react": "^6.4.20",
"@types/styled-components": "^5.1.24",
"@types/webpack": "^4.41.32",
"css-loader": "^6.7.1",
"prettier": "^2.6.2",
"react-codejar": "^1.1.2",
"speed-measure-webpack-plugin": "^1.5.0",
"style-loader": "^3.3.1",
"ts-loader": "^9.2.8",
"webpack": "^5.72.0",
"webpack-cli": "^4.9.2",

View File

@ -1,10 +1,8 @@
import * as React from "react";
import _ from "lodash";
import type { Spec } from "vega";
import type {
Distribution,
} from "@quri/squiggle-lang";
import { distributionErrorToString } from '@quri/squiggle-lang';
import type { Distribution } from "@quri/squiggle-lang";
import { distributionErrorToString } from "@quri/squiggle-lang";
import { createClassFromSpec } from "react-vega";
import * as chartSpecification from "../vega-specs/spec-distributions.json";
@ -16,12 +14,14 @@ type DistributionChartProps = {
distribution: Distribution;
width: number;
height: number;
}
};
export const DistributionChart: React.FC<DistributionChartProps> = ({ distribution, width, height }: DistributionChartProps) => {
console.log("Making shape")
export const DistributionChart: React.FC<DistributionChartProps> = ({
distribution,
width,
height,
}: DistributionChartProps) => {
let shape = distribution.shape();
console.log(shape)
if (shape.tag === "Ok") {
return (
<SquiggleVegaChart
@ -31,8 +31,7 @@ export const DistributionChart: React.FC<DistributionChartProps> = ({ distributi
actions={false}
/>
);
}
else{
} else {
return <> {distributionErrorToString(shape.value)} </>;
}
};

View File

@ -7,10 +7,10 @@ const ShowError = styled.div`
padding: 0.4em 0.8em;
`;
export const Error: React.FC<{ heading: string; children: React.ReactNode }> = ({
heading = "Error",
children,
}) => {
export const ErrorBox: React.FC<{
heading: string;
children: React.ReactNode;
}> = ({ heading = "Error", children }) => {
return (
<ShowError>
<h3>{heading}</h3>

View File

@ -5,15 +5,13 @@ import type { Distribution, errorValue, result } from "@quri/squiggle-lang";
import { createClassFromSpec } from "react-vega";
import * as percentilesSpec from "../vega-specs/spec-percentiles.json";
import { DistributionChart } from "./DistributionChart";
import { Error } from "./Error";
import { ErrorBox } from "./ErrorBox";
let SquigglePercentilesChart = createClassFromSpec({
spec: percentilesSpec as Spec,
});
type distPlusFn = (
a: number
) => result<Distribution, errorValue>
type distPlusFn = (a: number) => result<Distribution, errorValue>;
const _rangeByCount = (start: number, stop: number, count: number) => {
const step = (stop - start) / (count - 1);
@ -22,11 +20,26 @@ const _rangeByCount = (start: number, stop: number, count: number) => {
return result;
};
function unwrap<a, b>( x: result<a, b>): a {
if(x.tag === "Ok"){
return x.value
function unwrap<a, b>(x: result<a, b>): a {
if (x.tag === "Ok") {
return x.value;
} else {
throw Error("FAILURE TO UNWRAP");
}
}
function mapFilter<a, b>(xs: a[], f: (x: a) => b | undefined): b[] {
let initial: b[] = [];
return xs.reduce((previous, current) => {
let value: b | undefined = f(current);
if (value !== undefined) {
return previous.concat([value]);
} else {
return previous;
}
}, initial);
}
export const FunctionChart: React.FC<{
distPlusFn: distPlusFn;
diagramStart: number;
@ -44,46 +57,45 @@ export const FunctionChart: React.FC<{
let mouseItem = distPlusFn(mouseOverlay);
let showChart =
mouseItem.tag === "Ok" ? (
<DistributionChart distribution={mouseItem.value} width={400} height={140} />
<DistributionChart
distribution={mouseItem.value}
width={400}
height={140}
/>
) : (
<></>
);
let data1 = _rangeByCount(diagramStart, diagramStop, diagramCount);
let valueData = data1
.map((x) => {
let result = distPlusFn(x);
if (result.tag === "Ok") {
return { x: x, value: result.value };
} else return null;
})
.filter((x) => x !== null)
.map(({ x, value }) => {
return {
x: x,
p1: unwrap(value.inv(0.01)),
p5: unwrap(value.inv(0.05)),
p10: unwrap(value.inv(0.12)),
p20: unwrap(value.inv(0.20)),
p30: unwrap(value.inv(0.30)),
p40: unwrap(value.inv(0.40)),
p50: unwrap(value.inv(0.50)),
p60: unwrap(value.inv(0.60)),
p70: unwrap(value.inv(0.70)),
p80: unwrap(value.inv(0.80)),
p90: unwrap(value.inv(0.90)),
p95: unwrap(value.inv(0.95)),
p99: unwrap(value.inv(0.99)),
};
});
let valueData = mapFilter(data1, (x) => {
let result = distPlusFn(x);
if (result.tag === "Ok") {
return { x: x, value: result.value };
}
}).map(({ x, value }) => {
return {
x: x,
p1: unwrap(value.inv(0.01)),
p5: unwrap(value.inv(0.05)),
p10: unwrap(value.inv(0.12)),
p20: unwrap(value.inv(0.2)),
p30: unwrap(value.inv(0.3)),
p40: unwrap(value.inv(0.4)),
p50: unwrap(value.inv(0.5)),
p60: unwrap(value.inv(0.6)),
p70: unwrap(value.inv(0.7)),
p80: unwrap(value.inv(0.8)),
p90: unwrap(value.inv(0.9)),
p95: unwrap(value.inv(0.95)),
p99: unwrap(value.inv(0.99)),
};
});
let errorData = data1
.map((x) => {
let result = distPlusFn(x);
if (result.tag === "Error") {
return { x: x, error: result.value };
} else return null;
})
.filter((x) => x !== null);
let errorData = mapFilter(data1, (x) => {
let result = distPlusFn(x);
if (result.tag === "Error") {
return { x: x, error: result.value };
}
});
let error2 = _.groupBy(errorData, (x) => x.error);
return (
<>
@ -94,11 +106,10 @@ export const FunctionChart: React.FC<{
/>
{showChart}
{_.keysIn(error2).map((k) => (
<Error heading={k}>
<ErrorBox heading={k}>
{`Values: [${error2[k].map((r) => r.x.toFixed(2)).join(",")}]`}
</Error>
</ErrorBox>
))}
</>
);
};

View File

@ -2,97 +2,97 @@ import * as React from "react";
import _ from "lodash";
const orderOfMagnitudeNum = (n: number) => {
return Math.pow(10, n);
return Math.pow(10, n);
};
// 105 -> 3
const orderOfMagnitude = (n: number) => {
return Math.floor(Math.log(n) / Math.LN10 + 0.000000001);
return Math.floor(Math.log(n) / Math.LN10 + 0.000000001);
};
function withXSigFigs(number: number, sigFigs: number) {
const withPrecision = number.toPrecision(sigFigs);
const formatted = Number(withPrecision);
return `${formatted}`;
const withPrecision = number.toPrecision(sigFigs);
const formatted = Number(withPrecision);
return `${formatted}`;
}
class NumberShowerBuilder {
number: number;
precision: number;
number: number;
precision: number;
constructor(number: number, precision = 2) {
this.number = number;
this.precision = precision;
constructor(number: number, precision = 2) {
this.number = number;
this.precision = precision;
}
convert() {
const number = Math.abs(this.number);
const response = this.evaluate(number);
if (this.number < 0) {
response.value = "-" + response.value;
}
return response;
}
metricSystem(number: number, order: number) {
const newNumber = number / orderOfMagnitudeNum(order);
const precision = this.precision;
return `${withXSigFigs(newNumber, precision)}`;
}
evaluate(number: number) {
if (number === 0) {
return { value: this.metricSystem(0, 0) };
}
convert() {
const number = Math.abs(this.number);
const response = this.evaluate(number);
if (this.number < 0) {
response.value = "-" + response.value;
}
return response;
}
metricSystem(number: number, order: number) {
const newNumber = number / orderOfMagnitudeNum(order);
const precision = this.precision;
return `${withXSigFigs(newNumber, precision)}`;
}
evaluate(number: number) {
if (number === 0) {
return { value: this.metricSystem(0, 0) };
}
const order = orderOfMagnitude(number);
if (order < -2) {
return { value: this.metricSystem(number, order), power: order };
} else if (order < 4) {
return { value: this.metricSystem(number, 0) };
} else if (order < 6) {
return { value: this.metricSystem(number, 3), symbol: "K" };
} else if (order < 9) {
return { value: this.metricSystem(number, 6), symbol: "M" };
} else if (order < 12) {
return { value: this.metricSystem(number, 9), symbol: "B" };
} else if (order < 15) {
return { value: this.metricSystem(number, 12), symbol: "T" };
} else {
return { value: this.metricSystem(number, order), power: order };
}
const order = orderOfMagnitude(number);
if (order < -2) {
return { value: this.metricSystem(number, order), power: order };
} else if (order < 4) {
return { value: this.metricSystem(number, 0) };
} else if (order < 6) {
return { value: this.metricSystem(number, 3), symbol: "K" };
} else if (order < 9) {
return { value: this.metricSystem(number, 6), symbol: "M" };
} else if (order < 12) {
return { value: this.metricSystem(number, 9), symbol: "B" };
} else if (order < 15) {
return { value: this.metricSystem(number, 12), symbol: "T" };
} else {
return { value: this.metricSystem(number, order), power: order };
}
}
}
export function numberShow(number: number, precision = 2) {
const ns = new NumberShowerBuilder(number, precision);
return ns.convert();
const ns = new NumberShowerBuilder(number, precision);
return ns.convert();
}
export interface NumberShowerProps {
number: number;
precision?: number
number: number;
precision?: number;
}
export let NumberShower: React.FC<NumberShowerProps> = ({
number,
precision = 2
number,
precision = 2,
}: NumberShowerProps) => {
let numberWithPresentation = numberShow(number, precision);
return (
let numberWithPresentation = numberShow(number, precision);
return (
<span>
{numberWithPresentation.value}
{numberWithPresentation.symbol}
{numberWithPresentation.power ? (
<span>
{numberWithPresentation.value}
{numberWithPresentation.symbol}
{numberWithPresentation.power ? (
<span>
{"\u00b710"}
<span style={{ fontSize: "0.6em", verticalAlign: "super" }}>
{numberWithPresentation.power}
</span>
</span>
) : (
<></>
)}
{"\u00b710"}
<span style={{ fontSize: "0.6em", verticalAlign: "super" }}>
{numberWithPresentation.power}
</span>
</span>
);
}
) : (
<></>
)}
</span>
);
};

View File

@ -1,13 +1,10 @@
import * as React from "react";
import _ from "lodash";
import { run, errorValueToString } from "@quri/squiggle-lang";
import type {
samplingParams,
exportEnv,
} from "@quri/squiggle-lang";
import type { samplingParams, exportEnv } from "@quri/squiggle-lang";
import { NumberShower } from "./NumberShower";
import { DistributionChart } from "./DistributionChart";
import { Error } from "./Error";
import { ErrorBox } from "./ErrorBox";
export interface SquiggleChartProps {
/** The input string for squiggle */
@ -37,9 +34,6 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
squiggleString = "",
sampleCount = 1000,
outputXYPoints = 1000,
diagramStart = 0,
diagramStop = 10,
diagramCount = 20,
environment = [],
onEnvChange = () => {},
width = 500,
@ -47,18 +41,16 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
}: SquiggleChartProps) => {
let samplingInputs: samplingParams = {
sampleCount: sampleCount,
xyPointLength: outputXYPoints
xyPointLength: outputXYPoints,
};
let result = run(squiggleString, samplingInputs, environment);
console.log(result)
if (result.tag === "Ok") {
onEnvChange(environment);
let chartResult = result.value;
if (chartResult.tag === "number") {
return <NumberShower precision={3} number={chartResult.value} />;
} else if (chartResult.tag === "distribution") {
console.log("Is a distribution")
return (
<DistributionChart
distribution={chartResult.value}
@ -66,14 +58,19 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
width={width}
/>
);
console.log("NOT THIS LINE")
} else {
return (
<ErrorBox heading="No Viewer">
{"We don't currently have a viewer for this type: " + chartResult.tag}
</ErrorBox>
);
}
else {
console.log("Is a distribution")
return <Error heading="No Viewer">{"We don't currently have a viewer for this type: " + chartResult.tag}</Error>;
}
} else if (result.tag === "Error") {
} else {
// At this point, we came across an error. What was our error?
return <Error heading={"Parse Error"}>{errorValueToString(result.value)}</Error>;
return (
<ErrorBox heading={"Parse Error"}>
{errorValueToString(result.value)}
</ErrorBox>
);
}
};

View File

@ -3,7 +3,7 @@ import * as ReactDOM from "react-dom";
import { SquiggleChart } from "./SquiggleChart";
import { CodeEditor } from "./CodeEditor";
import type { exportEnv } from "@quri/squiggle-lang";
import styled from 'styled-components'
import styled from "styled-components";
export interface SquiggleEditorProps {
/** The input string for squiggle */

View File

@ -36,10 +36,8 @@ interface Props {
initialSquiggleString?: string;
}
let SquigglePlayground: FC<Props> = ({initialSquiggleString=""}: Props) => {
let [squiggleString, setSquiggleString] = useState(
initialSquiggleString
);
let SquigglePlayground: FC<Props> = ({ initialSquiggleString = "" }: Props) => {
let [squiggleString, setSquiggleString] = useState(initialSquiggleString);
let [sampleCount, setSampleCount] = useState(1000);
let [outputXYPoints, setOutputXYPoints] = useState(1000);
let [pointDistLength, setPointDistLength] = useState(1000);

View File

@ -1,5 +1,8 @@
export { SquiggleChart } from "./components/SquiggleChart";
export { SquiggleEditor, renderSquiggleEditorToDom } from "./components/SquiggleEditor";
export {
SquiggleEditor,
renderSquiggleEditorToDom,
} from "./components/SquiggleEditor";
import SquigglePlayground, {
renderSquigglePlaygroundToDom,
} from "./components/SquigglePlayground";

View File

@ -14,10 +14,10 @@ It uses the symbols "K", "M", "B", and "T", to represent thousands, millions, bi
name="Ten Thousand"
args={{
number: 10000,
precision: 2
precision: 2,
}}
>
{args => <NumberShower {...args}/>}
{(args) => <NumberShower {...args} />}
</Story>
</Canvas>
@ -26,10 +26,10 @@ It uses the symbols "K", "M", "B", and "T", to represent thousands, millions, bi
name="Ten Billion"
args={{
number: 10000000000,
precision: 2
precision: 2,
}}
>
{args => <NumberShower {...args}/>}
{(args) => <NumberShower {...args} />}
</Story>
</Canvas>
@ -38,10 +38,10 @@ It uses the symbols "K", "M", "B", and "T", to represent thousands, millions, bi
name="1.2*10^15"
args={{
number: 1200000000000000,
precision: 2
precision: 2,
}}
>
{args => <NumberShower {...args}/>}
{(args) => <NumberShower {...args} />}
</Story>
</Canvas>
@ -50,10 +50,10 @@ It uses the symbols "K", "M", "B", and "T", to represent thousands, millions, bi
name="1.35*10^-13"
args={{
number: 0.000000000000135,
precision: 2
precision: 2,
}}
>
{args => <NumberShower {...args}/>}
{(args) => <NumberShower {...args} />}
</Story>
</Canvas>

View File

@ -50,7 +50,8 @@ could be continuous, discrete or mixed.
<Story
name="Mixed"
args={{
squiggleString: "mm(0, 1, 3, 5, 8, normal(8, 1), [0.1, 0.3, 0.4, 0.35, 0.2, 0.8])",
squiggleString:
"mm(0, 1, 3, 5, 8, normal(8, 1), [0.1, 0.3, 0.4, 0.35, 0.2, 0.8])",
}}
>
{Template.bind({})}

View File

@ -160,7 +160,7 @@
"shape": {
"value": "circle"
},
"size": [{"value": 30}],
"size": [{ "value": 30 }],
"tooltip": {
"signal": "datum.y"
}

View File

@ -96,11 +96,11 @@
"signals": [
{
"name": "mousemove",
"on": [{"events": "mousemove", "update": "invert('xscale', x())"}]
"on": [{ "events": "mousemove", "update": "invert('xscale', x())" }]
},
{
"name": "mouseout",
"on": [{"events": "mouseout", "update": "invert('xscale', x())"}]
"on": [{ "events": "mouseout", "update": "invert('xscale', x())" }]
}
],
"axes": [
@ -132,7 +132,7 @@
"type": "rule",
"encode": {
"update": {
"xscale": {"scale": "xscale", "signal": "mousemove"}
"xscale": { "scale": "xscale", "signal": "mousemove" }
}
}
},

View File

@ -5,10 +5,12 @@
},
"module": "commonjs",
"jsx": "react",
"skipLibCheck": true,
"resolveJsonModule": true,
"noImplicitAny": false,
"esModuleInterop": true,
"removeComments": true,
"strict": true,
"preserveConstEnums": true,
"composite": true,
"outDir": "./dist",
@ -16,7 +18,10 @@
"declaration": true,
"sourceMap": true
},
"files": ["src/vega-specs/spec-distributions.json", "src/vega-specs/spec-percentiles.json"],
"files": [
"src/vega-specs/spec-distributions.json",
"src/vega-specs/spec-percentiles.json"
],
"target": "ES6",
"include": ["src/**/*", "src/*"],
"exclude": ["node_modules", "**/*.spec.ts", "webpack.config.js"],

View File

@ -3,13 +3,15 @@ const path = require("path");
module.exports = {
mode: "production",
devtool: "source-map",
profile: true,
entry: "./src/index.ts",
module: {
rules: [
{
test: /\.tsx?$/,
loader: "ts-loader",
options: { projectReferences: true },
include: path.resolve(__dirname, "src"),
options: { projectReferences: true, transpileOnly: true },
exclude: /node_modules/,
},
{

View File

@ -1,3 +0,0 @@
*.bs.js
*.gen.tsx
dist

View File

@ -1,10 +1,15 @@
import { run, Distribution, resultMap, squiggleExpression } from "../src/js/index";
import {
run,
Distribution,
resultMap,
squiggleExpression,
} from "../src/js/index";
let testRun = (x: string): squiggleExpression => {
let result = run(x, {sampleCount: 100, xyPointLength: 100});
expect(result.tag).toEqual("Ok")
if(result.tag === "Ok") {
return result.value
let result = run(x, { sampleCount: 100, xyPointLength: 100 });
expect(result.tag).toEqual("Ok");
if (result.tag === "Ok") {
return result.value;
}
};
@ -16,7 +21,7 @@ describe("Simple calculations and results", () => {
test("mean(normal(5,2))", () => {
expect(testRun("mean(normal(5,2))")).toEqual({
tag: "number",
value: 5
value: 5,
});
});
test("10+10", () => {

View File

@ -1,11 +1,26 @@
import * as _ from 'lodash'
import * as _ from "lodash";
import type {
exportEnv,
exportDistribution,
} from "../rescript/ProgramEvaluator.gen";
export type { exportEnv, exportDistribution };
import { genericDist, samplingParams, evaluate, expressionValue, errorValue, distributionError, toPointSet, continuousShape, discreteShape, distributionErrorToString } from "../rescript/TypescriptInterface.gen";
export { makeSampleSetDist, errorValueToString, distributionErrorToString } from "../rescript/TypescriptInterface.gen";
export type { exportEnv, exportDistribution };
import {
genericDist,
samplingParams,
evaluate,
expressionValue,
errorValue,
distributionError,
toPointSet,
continuousShape,
discreteShape,
distributionErrorToString,
} from "../rescript/TypescriptInterface.gen";
export {
makeSampleSetDist,
errorValueToString,
distributionErrorToString,
} from "../rescript/TypescriptInterface.gen";
import {
Constructors_mean,
Constructors_sample,
@ -32,11 +47,11 @@ import {
Constructors_pointwiseLogarithm,
Constructors_pointwisePower,
} from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen";
export type {samplingParams, errorValue}
export type { samplingParams, errorValue };
export let defaultSamplingInputs: samplingParams = {
sampleCount: 10000,
xyPointLength: 10000
xyPointLength: 10000,
};
export type result<a, b> =
@ -60,17 +75,24 @@ export function resultMap<a, b, c>(
}
}
function Ok<a,b>(x: a): result<a,b> {
return {"tag": "Ok", value: x}
function Ok<a, b>(x: a): result<a, b> {
return { tag: "Ok", value: x };
}
type tagged<a, b> = {tag: a, value: b}
type tagged<a, b> = { tag: a; value: b };
function tag<a,b>(x: a, y: b) : tagged<a, b>{
return { tag: x, value: y}
function tag<a, b>(x: a, y: b): tagged<a, b> {
return { tag: x, value: y };
}
export type squiggleExpression = tagged<"symbol", string> | tagged<"string", string> | tagged<"array", squiggleExpression[]> | tagged<"boolean", boolean> | tagged<"distribution", Distribution> | tagged<"number", number> | tagged<"record", {[key: string]: squiggleExpression }>
export type squiggleExpression =
| tagged<"symbol", string>
| tagged<"string", string>
| tagged<"array", squiggleExpression[]>
| tagged<"boolean", boolean>
| tagged<"distribution", Distribution>
| tagged<"number", number>
| tagged<"record", { [key: string]: squiggleExpression }>;
export function run(
squiggleString: string,
samplingInputs?: samplingParams,
@ -79,15 +101,20 @@ export function run(
let si: samplingParams = samplingInputs
? samplingInputs
: defaultSamplingInputs;
let result : result<expressionValue, errorValue> = evaluate(squiggleString);
return resultMap(result, x => createTsExport(x, si));
let result: result<expressionValue, errorValue> = evaluate(squiggleString);
return resultMap(result, (x) => createTsExport(x, si));
}
function createTsExport(x: expressionValue, sampEnv: samplingParams): squiggleExpression {
function createTsExport(
x: expressionValue,
sampEnv: samplingParams
): squiggleExpression {
switch (x.tag) {
case "EvArray":
return tag("array", x.value.map(x => createTsExport(x, sampEnv)));
return tag(
"array",
x.value.map((x) => createTsExport(x, sampEnv))
);
case "EvBool":
return tag("boolean", x.value);
case "EvDistribution":
@ -95,26 +122,32 @@ function createTsExport(x: expressionValue, sampEnv: samplingParams): squiggleEx
case "EvNumber":
return tag("number", x.value);
case "EvRecord":
return tag("record", _.mapValues(x.value, x => createTsExport(x, sampEnv)))
return tag(
"record",
_.mapValues(x.value, (x) => createTsExport(x, sampEnv))
);
case "EvString":
return tag("string", x.value);
case "EvSymbol":
return tag("symbol", x.value);
}
}
export function resultExn<a, c>(r: result<a, c>): a | c {
return r.value;
}
export type point = { x: number, y: number}
export type point = { x: number; y: number };
export type shape = {
continuous: point[]
discrete: point[]
}
continuous: point[];
discrete: point[];
};
function shapePoints(x : continuousShape | discreteShape): point[]{
function shapePoints(x: continuousShape | discreteShape): point[] {
let xs = x.xyShape.xs;
let ys = x.xyShape.ys;
return _.zipWith(xs, ys, (x, y) => ({x, y}))
return _.zipWith(xs, ys, (x, y) => ({ x, y }));
}
export class Distribution {
@ -127,7 +160,9 @@ export class Distribution {
return this;
}
mapResultDist(r: result<genericDist, distributionError>): result<Distribution, distributionError> {
mapResultDist(
r: result<genericDist, distributionError>
): result<Distribution, distributionError> {
return resultMap(r, (v: genericDist) => new Distribution(v, this.env));
}
@ -157,31 +192,35 @@ export class Distribution {
);
}
shape() : result<shape, distributionError> {
let pointSet = toPointSet(this.t, {xyPointLength: this.env.xyPointLength, sampleCount: this.env.sampleCount}, null);
if(pointSet.tag === "Ok"){
shape(): result<shape, distributionError> {
let pointSet = toPointSet(
this.t,
{
xyPointLength: this.env.xyPointLength,
sampleCount: this.env.sampleCount,
},
undefined
);
if (pointSet.tag === "Ok") {
let distribution = pointSet.value;
if(distribution.tag === "Continuous"){
if (distribution.tag === "Continuous") {
return Ok({
continuous: shapePoints(distribution.value),
discrete: []
})
}
else if(distribution.tag === "Discrete"){
discrete: [],
});
} else if (distribution.tag === "Discrete") {
return Ok({
discrete: shapePoints(distribution.value),
continuous: []
})
}
else if(distribution.tag === "Mixed"){
continuous: [],
});
} else {
return Ok({
discrete: shapePoints(distribution.value.discrete),
continuous: shapePoints(distribution.value.continuous)
})
continuous: shapePoints(distribution.value.continuous),
});
}
}
else {
return pointSet
} else {
return pointSet;
}
}
@ -197,7 +236,10 @@ export class Distribution {
);
}
truncate(left: number, right: number): result<Distribution, distributionError> {
truncate(
left: number,
right: number
): result<Distribution, distributionError> {
return this.mapResultDist(
Constructors_truncate({ env: this.env }, this.t, left, right)
);
@ -209,11 +251,10 @@ export class Distribution {
toString(): string {
let result = Constructors_toString({ env: this.env }, this.t);
if(result.tag === "Ok"){
return result.value
}
else {
return distributionErrorToString(result.value)
if (result.tag === "Ok") {
return result.value;
} else {
return distributionErrorToString(result.value);
}
}
@ -245,7 +286,9 @@ export class Distribution {
);
}
algebraicLogarithm(d2: Distribution): result<Distribution, distributionError> {
algebraicLogarithm(
d2: Distribution
): result<Distribution, distributionError> {
return this.mapResultDist(
Constructors_algebraicLogarithm({ env: this.env }, this.t, d2.t)
);
@ -281,7 +324,9 @@ export class Distribution {
);
}
pointwiseLogarithm(d2: Distribution): result<Distribution, distributionError> {
pointwiseLogarithm(
d2: Distribution
): result<Distribution, distributionError> {
return this.mapResultDist(
Constructors_pointwiseLogarithm({ env: this.env }, this.t, d2.t)
);

View File

@ -1 +1 @@
export type Dict_t<T> = { [key: string]: T }
export type Dict_t<T> = { [key: string]: T };

View File

@ -7,6 +7,7 @@
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true,
"strict": true,
"outDir": "./dist",
"declarationDir": "./dist",
"declaration": true,

View File

@ -1 +0,0 @@
.docusaurus

View File

@ -4025,28 +4025,10 @@
dependencies:
"@types/react" "*"
"@types/react@*":
version "17.0.44"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.44.tgz#c3714bd34dd551ab20b8015d9d0dbec812a51ec7"
integrity sha512-Ye0nlw09GeMp2Suh8qoOv0odfgCoowfM/9MG6WeRD60Gq9wS90bdkdRtYbRkNhXOpG4H+YXGvj4wOWhAC0LJ1g==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
csstype "^3.0.2"
"@types/react@^16.9.19":
version "16.14.24"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.24.tgz#f2c5e9fa78f83f769884b83defcf7924b9eb5c82"
integrity sha512-e7U2WC8XQP/xfR7bwhOhNFZKPTfW1ph+MiqtudKb8tSV8RyCsovQx2sNVtKoOryjxFKpHPPC/yNiGfdeVM5Gyw==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
csstype "^3.0.2"
"@types/react@^18.0.1":
version "18.0.1"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.1.tgz#1b2e02fb7613212518733946e49fb963dfc66e19"
integrity sha512-VnWlrVgG0dYt+NqlfMI0yUYb8Rdl4XUROyH+c6gq/iFCiZ805Vi//26UW38DHnxQkbDhnrIWTBiy6oKZqL11cw==
"@types/react@*", "@types/react@17.0.43", "@types/react@^16.9.19", "@types/react@^18.0.1":
version "17.0.43"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.43.tgz#4adc142887dd4a2601ce730bc56c3436fdb07a55"
integrity sha512-8Q+LNpdxf057brvPu1lMtC5Vn7J119xrP1aq4qiaefNioQUYANF/CYeK4NsKorSZyUGJ66g0IM+4bbjwx45o2A==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
@ -15495,6 +15477,13 @@ spdy@^4.0.2:
select-hose "^2.0.0"
spdy-transport "^3.0.0"
speed-measure-webpack-plugin@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.5.0.tgz#caf2c5bee24ab66c1c7c30e8daa7910497f7681a"
integrity sha512-Re0wX5CtM6gW7bZA64ONOfEPEhwbiSF/vz6e2GvadjuaPrQcHTQdRGsD8+BE7iUOysXH8tIenkPCQBEcspXsNg==
dependencies:
chalk "^4.1.0"
split-string@^3.0.1, split-string@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"