Compare commits

..

1 Commits

Author SHA1 Message Date
Ozzie Gooen
d4025e7f02 Attempt of refactor for Bindings and Paramaters 2022-04-25 16:26:23 -04:00
427 changed files with 10960 additions and 30594 deletions

20
.github/CODEOWNERS vendored
View File

@ -9,22 +9,22 @@
# This also holds true for GitHub teams.
# Rescript
*.res @berekuk @OAGr
*.resi @berekuk @OAGr
*.res @OAGr @quinn-dougherty
*.resi @OAGr @quinn-dougherty
# Typescript
*.tsx @Hazelfire @berekuk @OAGr
*.ts @Hazelfire @berekuk @OAGr
*.tsx @Hazelfire @OAGr
*.ts @Hazelfire @OAGr
# Javascript
*.js @Hazelfire @berekuk @OAGr
*.js @Hazelfire @OAGr
# Any opsy files
.github/** @quinn-dougherty @berekuk @OAGr
*.json @quinn-dougherty @Hazelfire @berekuk @OAGr
*.y*ml @quinn-dougherty @berekuk @OAGr
*.config.js @Hazelfire @berekuk @OAGr
vercel.json @OAGr @berekuk @Hazelfire
.github/** @quinn-dougherty @OAGr
*.json @quinn-dougherty @Hazelfire @OAGr
*.y*ml @quinn-dougherty @OAGr
*.config.js @Hazelfire @OAGr
netlify.toml @quinn-dougherty @OAGr @Hazelfire
# Documentation
*.md @quinn-dougherty @OAGr @Hazelfire

View File

@ -8,17 +8,6 @@ updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
interval: "daily"
commit-message:
prefix: "⬆️"
open-pull-requests-limit: 100
labels:
- "dependencies"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
commit-message:
prefix: "⬆️"
labels:
- "dependencies"

View File

@ -1,87 +0,0 @@
name: Nix build
on:
push:
branches:
- master
- develop
pull_request:
branches:
- master
- develop
- reducer-dev
- epic-reducer-project
jobs:
flake-lints:
name: All lint
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install nix
uses: cachix/install-nix-action@v17
with:
nix_path: nixpkgs=channel:nixos-22.05
- name: Use cachix
uses: cachix/cachix-action@v10
with:
name: quantified-uncertainty
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
- name: Check that lang lints
run: nix build .#lang-lint
- name: Check that components lints
run: nix build .#components-lint
- name: Check that website lints
run: nix build .#docusaurus-lint
- name: Check that vscode extension lints
run: nix build .#vscode-lint
- name: Check that cli lints
run: nix build .#cli-lint
flake-packages:
name: Builds, tests, and bundles
runs-on: ubuntu-latest
needs: flake-lints
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install nix
uses: cachix/install-nix-action@v17
with:
nix_path: nixpkgs=channel:nixos-22.05
- name: Use cachix
uses: cachix/cachix-action@v10
with:
name: quantified-uncertainty
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
- name: Check all lang tests
run: nix build .#lang-test
- name: Check that lang bundles
run: nix build .#lang-bundle
- name: Check that components builds
run: nix build .#components
- name: Check that components bundles
run: nix build .#components-bundle
flake-devshells:
name: Development shell environment
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install nix
uses: cachix/install-nix-action@v17
with:
nix_path: nixpkgs=channel:nixos-22.05
- name: Use cachix
uses: cachix/cachix-action@v10
with:
name: quantified-uncertainty
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
- name: Build js devshell
run: nix develop .#js --profile just-js
- name: Build js & wasm devshell
run: nix develop --profile full-shell

View File

@ -1,4 +1,4 @@
name: Squiggle packages checks
name: Squiggle packages check
on:
push:
@ -10,39 +10,146 @@ on:
- master
- develop
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: quantified-uncertainty
jobs:
build-test-lint:
name: Build, test, lint
pre_check:
name: Precheck for skipping redundant jobs
runs-on: ubuntu-latest
outputs:
should_skip_lang: ${{ steps.skip_lang_check.outputs.should_skip }}
should_skip_components: ${{ steps.skip_components_check.outputs.should_skip }}
should_skip_website: ${{ steps.skip_website_check.outputs.should_skip }}
steps:
- uses: actions/checkout@v3
- name: Setup Node.js environment
uses: actions/setup-node@v3
- id: skip_lang_check
name: Check if the changes are about squiggle-lang src files
uses: fkirc/skip-duplicate-actions@v3.4.1
with:
node-version: 16
cache: 'yarn'
- name: Install dependencies
run: yarn --frozen-lockfile
- name: Turbo run
run: npx turbo run build test lint bundle
paths: '["packages/squiggle-lang/**"]'
- id: skip_components_check
name: Check if the changes are about components src files
uses: fkirc/skip-duplicate-actions@v3.4.1
with:
paths: '["packages/components/**"]'
- id: skip_website_check
name: Check if the changes are about website src files
uses: fkirc/skip-duplicate-actions@v3.4.1
with:
paths: '["packages/website/**"]'
coverage:
name: Coverage
lang-lint:
name: Language lint
runs-on: ubuntu-latest
needs: pre_check
if: ${{ needs.pre_check.outputs.should_skip_lang != 'true' }}
defaults:
run:
shell: bash
working-directory: packages/squiggle-lang
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- name: Install Dependencies
run: cd ../../ && yarn
- name: Check rescript lint
run: yarn lint:rescript
- name: Check javascript, typescript, and markdown lint
uses: creyD/prettier_action@v4.2
with:
fetch-depth: 2
- name: Setup Node.js environment
uses: actions/setup-node@v2
dry: true
prettier_options: --check packages/squiggle-lang
lang-build-test-bundle:
name: Language build, test, and bundle
runs-on: ubuntu-latest
needs: pre_check
if: ${{ needs.pre_check.outputs.should_skip_lang != 'true' }}
defaults:
run:
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 rescript tests
run: yarn test:rescript
- name: Run typescript tests
run: yarn test:ts
- name: Run webpack
run: yarn bundle
- name: Upload rescript coverage report
run: yarn coverage:rescript:ci
- name: Upload typescript coverage report
run: yarn coverage:ts:ci
components-lint:
name: Components lint
runs-on: ubuntu-latest
needs: pre_check
if: ${{ needs.pre_check.outputs.should_skip_components != 'true' }}
defaults:
run:
shell: bash
working-directory: packages/components
steps:
- uses: actions/checkout@v2
- name: Check javascript, typescript, and markdown lint
uses: creyD/prettier_action@v4.2
with:
node-version: 16
cache: 'yarn'
- name: Install dependencies
run: yarn
- name: Coverage
run: npx turbo run coverage
dry: true
prettier_options: --check packages/components
components-bundle-build:
name: Components bundle and build
runs-on: ubuntu-latest
needs: pre_check
if: ${{ (needs.pre_check.outputs.should_skip_components != 'true') || (needs.pre_check.outputs.should_skip_lang != 'true') }}
defaults:
run:
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
website-lint:
name: Website lint
runs-on: ubuntu-latest
needs: pre_check
if: ${{ needs.pre_check.outputs.should_skip_website != 'true' }}
defaults:
run:
shell: bash
working-directory: packages/website
steps:
- uses: actions/checkout@v2
- name: Check javascript, typescript, and markdown lint
uses: creyD/prettier_action@v4.2
with:
dry: true
prettier_options: --check packages/website
website-build:
name: Website build
runs-on: ubuntu-latest
needs: pre_check
if: ${{ (needs.pre_check.outputs.should_skip_website != 'true') || (needs.pre_check.outputs.should_skip_lang != 'true') || (needs.pre_check.outputs.should_skip_components != 'true') }}
defaults:
run:
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

View File

@ -12,6 +12,12 @@
name: "CodeQL"
on:
push:
branches:
- master
- production
- staging
- develop
schedule:
- cron: "42 19 * * 0"
@ -33,11 +39,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
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.
@ -48,7 +54,7 @@ jobs:
# 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@v2
uses: github/codeql-action/autobuild@v1
- name: Install dependencies
run: yarn
- name: Build rescript
@ -65,4 +71,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v1

View File

@ -1,141 +0,0 @@
name: Run Release Please
on:
push:
branches:
- master
jobs:
pre_check:
name: Precheck for skipping redundant jobs
runs-on: ubuntu-latest
outputs:
should_skip_lang: ${{ steps.skip_lang_check.outputs.should_skip }}
should_skip_components: ${{ steps.skip_components_check.outputs.should_skip }}
should_skip_website: ${{ steps.skip_website_check.outputs.should_skip }}
should_skip_vscodeext: ${{ steps.skip_vscodeext_check.outputs.should_skip }}
should_skip_cli: ${{ steps.skip_cli_check.outputs.should_skip }}
steps:
- id: skip_lang_check
name: Check if the changes are about squiggle-lang src files
uses: fkirc/skip-duplicate-actions@v5.2.0
with:
paths: '["packages/squiggle-lang/**"]'
- id: skip_components_check
name: Check if the changes are about components src files
uses: fkirc/skip-duplicate-actions@v5.2.0
with:
paths: '["packages/components/**"]'
- id: skip_website_check
name: Check if the changes are about website src files
uses: fkirc/skip-duplicate-actions@v5.2.0
with:
paths: '["packages/website/**"]'
- id: skip_vscodeext_check
name: Check if the changes are about vscode extension src files
uses: fkirc/skip-duplicate-actions@v5.2.0
with:
paths: '["packages/vscode-ext/**"]'
- id: skip_cli_check
name: Check if the changes are about cli src files
uses: fkirc/skip-duplicate-actions@v5.2.0
with:
paths: '["packages/cli/**"]'
relplz-lang:
name: for squiggle-lang
runs-on: ubuntu-latest
needs: pre_check
if: ${{ needs.pre_check.outputs.should_skip_lang != 'true' }}
steps:
- name: Release please (squiggle-lang)
uses: google-github-actions/release-please-action@v3
id: release
with:
token: ${{secrets.GITHUB_TOKEN}}
command: manifest-pr
path: packages/squiggle-lang
# bump-patch-for-minor-pre-major: true
skip-github-release: true
- name: Publish- Checkout source
uses: actions/checkout@v3
# these if statements ensure that a publication only occurs when
# a new release is created:
if: ${{ steps.release.outputs.release_created }}
- name: Publish- Install dependencies
run: yarn
if: ${{ steps.release.outputs.release_created }}
- name: Publish
run: cd packages/squiggle-lang && yarn publish
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
if: ${{ steps.release.outputs.release_created }}
relplz-components:
name: for components
runs-on: ubuntu-latest
needs: pre_check
if: ${{ needs.pre_check.outputs.should_skip_components != 'true' }}
steps:
- name: Release please (components)
uses: google-github-actions/release-please-action@v3
with:
token: ${{secrets.GITHUB_TOKEN}}
command: manifest-pr
path: packages/components
# bump-patch-for-minor-pre-major: true
skip-github-release: true
- name: Publish- Checkout source
uses: actions/checkout@v3
# these if statements ensure that a publication only occurs when
# a new release is created:
if: ${{ steps.release.outputs.release_created }}
- name: Publish- Install dependencies
run: yarn
if: ${{ steps.release.outputs.release_created }}
- name: Publish
run: cd packages/components && yarn publish
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
relplz-website:
name: for website
runs-on: ubuntu-latest
needs: pre_check
if: ${{ needs.pre_check.outputs.should_skip_website != 'true' }}
steps:
- name: Release please (website)
uses: google-github-actions/release-please-action@v3
with:
token: ${{secrets.GITHUB_TOKEN}}
command: manifest-pr
path: packages/website
# bump-patch-for-minor-pre-major: true
skip-github-release: true
relplz-vscodeext:
name: for vscode-ext
runs-on: ubuntu-latest
needs: pre_check
if: ${{ needs.pre_check.outputs.should_skip_vscodeext != 'true' }}
steps:
- name: Release please (vscode-ext)
uses: google-github-actions/release-please-action@v3
with:
token: ${{secrets.GITHUB_TOKEN}}
command: manifest-pr
path: packages/vscode-ext
# bump-patch-for-minor-pre-major: true
skip-github-release: true
relplz-cl:
name: for cli
runs-on: ubuntu-latest
needs: pre_check
if: ${{ needs.pre_check.outputs.should_skip_cli != 'true' }}
steps:
- name: Release please (cli)
uses: google-github-actions/release-please-action@v3
with:
token: ${{secrets.GITHUB_TOKEN}}
command: manifest-pr
path: packages/cli
bump-patch-for-minor-pre-major: true
skip-github-release: true

6
.gitignore vendored
View File

@ -7,9 +7,3 @@ yarn-error.log
**/.sync.ffs_db
.direnv
.log
.vscode
todo.txt
result
shell.nix
.turbo

View File

@ -1,16 +1,12 @@
.direnv
*.bs.js
*.gen.tsx
packages/*/dist
packages/components/storybook-static
node_modules
packages/*/node_modules
packages/website/.docusaurus
packages/squiggle-lang/lib
packages/squiggle-lang/.nyc_output/
packages/squiggle-lang/coverage/
packages/squiggle-lang/.cache/
packages/website/build/
packages/squiggle-lang/src/rescript/Reducer/Reducer_Peggy/Reducer_Peggy_GeneratedParser.js
packages/vscode-ext/media/vendor/
packages/squiggle-lang/.nyc_output/
packages/*/dist
result

View File

@ -1,7 +0,0 @@
{
"packages/cli": "0.0.3",
"packages/components": "0.4.1",
"packages/squiggle-lang": "0.4.1",
"packages/vscode-ext": "0.4.1",
"packages/website": "0.0.0"
}

View File

@ -1 +0,0 @@
See the [Changelog.mdx page](./packages/website/docs/Changelog.mdx) for the changelog.

View File

@ -16,7 +16,7 @@ Squiggle is currently pre-alpha.
# Bug reports
Anyone (with a github account) can file an issue at any time. Please allow Slava, Sam, and Ozzie to triage, but otherwise just follow the suggestions in the issue templates.
Anyone (with a github account) can file an issue at any time. Please allow Quinn, Sam, and Ozzie to triage, but otherwise just follow the suggestions in the issue templates.
# Project structure
@ -28,7 +28,7 @@ Squiggle is a **monorepo** with three **packages**.
# Deployment ops
We use Vercel, and it should only concern Slava, Sam, and Ozzie.
We use netlify, and it should only concern Quinn, Sam, and Ozzie.
# Development environment, building, testing, dev server
@ -56,9 +56,9 @@ If you absolutely must, please prefix your commit message with `hotfix: `.
Please work against `develop` branch. **Do not** work against `master`.
- For rescript code: Slava and Ozzie are reviewers
- For rescript code: Quinn and Ozzie are reviewers
- For js or typescript code: Sam and Ozzie are reviewers
- For ops code (i.e. yaml, package.json): Slava and Sam are reviewers
- For ops code (i.e. yaml, package.json): Quinn and Sam are reviewers
Autopings are set up: if you are not autopinged, you are welcome to comment, but please do not use the formal review feature, send approvals, rejections, or merges.

View File

@ -1,30 +1,19 @@
# Squiggle
[![Packages check](https://github.com/quantified-uncertainty/squiggle/actions/workflows/ci.yml/badge.svg)](https://github.com/quantified-uncertainty/squiggle/actions/workflows/ci.yml)
[![npm version - lang](https://badge.fury.io/js/@quri%2Fsquiggle-lang.svg)](https://www.npmjs.com/package/@quri/squiggle-lang)
[![npm version - components](https://badge.fury.io/js/@quri%2Fsquiggle-components.svg)](https://www.npmjs.com/package/@quri/squiggle-components)
[![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)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/quantified-uncertainty/squiggle/blob/develop/LICENSE)
[![codecov](https://codecov.io/gh/quantified-uncertainty/squiggle/branch/develop/graph/badge.svg?token=QRLBL5CQ7C)](https://codecov.io/gh/quantified-uncertainty/squiggle)
_An estimation language_.
## Get started
- [Gallery](https://www.squiggle-language.com/docs/Discussions/Gallery)
- [Squiggle playground](https://squiggle-language.com/playground)
- [Language basics](https://www.squiggle-language.com/docs/Guides/Language)
- [Squiggle functions source of truth](https://www.squiggle-language.com/docs/Guides/Functions)
- [Known bugs](https://www.squiggle-language.com/docs/Discussions/Bugs)
- [Original lesswrong sequence](https://www.lesswrong.com/s/rDe8QE5NvXcZYzgZ3)
- [Author your squiggle models as Observable notebooks](https://observablehq.com/@hazelfire/squiggle)
- [Use squiggle in VS Code](https://marketplace.visualstudio.com/items?itemName=QURI.vscode-squiggle)
This is an experimental DSL/language for making probabilistic estimates. The full story can be found [here](https://www.lesswrong.com/s/rDe8QE5NvXcZYzgZ3).
## Our deployments
- **website/docs prod**: https://squiggle-language.com
- **website/docs staging**: https://preview.squiggle-language.com
- **components storybook prod**: https://components.squiggle-language.com
- **components storybook staging**: https://preview-components.squiggle-language.com
- **website/docs prod**: https://squiggle-language.com [![Netlify Status](https://api.netlify.com/api/v1/badges/2139af5c-671d-473d-a9f6-66c96077d8a1/deploy-status)](https://app.netlify.com/sites/squiggle-documentation/deploys)
- **website/docs staging**: https://develop--squiggle-documentation.netlify.app/
- **components storybook prod**: https://squiggle-components.netlify.app/ [![Netlify Status](https://api.netlify.com/api/v1/badges/b7f724aa-6b20-4d0e-bf86-3fcd1a3e9a70/deploy-status)](https://app.netlify.com/sites/squiggle-components/deploys)
- **components storybook staging**: https://develop--squiggle-components.netlify.app/
- **legacy (2020) playground**: https://playground.squiggle-language.com
## Packages
@ -38,10 +27,10 @@ the packages can be found in `packages`.
- `@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.
- `packages/website` is the main descriptive website for squiggle,
- `@quri/squiggle-website` in `packages/website` The main descriptive website for squiggle,
it is hosted at `squiggle-language.com`.
- `packages/vscode-ext` is the VS Code extension for writing estimation functions.
- `packages/cli` is an experimental way of using imports in squiggle, which is also on [npm](https://www.npmjs.com/package/squiggle-cli-experimental).
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.
# Develop
@ -51,25 +40,7 @@ For any project in the repo, begin by running `yarn` in the top level
yarn
```
Then use `turbo` to build the specific packages or the entire monorepo:
```sh
turbo run build
```
Or:
```sh
turbo run build --filter=@quri/squiggle-components
```
You can also run specific npm scripts for the package you're working on. See `packages/*/README.md` for the details.
# NixOS users
This repository requires the use of bundled binaries from node_modules, which
are not linked statically. The easiest way to get them working is to enable
[nix-ld](https://github.com/Mic92/nix-ld).
See `packages/*/README.md` to work with whatever project you're interested in.
# Contributing

View File

@ -1,20 +0,0 @@
# The following code was provided by Nuño Sempere, it comes directly from the post https://www.lesswrong.com/s/rDe8QE5NvXcZYzgZ3/p/j8o6sgRerE3tqNWdj
## Initial setup
yearly_probability_max = 0.95
yearly_probability_min = 0.66
period_probability_function(epsilon, yearly_probability) = 1 - (1 - yearly_probability) ^ (1 / epsilon)
probability_decayed(t, time_periods, period_probability) = 1 - (1 - period_probability) ^ (time_periods - t)
## Monthly decomposition
months_in_a_year=12
monthly_probability_min = period_probability_function(months_in_a_year, yearly_probability_min)
monthly_probability_max = period_probability_function(months_in_a_year, yearly_probability_max)
probability_decayed_monthly_min(t) = probability_decayed(t, months_in_a_year, monthly_probability_min)
probability_decayed_monthly_max(t) = probability_decayed(t, months_in_a_year, monthly_probability_max)
probability_decayed_monthly(t) = probability_decayed_monthly_min(t) to probability_decayed_monthly_max(t)
probability_decayed_monthly
## probability_decayed_monthly(6)
## mean(probability_decayed_monthly(6))

View File

@ -1,38 +0,0 @@
# This is a cost effectiveness analysis of givedirectly, originally done by givewell, and translated into Squiggle by Sam Nolan
donation_size = 10000
proportion_of_funding_available = beta(10, 2)
total_funding_available = donation_size * proportion_of_funding_available
household_size = 3.7 to 5.7
size_of_transfer = 800 to 1200
size_of_transfer_per_person = size_of_transfer / household_size
portion_invested = 0.3 to 0.5
amount_invested = portion_invested * size_of_transfer_per_person
amount_consumed = (1 - portion_invested) * size_of_transfer_per_person
return_on_investment = 0.08 to 0.12
increase_in_consumption_from_investments = return_on_investment * amount_invested
baseline_consumption = 200 to 350
log_increase_in_consumption = log(amount_consumed + baseline_consumption) + log(baseline_consumption)
log_increase_in_consumption_from_investment = log(increase_in_consumption_from_investments + baseline_consumption) + log(baseline_consumption)
investment_duration = 8 to 12
discount_rate = beta(1.004, 20)
present_value_excluding_last_year = log_increase_in_consumption_from_investment * (1 - (1 + discount_rate) ^ (-investment_duration)) / (log(1 + discount_rate))
percent_of_investment_returned = 0.15 to 0.25
pv_consumption_last_year = (log(baseline_consumption + amount_invested * (return_on_investment + percent_of_investment_returned)) - log(baseline_consumption)) / (1 + discount_rate)^investment_duration
total_pv_of_cash_transfer = pv_consumption_last_year + present_value_excluding_last_year + log_increase_in_consumption
discount_negative_spoiler = 0.03 to 0.07
value_discounting_spoiler = discount_negative_spoiler * total_pv_of_cash_transfer
consumption_increase_per_household = value_discounting_spoiler * household_size
amount_of_transfers_made = total_funding_available / size_of_transfer
total_increase_in_ln_consumption = amount_of_transfers_made * consumption_increase_per_household
total_increase_in_ln_consumption

View File

@ -1,3 +0,0 @@
xY1 = 99
aBa3 = xY1 * 2 + 1
aBa3 * xY1 + aBa3

View File

@ -1,79 +0,0 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gentype": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1661855866,
"narHash": "sha256-+q0OOTyaq8eOn9BOWdPOCtSDOISW4A59v3mq3JOZyug=",
"owner": "rescript-association",
"repo": "genType",
"rev": "6b5f164b4f6ced456019b7579a0ab7e0a86518ad",
"type": "github"
},
"original": {
"owner": "rescript-association",
"repo": "genType",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1661617163,
"narHash": "sha256-NN9Ky47j8ohgPhA9JZyfkYIbbAo6RJkGz+7h8/exVpE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "0ba2543f8c855d7be8e90ef6c8dc89c1617e8a08",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-22.05",
"type": "indirect"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"gentype": "gentype",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

View File

@ -1,99 +0,0 @@
{
description = "Squiggle packages";
inputs = {
nixpkgs.url = "nixpkgs/nixos-22.05";
gentype = {
url = "github:rescript-association/genType";
inputs.nixpkgs.follows = "nixpkgs";
};
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, gentype, flake-utils }:
let
version = builtins.substring 0 8 self.lastModifiedDate;
overlays = [
(final: prev: {
# set the node version here
nodejs = prev.nodejs-18_x;
# The override is the only way to get it into mkYarnModules
})
];
commonFn = pkgs: {
buildInputs = with pkgs; [ nodejs yarn ];
prettier = with pkgs.nodePackages; [ prettier ];
which = [ pkgs.which ];
};
gentypeOutputFn = pkgs: gentype.outputs.packages.${pkgs.system}.default;
langFn = { pkgs, ... }:
# Probably doesn't work on i686-linux
import ./nix/squiggle-lang.nix {
inherit pkgs commonFn gentypeOutputFn;
};
componentsFn = { pkgs, ... }:
import ./nix/squiggle-components.nix { inherit pkgs commonFn langFn; };
websiteFn = { pkgs, ... }:
import ./nix/squiggle-website.nix {
inherit pkgs commonFn langFn componentsFn;
};
vscodeextFn = { pkgs, ... }:
import ./nix/squiggle-vscode.nix {
inherit pkgs commonFn langFn componentsFn;
};
cliFn = { pkgs, ... }:
import ./nix/squiggle-cli.nix {
inherit pkgs commonFn;
};
# local machines
localFlakeOutputs = { pkgs, ... }:
let
lang = langFn pkgs;
components = componentsFn pkgs;
website = websiteFn pkgs;
vscodeext = vscodeextFn pkgs;
cli = cliFn pkgs;
in {
# validating
checks = flake-utils.lib.flattenTree {
lang-lint = lang.lint;
lang-test = lang.test;
components-lint = components.lint;
docusaurus-lint = website.lint;
cli-lint = cli.lint;
};
# building
packages = flake-utils.lib.flattenTree {
default = components.build;
lang = lang.build;
lang-bundle = lang.bundle;
lang-test = lang.test;
components = components.build;
components-bundle = components.bundle;
# Lint
lang-lint = lang.lint;
components-lint = components.lint;
docusaurus-lint = website.lint;
vscode-lint = vscodeext.lint;
cli-lint = cli.lint;
};
# developing
devShells = let shellNix = import ./nix/shell.nix { inherit pkgs; };
in flake-utils.lib.flattenTree {
default = shellNix.all;
js = shellNix.just-js;
};
};
in flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = overlays;
};
in localFlakeOutputs pkgs);
}

View File

@ -1 +0,0 @@
Visit `quantified-uncertainty.cachix.org` for information about how to add our binary cache to your local dev environment.

View File

@ -1,25 +0,0 @@
{ pkgs }:
with pkgs;
let
js = [ yarn nodejs nodePackages.ts-node ];
rust = [
wasm-pack
cargo
rustup
pkg-config
libressl
rustfmt
wasmtime
binaryen
wasm-bindgen-cli
];
in {
all = mkShell {
name = "squiggle_yarn-wasm-devshell";
buildInputs = builtins.concatLists [ js rust [ nixfmt ] ];
};
just-js = mkShell {
name = "squiggle_yarn-devshell";
buildInputs = js ++ [ nixfmt ];
};
}

View File

@ -1,13 +0,0 @@
{ pkgs, commonFn }:
rec {
common = commonFn pkgs;
lint = pkgs.stdenv.mkDerivation {
name = "squiggle-cli-lint";
buildInputs = common.buildInputs ++ common.prettier;
src = ../packages/cli;
buildPhase = "prettier --check .";
installPhase = "mkdir -p $out";
};
}

View File

@ -1,75 +0,0 @@
{ pkgs, commonFn, langFn }:
rec {
common = commonFn pkgs;
lang = langFn pkgs;
componentsPackageJson = let
raw = pkgs.lib.importJSON ../packages/components/package.json;
modified =
pkgs.lib.recursiveUpdate raw { dependencies.react-dom = "^18.2.0"; };
packageJsonString = builtins.toJSON modified;
in pkgs.writeText "packages/components/patched-package.json"
packageJsonString;
yarn-source = pkgs.mkYarnPackage {
name = "squiggle-components_yarnsource";
buildInputs = common.buildInputs;
src = ../packages/components;
packageJSON = componentsPackageJson;
yarnLock = ../yarn.lock;
packageResolutions."@quri/squiggle-lang" = lang.build;
};
lint = pkgs.stdenv.mkDerivation {
name = "squiggle-components-lint";
src = ../packages/components;
buildInputs = common.buildInputs ++ common.prettier;
buildPhase = "yarn lint";
installPhase = "mkdir -p $out";
};
build = pkgs.stdenv.mkDerivation {
name = "squiggle-components-build";
src = yarn-source + "/libexec/@quri/squiggle-components";
buildInputs = common.buildInputs;
buildPhase = ''
cp -r node_modules/@quri/squiggle-lang deps/@quri
pushd deps/@quri/squiggle-components
yarn --offline build:cjs
yarn --offline build:css
popd
'';
installPhase = ''
mkdir -p $out
# annoying hack because permissions on transitive dependencies later on
mv deps/@quri/squiggle-components/node_modules deps/@quri/squiggle-components/NODE_MODULES
mv node_modules deps/@quri/squiggle-components
# patching .gitignore so flake keeps build artefacts
sed -i /dist/d deps/@quri/squiggle-components/.gitignore
cp -r deps/@quri/squiggle-components/. $out
'';
};
bundle = pkgs.stdenv.mkDerivation {
name = "squiggle-components-bundle";
src = yarn-source + "/libexec/@quri/squiggle-components";
buildInputs = common.buildInputs;
buildPhase = ''
cp -r node_modules/@quri/squiggle-lang deps/@quri
pushd deps/@quri/squiggle-components
yarn --offline bundle
popd
'';
installPhase = ''
mkdir -p $out
# annoying hack because permissions on transitive dependencies later on
mv deps/@quri/squiggle-components/node_modules deps/@quri/squiggle-components/NODE_MODULES
mv node_modules deps/@quri/squiggle-components
# patching .gitignore so flake keeps build artefacts
sed -i /dist/d deps/@quri/squiggle-components/.gitignore
cp -r deps/@quri/squiggle-components/. $out
'';
};
}

View File

@ -1,116 +0,0 @@
{ pkgs, commonFn, gentypeOutputFn }:
rec {
common = commonFn pkgs;
langPackageJson = let
raw = pkgs.lib.importJSON ../packages/squiggle-lang/package.json;
modified = pkgs.lib.recursiveUpdate raw {
devDependencies."@types/lodash" = "^4.14.167";
};
packageJsonString = builtins.toJSON modified;
in pkgs.writeText "packages/squiggle-lang/patched-package.json"
packageJsonString;
yarn-source = pkgs.mkYarnPackage {
name = "squiggle-lang_yarnsource";
src = ../packages/squiggle-lang;
packageJSON = langPackageJson;
yarnLock = ../yarn.lock;
pkgConfig = {
rescript = {
buildInputs = common.which
++ (if pkgs.system != "i686-linux" then [ pkgs.gcc_multi ] else [ ]);
postInstall = ''
echo "PATCHELF'ING RESCRIPT EXECUTABLES (INCL NINJA)"
# Patching interpreter for linux/*.exe's
THE_LD=$(patchelf --print-interpreter $(which mkdir))
patchelf --set-interpreter $THE_LD linux/*.exe && echo "- patched interpreter for linux/*.exe's"
# Replacing needed shared library for linux/ninja.exe
THE_SO=$(find /nix/store/*/lib64 -name libstdc++.so.6 | head -n 1)
patchelf --replace-needed libstdc++.so.6 $THE_SO linux/ninja.exe && echo "- replaced needed for linux/ninja.exe"
'';
};
gentype = {
postInstall = ''
mv gentype.exe ELFLESS-gentype.exe
cp ${gentypeOutputFn pkgs}/src/GenType.exe gentype.exe
'';
};
};
};
lint = pkgs.stdenv.mkDerivation {
name = "squiggle-lang-lint";
src = yarn-source + "/libexec/@quri/squiggle-lang/deps/@quri/squiggle-lang";
buildInputs = common.buildInputs ++ common.prettier;
buildPhase = ''
yarn lint:prettier
yarn lint:rescript
'';
installPhase = "mkdir -p $out";
};
build = pkgs.stdenv.mkDerivation {
name = "squiggle-lang-build";
# `peggy` is in the `node_modules` that's adjacent to `deps`.
src = yarn-source + "/libexec/@quri/squiggle-lang";
buildInputs = common.buildInputs;
buildPhase = ''
# so that the path to ppx doesn't need to be patched.
mv node_modules deps
pushd deps/@quri/squiggle-lang
yarn --offline build:peggy
yarn --offline build:rescript
yarn --offline build:typescript
# custom gitignore so that the flake keeps build artefacts
mv .gitignore GITIGNORE
sed -i /Reducer_Peggy_GeneratedParser.js/d GITIGNORE
sed -i /ReducerProject_IncludeParser.js/d GITIGNORE
sed -i /\*.bs.js/d GITIGNORE
sed -i /\*.gen.ts/d GITIGNORE
sed -i /\*.gen.tsx/d GITIGNORE
sed -i /\*.gen.js/d GITIGNORE
sed -i /helpers.js/d GITIGNORE
popd
'';
installPhase = ''
mkdir -p $out
# mkdir -p $out/node_modules
mv deps/@quri/squiggle-lang/GITIGNORE deps/@quri/squiggle-lang/.gitignore
# annoying hack because permissions on transitive dependencies later on
mv deps/@quri/squiggle-lang/node_modules deps/@quri/squiggle-lang/NODE_MODULES
mv deps/node_modules deps/@quri/squiggle-lang
# the proper install phase
cp -r deps/@quri/squiggle-lang/. $out
'';
};
test = pkgs.stdenv.mkDerivation {
name = "squiggle-lang-test";
src = build;
buildInputs = common.buildInputs;
buildPhase = ''
yarn --offline test
'';
installPhase = ''
mkdir -p $out
cp -r . $out
'';
};
bundle = pkgs.stdenv.mkDerivation {
name = "squiggle-lang-bundle";
src = test;
buildInputs = common.buildInputs;
buildPhase = ''
yarn --offline bundle
'';
installPhase = ''
mkdir -p $out
cp -r dist $out
cp *.json $out/dist
'';
};
}

View File

@ -1,24 +0,0 @@
{ pkgs, commonFn, langFn, componentsFn }:
rec {
common = commonFn pkgs;
lang = langFn pkgs;
components = componentsFn pkgs;
yarn-source = pkgs.mkYarnPackage {
name = "squiggle-vscodeext_yarnsource";
src = ../packages/vscode-ext;
packageJson = ../packages/vscode-ext/package.json;
yarnLock = ../yarn.lock;
packageResolutions."@quri/squiggle-lang" = lang.build;
packageResolutions."@quri/squiggle-components" = components.build;
};
lint = pkgs.stdenv.mkDerivation {
name = "squiggle-vscode-lint";
buildInputs = common.buildInputs ++ common.prettier;
src =
../packages/vscode-ext; # yarn-source + "/libexec/vscode-squiggle/deps/vscode-squiggle";
buildPhase = "prettier --check .";
installPhase = "mkdir -p $out";
};
}

View File

@ -1,30 +0,0 @@
{ pkgs, commonFn, langFn, componentsFn }:
rec {
common = commonFn pkgs;
lang = langFn pkgs;
components = componentsFn pkgs;
websitePackageJson = let
raw = pkgs.lib.importJSON ../packages/website/package.json;
modified = pkgs.lib.recursiveUpdate raw {
dependencies.postcss-import = "^14.1.0";
dependencies.tailwindcss = "^3.1.8";
};
packageJsonString = builtins.toJSON modified;
in pkgs.writeText "packages/website/patched-package.json" packageJsonString;
yarn-source = pkgs.mkYarnPackage {
name = "squiggle-website_yarnsource";
src = ../packages/website;
packageJSON = websitePackageJson;
yarnLock = ../yarn.lock;
packageResolutions."@quri/squiggle-lang" = lang.build;
packageResolutions."@quri/squiggle-components" = components.build;
};
lint = pkgs.stdenv.mkDerivation {
name = "squiggle-website-lint";
buildInputs = common.buildInputs ++ common.prettier;
src = ../packages/website;
buildPhase = "yarn lint";
installPhase = "mkdir -p $out";
};
}

18
nixos.sh Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
# This script is only relevant if you're rolling nixos.
# Esy (a bisect_ppx dependency/build tool) is borked on nixos without using an FHS shell. https://github.com/esy/esy/issues/858
# We need to patchelf rescript executables. https://github.com/NixOS/nixpkgs/issues/107375
set -x
fhsShellName="squiggle-development"
fhsShellDotNix="{pkgs ? import <nixpkgs> {} }: (pkgs.buildFHSUserEnv { name = \"${fhsShellName}\"; targetPkgs = pkgs: [pkgs.yarn]; runScript = \"yarn\"; }).env"
nix-shell - <<<"$fhsShellDotNix"
theLd=$(patchelf --print-interpreter $(which mkdir))
patchelf --set-interpreter $theLd ./node_modules/gentype/gentype.exe
patchelf --set-interpreter $theLd ./node_modules/rescript/linux/*.exe
patchelf --set-interpreter $theLd ./node_modules/bisect_ppx/ppx
patchelf --set-interpreter $theLd ./node_moduels/bisect_ppx/bisect-ppx-report
theSo=$(find /nix/store/*$fhsShellName*/lib64 -name libstdc++.so.6 | grep $fhsShellName | head -n 1)
patchelf --replace-needed libstdc++.so.6 $theSo ./node_modules/rescript/linux/ninja.exe

View File

@ -2,11 +2,12 @@
"private": true,
"name": "squiggle",
"scripts": {
"nodeclean": "rm -r node_modules && rm -r packages/*/node_modules"
"nodeclean": "rm -r node_modules && rm -r packages/*/node_modules",
"format:all": "prettier --write . && cd packages/squiggle-lang && yarn format",
"lint:all": "prettier --check . && cd packages/squiggle-lang && yarn lint:rescript"
},
"devDependencies": {
"prettier": "^2.7.1",
"turbo": "^1.5.5"
"prettier": "^2.6.2"
},
"workspaces": [
"packages/*"

View File

@ -1,4 +0,0 @@
## Artifacts
*.swp
/node_modules/
yarn-error.log

View File

@ -1,49 +0,0 @@
## Squiggle CLI
This package can be used to incorporate a very simple `import` system into Squiggle.
To use, write special files with a `.squiggleU` file type. In these files, you can write lines like,
```
@import(models/gdp_over_time.squiggle, gdpOverTime)
gdpOverTime(2.5)
```
The imports will be replaced with the contents of the file in `models/gdp_over_time.squiggle` upon compilation. The `.squiggleU` file will be converted into a `.squiggle` file with the `import` statement having this replacement.
## Running
### `npx squiggle-cli-experimental compile`
Runs compilation in the current directory and all of its subdirectories.
### `npx squiggle-cli-experimental watch`
Watches `.squiggleU` files in the current directory (and subdirectories) and rebuilds them when they are saved. Note that this will _not_ rebuild files when their dependencies are changed, just when they are changed directly.
## Further instructions
The above requires having node, npm and npx. To install the first two, see [here](https://nodejs.org/en/), to install npx, run:
```
npm install -g npx
```
Alternatively, you can run the following without the need for npx:
```
npm install squiggle-cli-experimental
node node_modules/squiggle-cli-experimental/index.js compile
```
or you can add a script to your `package.json`, like:
```
...
scripts: {
"compile": "squiggle-cli-experimental compile"
}
...
```
This can be run with `npm run compile`. `npm` knows how to reach into the node_modules directly, so it's not necessary to specify that.

View File

@ -1,96 +0,0 @@
#!/usr/bin/env node
import fs from "fs";
import path from "path";
import indentString from "indent-string";
import chokidar from "chokidar";
import chalk from "chalk";
import { Command } from "commander";
import glob from "glob";
const processFile = (fileName, seen = []) => {
const normalizedFileName = path.resolve(fileName);
if (seen.includes(normalizedFileName)) {
throw new Error(`Recursive dependency for file ${fileName}`);
}
const fileContents = fs.readFileSync(fileName, "utf-8");
if (!fileName.endsWith(".squiggleU")) {
return fileContents;
}
const regex = /\@import\(\s*([^)]+?)\s*\)/g;
const matches = Array.from(fileContents.matchAll(regex)).map((r) =>
r[1].split(/\s*,\s*/)
);
const newContent = fileContents.replaceAll(regex, "");
const appendings = [];
matches.forEach((r) => {
const importFileName = r[0];
const rename = r[1];
const item = fs.statSync(importFileName);
if (item.isFile()) {
const data = processFile(importFileName, [...seen, normalizedFileName]);
if (data) {
const importString = `${rename} = {\n${indentString(data, 2)}\n}\n`;
appendings.push(importString);
}
} else {
console.log(
chalk.red(`Import Error`) +
`: ` +
chalk.cyan(importFileName) +
` not found in file ` +
chalk.cyan(fileName) +
`. Make sure the @import file names all exist in this repo.`
);
}
});
const imports = appendings.join("\n");
const newerContent = imports.concat(newContent);
return newerContent;
};
const run = (fileName) => {
const content = processFile(fileName);
const parsedPath = path.parse(path.resolve(fileName));
const newFilename = `${parsedPath.dir}/${parsedPath.name}.squiggle`;
fs.writeFileSync(newFilename, content);
console.log(chalk.cyan(`Updated ${fileName} -> ${newFilename}`));
};
const compile = () => {
glob("**/*.squiggleU", (_err, files) => {
files.forEach(run);
});
};
const watch = () => {
chokidar
.watch("**.squiggleU")
.on("ready", () => console.log(chalk.green("Ready!")))
.on("change", (event, _) => {
run(event);
});
};
const program = new Command();
program
.name("squiggle-utils")
.description("CLI to transform squiggle files with @imports")
.version("0.0.1");
program
.command("watch")
.description("watch files and compile on the fly")
.action(watch);
program
.command("compile")
.description("compile all .squiggleU files into .squiggle files")
.action(compile);
program.parse();

View File

@ -1,23 +0,0 @@
{
"name": "squiggle-cli-experimental",
"version": "0.0.3",
"main": "index.js",
"homepage": "https://squiggle-language.com",
"author": "Quantified Uncertainty Research Institute",
"bin": "index.js",
"type": "module",
"scripts": {
"start": "node .",
"lint": "prettier --check .",
"format": "prettier --write ."
},
"license": "MIT",
"dependencies": {
"chalk": "^5.1.0",
"chokidar": "^3.5.3",
"commander": "^9.4.1",
"fs": "^0.0.1-security",
"glob": "^8.0.3",
"indent-string": "^5.0.0"
}
}

View File

@ -1,4 +1,2 @@
dist/
storybook-static
src/styles/base.css
src/styles/forms.css

View File

@ -1,15 +1,3 @@
import "../src/styles/main.css";
import "!style-loader!css-loader!postcss-loader!../src/styles/main.css";
import { SquiggleContainer } from "../src/components/SquiggleContainer";
export const decorators = [
(Story) => (
<SquiggleContainer>
<Story />
</SquiggleContainer>
),
];
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {

View File

@ -1,67 +1,8 @@
[![npm version](https://badge.fury.io/js/@quri%2Fsquiggle-components.svg)](https://www.npmjs.com/package/@quri/squiggle-components)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/quantified-uncertainty/squiggle/blob/develop/LICENSE)
# Squiggle Components
# Squiggle components
This package contains all the components for squiggle. These can be used either as a library or hosted as a [storybook](https://storybook.js.org/).
This package contains the react components for squiggle. These can be used either as a library or hosted as a [storybook](https://storybook.js.org/).
The `@quri/squiggle-components` package offers several components and utilities for people who want to embed Squiggle components into websites.
# Usage in a `react` project
For example, in a fresh `create-react-app` project
```sh
yarn add @quri/squiggle-components
```
Add to `App.js`:
```jsx
import { SquiggleEditor } from "@quri/squiggle-components";
<SquiggleEditor
defaultCode="x = beta($alpha, 10); x + $shift"
jsImports={{ alpha: 3, shift: 20 }}
/>;
```
# Usage in a Nextjs project
For now, `squiggle-components` requires the `window` property, so using the package in nextjs requires dynamic loading:
```
import React from "react";
import { SquiggleChart } from "@quri/squiggle-components";
import dynamic from "next/dynamic";
const SquiggleChart = dynamic(
() => import("@quri/squiggle-components").then((mod) => mod.SquiggleChart),
{
loading: () => <p>Loading...</p>,
ssr: false,
}
);
export function DynamicSquiggleChart({ squiggleString }) {
if (squiggleString == "") {
return null;
} else {
return (
<SquiggleChart
defaultCode={squiggleString}
width={445}
height={200}
showSummary={true}
/>
);
}
}
```
# Build storybook for development
# Build for development
We assume that you had run `yarn` at monorepo level, installing dependencies.
@ -79,3 +20,10 @@ Run a development server
```sh
yarn start
```
And build artefacts for production,
```sh
yarn bundle # builds components library
yarn build # builds storybook app
```

View File

@ -1,6 +0,0 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: "ts-jest",
setupFilesAfterEnv: ["<rootDir>/test/setup.js"],
testEnvironment: "jsdom",
};

View File

@ -0,0 +1,8 @@
[build]
base = "packages/components/"
command = "cd ../squiggle-lang && yarn build && cd ../components && yarn build"
publish = "storybook-static/"
ignore = "node -e 'process.exitCode = process.env.BRANCH.includes(\"dependabot\") ? 0 : 1' && git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF . ../squiggle-lang"
[build.environment]
NETLIFY_USE_YARN = "true"

View File

@ -1,92 +1,41 @@
{
"name": "@quri/squiggle-components",
"version": "0.5.0",
"license": "MIT",
"version": "0.1.8",
"dependencies": {
"@floating-ui/react-dom": "^1.0.0",
"@floating-ui/react-dom-interactions": "^0.10.1",
"@headlessui/react": "^1.7.3",
"@heroicons/react": "^1.0.6",
"@hookform/resolvers": "^2.9.8",
"@quri/squiggle-lang": "^0.5.0",
"@quri/squiggle-lang": "0.2.2",
"@react-hook/size": "^2.1.2",
"@types/uuid": "^8.3.4",
"clsx": "^1.2.1",
"framer-motion": "^7.5.3",
"lodash": "^4.17.21",
"react": "^18.1.0",
"react-ace": "^10.1.0",
"react-hook-form": "^7.37.0",
"react-use": "^17.4.0",
"react-vega": "^7.6.0",
"uuid": "^9.0.0",
"vega": "^5.22.1",
"vega-embed": "^6.21.0",
"vega-lite": "^5.5.0",
"vscode-uri": "^3.0.6",
"yup": "^0.32.11"
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.18.6",
"@storybook/addon-actions": "^6.5.12",
"@storybook/addon-essentials": "^6.5.12",
"@storybook/addon-links": "^6.5.12",
"@storybook/builder-webpack5": "^6.5.12",
"@storybook/manager-webpack5": "^6.5.12",
"@storybook/node-logger": "^6.5.9",
"@storybook/preset-create-react-app": "^4.1.2",
"@storybook/react": "^6.5.12",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
"@types/jest": "^27.5.0",
"@types/lodash": "^4.14.186",
"@types/node": "^18.8.3",
"@types/react": "^18.0.21",
"@types/styled-components": "^5.1.26",
"@types/uuid": "^8.3.4",
"@types/webpack": "^5.28.0",
"canvas": "^2.10.1",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.1.1",
"@testing-library/user-event": "^14.1.1",
"@types/jest": "^27.4.0",
"@types/lodash": "^4.14.182",
"@types/node": "^17.0.25",
"@types/react": "^18.0.3",
"@types/react-dom": "^18.0.2",
"antd": "^4.19.3",
"cross-env": "^7.0.3",
"jest": "^29.0.3",
"jest-environment-jsdom": "^29.1.2",
"jsdom": "^20.0.1",
"mini-css-extract-plugin": "^2.6.1",
"postcss-cli": "^10.0.0",
"postcss-import": "^15.0.0",
"postcss-loader": "^7.0.1",
"postcss-nesting": "^10.2.0",
"react": "^18.1.0",
"react-scripts": "^5.0.1",
"style-loader": "^3.3.1",
"tailwindcss": "^3.1.8",
"ts-jest": "^29.0.3",
"ts-loader": "^9.4.1",
"tsconfig-paths-webpack-plugin": "^4.0.0",
"typescript": "^4.8.4",
"web-vitals": "^3.0.3",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.1"
},
"peerDependencies": {
"react": "^16.8.0 || ^17 || ^18",
"react-dom": "^16.8.0 || ^17 || ^18"
"lodash": "^4.17.21",
"react": "^18.0.0",
"react-ace": "10.0.0",
"react-dom": "^18.0.0",
"react-scripts": "5.0.1",
"react-vega": "^7.5.0",
"styled-components": "^5.3.5",
"tsconfig-paths-webpack-plugin": "^3.5.2",
"typescript": "^4.6.3",
"vega": "^5.22.1",
"vega-embed": "^6.20.6",
"vega-lite": "^5.2.0",
"web-vitals": "^2.1.4",
"webpack-cli": "^4.9.2"
},
"scripts": {
"start": "cross-env REACT_APP_FAST_REFRESH=false && start-storybook -p 6006 -s public",
"build:cjs": "rm -rf dist/src && rm -f dist/tsconfig.tsbuildinfo && tsc -b",
"build:css": "postcss ./src/styles/main.css -o ./dist/main.css",
"build:storybook": "build-storybook -s public",
"build": "yarn run build:cjs && yarn run build:css && yarn run build:storybook",
"build": "tsc -b && build-storybook -s public",
"bundle": "webpack",
"all": "yarn bundle && yarn build",
"lint": "prettier --check .",
"format": "prettier --write .",
"prepack": "yarn run build:cjs && yarn run bundle",
"test": "jest",
"test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
"test:profile": "node --cpu-prof node_modules/.bin/jest --runInBand"
"format": "prettier --write ."
},
"eslintConfig": {
"extends": [
@ -116,10 +65,29 @@
"last 1 safari version"
]
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.16.7",
"@storybook/addon-actions": "^6.4.22",
"@storybook/addon-essentials": "^6.4.22",
"@storybook/addon-links": "^6.4.22",
"@storybook/builder-webpack5": "^6.4.22",
"@storybook/manager-webpack5": "^6.4.22",
"@storybook/node-logger": "^6.4.22",
"@storybook/preset-create-react-app": "^4.1.0",
"@storybook/react": "^6.4.22",
"@types/styled-components": "^5.1.24",
"@types/webpack": "^5.28.0",
"react-codejar": "^1.1.2",
"style-loader": "^3.3.1",
"ts-loader": "^9.2.8",
"webpack": "^5.72.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.8.1"
},
"resolutions": {
"@types/react": "17.0.43"
},
"source": "./src/index.ts",
"main": "./dist/src/index.js",
"types": "./dist/src/index.d.ts"
"main": "dist/bundle.js",
"types": "dist/src/index.d.ts"
}

View File

@ -1,9 +0,0 @@
module.exports = {
plugins: {
"postcss-import": {},
"tailwindcss/nesting": {},
tailwindcss: {},
autoprefixer: {},
cssnano: {},
},
};

File diff suppressed because one or more lines are too long

View File

@ -1,86 +0,0 @@
import * as React from "react";
import {
XCircleIcon,
InformationCircleIcon,
CheckCircleIcon,
} from "@heroicons/react/solid";
import clsx from "clsx";
export const Alert: React.FC<{
heading: string;
backgroundColor: string;
headingColor: string;
bodyColor: string;
icon: (props: React.ComponentProps<"svg">) => JSX.Element;
iconColor: string;
children?: React.ReactNode;
}> = ({
heading = "Error",
backgroundColor,
headingColor,
bodyColor,
icon: Icon,
iconColor,
children,
}) => {
return (
<div className={clsx("rounded-md p-4", backgroundColor)} role="status">
<div className="flex">
<Icon
className={clsx("h-5 w-5 flex-shrink-0", iconColor)}
aria-hidden="true"
/>
<div className="ml-3 grow">
<header className={clsx("text-sm font-medium", headingColor)}>
{heading}
</header>
{children && React.Children.count(children) ? (
<div className={clsx("mt-2 text-sm", bodyColor)}>{children}</div>
) : null}
</div>
</div>
</div>
);
};
export const ErrorAlert: React.FC<{
heading: string;
children?: React.ReactNode;
}> = (props) => (
<Alert
{...props}
backgroundColor="bg-red-100"
headingColor="text-red-800"
bodyColor="text-red-700"
icon={XCircleIcon}
iconColor="text-red-400"
/>
);
export const MessageAlert: React.FC<{
heading: string;
children?: React.ReactNode;
}> = (props) => (
<Alert
{...props}
backgroundColor="bg-slate-100"
headingColor="text-slate-700"
bodyColor="text-slate-700"
icon={InformationCircleIcon}
iconColor="text-slate-400"
/>
);
export const SuccessAlert: React.FC<{
heading: string;
children?: React.ReactNode;
}> = (props) => (
<Alert
{...props}
backgroundColor="bg-green-50"
headingColor="text-green-800"
bodyColor="text-green-700"
icon={CheckCircleIcon}
iconColor="text-green-400"
/>
);

View File

@ -1,49 +1,34 @@
import _ from "lodash";
import React, { FC, useMemo, useRef } from "react";
import React, { FC } from "react";
import AceEditor from "react-ace";
import "ace-builds/src-noconflict/mode-golang";
import "ace-builds/src-noconflict/theme-github";
import { SqLocation } from "@quri/squiggle-lang";
interface CodeEditorProps {
value: string;
onChange: (value: string) => void;
onSubmit?: () => void;
oneLine?: boolean;
width?: number;
height: number;
showGutter?: boolean;
errorLocations?: SqLocation[];
}
export const CodeEditor: FC<CodeEditorProps> = ({
export let CodeEditor: FC<CodeEditorProps> = ({
value,
onChange,
onSubmit,
height,
oneLine = false,
showGutter = false,
errorLocations = [],
}) => {
const lineCount = value.split("\n").length;
const id = useMemo(() => _.uniqueId(), []);
// this is necessary because AceEditor binds commands on mount, see https://github.com/securingsincity/react-ace/issues/684
const onSubmitRef = useRef<typeof onSubmit | null>(null);
onSubmitRef.current = onSubmit;
const editorEl = useRef<AceEditor | null>(null);
height,
}: CodeEditorProps) => {
let lineCount = value.split("\n").length;
let id = _.uniqueId();
return (
<AceEditor
ref={editorEl}
value={value}
mode="golang"
theme="github"
width="100%"
fontSize={14}
width={"100%"}
height={String(height) + "px"}
minLines={oneLine ? lineCount : undefined}
maxLines={oneLine ? lineCount : undefined}
@ -55,22 +40,11 @@ export const CodeEditor: FC<CodeEditorProps> = ({
editorProps={{
$blockScrolling: true,
}}
setOptions={{}}
commands={[
{
name: "submit",
bindKey: { mac: "Cmd-Enter", win: "Ctrl-Enter" },
exec: () => onSubmitRef.current?.(),
},
]}
markers={errorLocations?.map((location) => ({
startRow: location.start.line - 1,
startCol: location.start.column - 1,
endRow: location.end.line - 1,
endCol: location.end.column - 1,
className: "ace-error-marker",
type: "text",
}))}
setOptions={{
enableBasicAutocompletion: false,
enableLiveAutocompletion: false,
}}
/>
);
};
export default CodeEditor;

View File

@ -1,222 +1,42 @@
import * as React from "react";
import {
SqDistribution,
result,
SqDistributionError,
resultMap,
SqRecord,
environment,
SqDistributionTag,
} from "@quri/squiggle-lang";
import { Vega } from "react-vega";
import { ErrorAlert } from "./Alert";
import { useSize } from "react-use";
import _ from "lodash";
import type { Spec } from "vega";
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";
import { ErrorBox } from "./ErrorBox";
import {
buildVegaSpec,
DistributionChartSpecOptions,
} from "../lib/distributionSpecBuilder";
import { NumberShower } from "./NumberShower";
import { Plot, parsePlot } from "../lib/plotParser";
import { flattenResult } from "../lib/utility";
import { hasMassBelowZero } from "../lib/distributionUtils";
let SquiggleVegaChart = createClassFromSpec({
spec: chartSpecification as Spec,
});
export type DistributionPlottingSettings = {
/** Whether to show a summary of means, stdev, percentiles etc */
showSummary: boolean;
actions?: boolean;
} & DistributionChartSpecOptions;
export type DistributionChartProps = {
plot: Plot;
environment: environment;
width?: number;
type DistributionChartProps = {
distribution: Distribution;
width: number;
height: number;
xAxisType?: "number" | "dateTime";
} & DistributionPlottingSettings;
export function defaultPlot(distribution: SqDistribution): Plot {
return { distributions: [{ name: "default", distribution }] };
}
export function makePlot(record: SqRecord): Plot | void {
const plotResult = parsePlot(record);
if (plotResult.tag === "Ok") {
return plotResult.value;
}
}
export const DistributionChart: React.FC<DistributionChartProps> = (props) => {
const {
plot,
environment,
height,
showSummary,
width,
logX,
actions = false,
} = props;
const [sized] = useSize((size) => {
const shapes = flattenResult(
plot.distributions.map((x) =>
resultMap(x.distribution.pointSet(environment), (pointSet) => ({
name: x.name,
// color: x.color, // not supported yet
...pointSet.asShape(),
}))
)
);
if (shapes.tag === "Error") {
return (
<ErrorAlert heading="Distribution Error">
{shapes.value.toString()}
</ErrorAlert>
);
}
// if this is a sample set, include the samples
const samples: number[] = [];
for (const { distribution } of plot?.distributions) {
if (distribution.tag === SqDistributionTag.SampleSet) {
samples.push(...distribution.value());
}
}
const domain = shapes.value.flatMap((shape) =>
shape.discrete.concat(shape.continuous)
);
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) {
console.warn(
`Width of Distribution is set to ${widthProp}, which is too small`
);
widthProp = 20;
}
const vegaData = { data: shapes.value, samples };
return (
<div style={{ width: widthProp }}>
{logX && shapes.value.some(hasMassBelowZero) ? (
<ErrorAlert heading="Log Domain Error">
Cannot graph distribution with negative values on logarithmic scale.
</ErrorAlert>
) : (
<Vega
spec={spec}
data={vegaData}
width={widthProp - 10}
height={height}
actions={actions}
/>
)}
<div className="flex justify-center">
{showSummary && plot.distributions.length === 1 && (
<SummaryTable
distribution={plot.distributions[0].distribution}
environment={environment}
/>
)}
</div>
</div>
);
});
return sized;
};
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 = {
distribution: SqDistribution;
environment: environment;
};
const SummaryTable: React.FC<SummaryTableProps> = ({
export const DistributionChart: React.FC<DistributionChartProps> = ({
distribution,
environment,
}) => {
const mean = distribution.mean(environment);
const stdev = distribution.stdev(environment);
const p5 = distribution.inv(environment, 0.05);
const p10 = distribution.inv(environment, 0.1);
const p25 = distribution.inv(environment, 0.25);
const p50 = distribution.inv(environment, 0.5);
const p75 = distribution.inv(environment, 0.75);
const p90 = distribution.inv(environment, 0.9);
const p95 = distribution.inv(environment, 0.95);
const hasResult = (x: result<number, SqDistributionError>): boolean =>
x.tag === "Ok";
const unwrapResult = (
x: result<number, SqDistributionError>
): React.ReactNode => {
if (x.tag === "Ok") {
return <NumberShower number={x.value} />;
} else {
return (
<ErrorAlert heading="Distribution Error">
{x.value.toString()}
</ErrorAlert>
);
}
};
return (
<table className="border border-collapse border-slate-400">
<thead className="bg-slate-50">
<tr>
<TableHeadCell>{"Mean"}</TableHeadCell>
{hasResult(stdev) && <TableHeadCell>{"Stdev"}</TableHeadCell>}
<TableHeadCell>{"5%"}</TableHeadCell>
<TableHeadCell>{"10%"}</TableHeadCell>
<TableHeadCell>{"25%"}</TableHeadCell>
<TableHeadCell>{"50%"}</TableHeadCell>
<TableHeadCell>{"75%"}</TableHeadCell>
<TableHeadCell>{"90%"}</TableHeadCell>
<TableHeadCell>{"95%"}</TableHeadCell>
</tr>
</thead>
<tbody>
<tr>
<Cell>{unwrapResult(mean)}</Cell>
{hasResult(stdev) && <Cell>{unwrapResult(stdev)}</Cell>}
<Cell>{unwrapResult(p5)}</Cell>
<Cell>{unwrapResult(p10)}</Cell>
<Cell>{unwrapResult(p25)}</Cell>
<Cell>{unwrapResult(p50)}</Cell>
<Cell>{unwrapResult(p75)}</Cell>
<Cell>{unwrapResult(p90)}</Cell>
<Cell>{unwrapResult(p95)}</Cell>
</tr>
</tbody>
</table>
);
width,
height,
}: DistributionChartProps) => {
let shape = distribution.pointSet();
if (shape.tag === "Ok") {
return (
<SquiggleVegaChart
data={{ con: shape.value.continuous, dis: shape.value.discrete }}
width={width - 20}
height={height}
actions={false}
/>
);
} else {
return (
<ErrorBox heading="Distribution Error">
{distributionErrorToString(shape.value)}
</ErrorBox>
);
}
};

View File

@ -1,80 +0,0 @@
import type { LogScale, LinearScale, PowScale } from "vega";
export let linearXScale: LinearScale = {
name: "xscale",
type: "linear",
range: "width",
zero: false,
nice: false,
domain: {
fields: [
{
data: "con",
field: "x",
},
{
data: "dis",
field: "x",
},
],
},
};
export let linearYScale: LinearScale = {
name: "yscale",
type: "linear",
range: "height",
zero: true,
domain: {
fields: [
{
data: "con",
field: "y",
},
{
data: "dis",
field: "y",
},
],
},
};
export let logXScale: LogScale = {
name: "xscale",
type: "log",
range: "width",
zero: false,
base: 10,
nice: false,
domain: {
fields: [
{
data: "con",
field: "x",
},
{
data: "dis",
field: "x",
},
],
},
};
export let expYScale: PowScale = {
name: "yscale",
type: "pow",
exponent: 0.1,
range: "height",
zero: true,
nice: false,
domain: {
fields: [
{
data: "con",
field: "y",
},
{
data: "dis",
field: "y",
},
],
},
};

View File

@ -0,0 +1,20 @@
import * as React from "react";
import styled from "styled-components";
const ShowError = styled.div`
border: 1px solid #792e2e;
background: #eee2e2;
padding: 0.4em 0.8em;
`;
export const ErrorBox: React.FC<{
heading: string;
children: React.ReactNode;
}> = ({ heading = "Error", children }) => {
return (
<ShowError>
<h3>{heading}</h3>
{children}
</ShowError>
);
};

View File

@ -1,107 +1,115 @@
import * as React from "react";
import {
SqLambda,
environment,
SqValueTag,
SqError,
} from "@quri/squiggle-lang";
import { FunctionChart1Dist } from "./FunctionChart1Dist";
import { FunctionChart1Number } from "./FunctionChart1Number";
import { DistributionPlottingSettings } from "./DistributionChart";
import { MessageAlert } from "./Alert";
import { SquiggleErrorAlert } from "./SquiggleErrorAlert";
import _ from "lodash";
import type { Spec } from "vega";
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 { ErrorBox } from "./ErrorBox";
export type FunctionChartSettings = {
start: number;
stop: number;
count: number;
let SquigglePercentilesChart = createClassFromSpec({
spec: percentilesSpec as Spec,
});
type distPlusFn = (a: number) => result<Distribution, errorValue>;
const _rangeByCount = (start: number, stop: number, count: number) => {
const step = (stop - start) / (count - 1);
const items = _.range(start, stop, step);
const result = items.concat([stop]);
return result;
};
interface FunctionChartProps {
fn: SqLambda;
chartSettings: FunctionChartSettings;
distributionPlotSettings: DistributionPlottingSettings;
environment: environment;
height: number;
function unwrap<a, b>(x: result<a, b>): a {
if (x.tag === "Ok") {
return x.value;
} else {
throw Error("FAILURE TO UNWRAP");
}
}
const FunctionCallErrorAlert = ({ error }: { error: SqError }) => {
const [expanded, setExpanded] = React.useState(false);
if (expanded) {
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;
diagramStop: number;
diagramCount: number;
}> = ({ distPlusFn, diagramStart, diagramStop, diagramCount }) => {
let [mouseOverlay, setMouseOverlay] = React.useState(0);
function handleHover(...args) {
setMouseOverlay(args[1]);
}
function handleOut() {
setMouseOverlay(NaN);
}
const signalListeners = { mousemove: handleHover, mouseout: handleOut };
let mouseItem = distPlusFn(mouseOverlay);
let showChart =
mouseItem.tag === "Ok" ? (
<DistributionChart
distribution={mouseItem.value}
width={400}
height={140}
/>
) : (
<></>
);
let data1 = _rangeByCount(diagramStart, diagramStop, diagramCount);
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 = 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 (
<MessageAlert heading="Function Display Failed">
<div className="space-y-2">
<span
className="underline decoration-dashed cursor-pointer"
onClick={() => setExpanded(!expanded)}
>
{expanded ? "Hide" : "Show"} error details
</span>
{expanded ? <SquiggleErrorAlert error={error} /> : null}
</div>
</MessageAlert>
<>
<SquigglePercentilesChart
data={{ facet: valueData }}
actions={false}
signalListeners={signalListeners}
/>
{showChart}
{_.keysIn(error2).map((k) => (
<ErrorBox heading={k}>
{`Values: [${error2[k].map((r) => r.x.toFixed(2)).join(",")}]`}
</ErrorBox>
))}
</>
);
};
export const FunctionChart: React.FC<FunctionChartProps> = ({
fn,
chartSettings,
environment,
distributionPlotSettings,
height,
}) => {
console.log(fn.parameters().length);
if (fn.parameters().length !== 1) {
return (
<MessageAlert heading="Function Display Not Supported">
Only functions with one parameter are displayed.
</MessageAlert>
);
}
const result1 = fn.call([chartSettings.start]);
const result2 = fn.call([chartSettings.stop]);
const getValidResult = () => {
if (result1.tag === "Ok") {
return result1;
} else if (result2.tag === "Ok") {
return result2;
} else {
return result1;
}
};
const validResult = getValidResult();
if (validResult.tag === "Error") {
return <FunctionCallErrorAlert error={validResult.value} />;
}
switch (validResult.value.tag) {
case SqValueTag.Distribution:
return (
<FunctionChart1Dist
fn={fn}
chartSettings={chartSettings}
environment={environment}
height={height}
distributionPlotSettings={distributionPlotSettings}
/>
);
case SqValueTag.Number:
return (
<FunctionChart1Number
fn={fn}
chartSettings={chartSettings}
environment={environment}
height={height}
/>
);
default:
return (
<MessageAlert heading="Function Display Not Supported">
There is no function visualization for this type of output:{" "}
<span className="font-bold">{validResult.value.tag}</span>
</MessageAlert>
);
}
};

View File

@ -1,225 +0,0 @@
import * as React from "react";
import _ from "lodash";
import type { Spec } from "vega";
import {
SqDistribution,
result,
SqLambda,
environment,
SqError,
SqValue,
SqValueTag,
} from "@quri/squiggle-lang";
import { createClassFromSpec } from "react-vega";
import * as percentilesSpec from "../vega-specs/spec-percentiles.json";
import {
DistributionChart,
DistributionPlottingSettings,
defaultPlot,
} from "./DistributionChart";
import { NumberShower } from "./NumberShower";
import { ErrorAlert } from "./Alert";
let SquigglePercentilesChart = createClassFromSpec({
spec: percentilesSpec as Spec,
});
const _rangeByCount = (start: number, stop: number, count: number) => {
const step = (stop - start) / (count - 1);
const items = _.range(start, stop, step);
const result = items.concat([stop]);
return result;
};
function unwrap<a, b>(x: result<a, b>): a {
if (x.tag === "Ok") {
return x.value;
} else {
throw Error("FAILURE TO UNWRAP");
}
}
export type FunctionChartSettings = {
start: number;
stop: number;
count: number;
};
interface FunctionChart1DistProps {
fn: SqLambda;
chartSettings: FunctionChartSettings;
distributionPlotSettings: DistributionPlottingSettings;
environment: environment;
height: number;
}
type percentiles = {
x: number;
p1: number;
p5: number;
p10: number;
p20: number;
p30: number;
p40: number;
p50: number;
p60: number;
p70: number;
p80: number;
p90: number;
p95: number;
p99: number;
}[];
type errors = _.Dictionary<
{
x: number;
value: string;
}[]
>;
type point = { x: number; value: result<SqDistribution, string> };
let getPercentiles = ({
chartSettings,
fn,
environment,
}: {
chartSettings: FunctionChartSettings;
fn: SqLambda;
environment: environment;
}) => {
let chartPointsToRender = _rangeByCount(
chartSettings.start,
chartSettings.stop,
chartSettings.count
);
let chartPointsData: point[] = chartPointsToRender.map((x) => {
let result = fn.call([x]);
if (result.tag === "Ok") {
if (result.value.tag === SqValueTag.Distribution) {
return { x, value: { tag: "Ok", value: result.value.value } };
} else {
return {
x,
value: {
tag: "Error",
value:
"Cannot currently render functions that don't return distributions",
},
};
}
} else {
return {
x,
value: { tag: "Error", value: result.value.toString() },
};
}
});
let initialPartition: [
{ x: number; value: SqDistribution }[],
{ x: number; value: string }[]
] = [[], []];
let [functionImage, errors] = chartPointsData.reduce((acc, current) => {
if (current.value.tag === "Ok") {
acc[0].push({ x: current.x, value: current.value.value });
} else {
acc[1].push({ x: current.x, value: current.value.value });
}
return acc;
}, initialPartition);
let groupedErrors: errors = _.groupBy(errors, (x) => x.value);
let percentiles: percentiles = functionImage.map(({ x, value }) => {
const res = {
x: x,
p1: unwrap(value.inv(environment, 0.01)),
p5: unwrap(value.inv(environment, 0.05)),
p10: unwrap(value.inv(environment, 0.1)),
p20: unwrap(value.inv(environment, 0.2)),
p30: unwrap(value.inv(environment, 0.3)),
p40: unwrap(value.inv(environment, 0.4)),
p50: unwrap(value.inv(environment, 0.5)),
p60: unwrap(value.inv(environment, 0.6)),
p70: unwrap(value.inv(environment, 0.7)),
p80: unwrap(value.inv(environment, 0.8)),
p90: unwrap(value.inv(environment, 0.9)),
p95: unwrap(value.inv(environment, 0.95)),
p99: unwrap(value.inv(environment, 0.99)),
};
return res;
});
return { percentiles, errors: groupedErrors };
};
export const FunctionChart1Dist: React.FC<FunctionChart1DistProps> = ({
fn,
chartSettings,
environment,
distributionPlotSettings,
height,
}) => {
let [mouseOverlay, setMouseOverlay] = React.useState(0);
function handleHover(_name: string, value: unknown) {
setMouseOverlay(value as number);
}
function handleOut() {
setMouseOverlay(NaN);
}
const signalListeners = { mousemove: handleHover, mouseout: handleOut };
//TODO: This custom error handling is a bit hacky and should be improved.
let mouseItem: result<SqValue, SqError> = !!mouseOverlay
? fn.call([mouseOverlay])
: {
tag: "Error",
value: SqError.createOtherError(
"Hover x-coordinate returned NaN. Expected a number."
),
};
let showChart =
mouseItem.tag === "Ok" &&
mouseItem.value.tag === SqValueTag.Distribution ? (
<DistributionChart
plot={defaultPlot(mouseItem.value.value)}
environment={environment}
width={400}
height={50}
{...distributionPlotSettings}
/>
) : null;
let getPercentilesMemoized = React.useMemo(
() => getPercentiles({ chartSettings, fn, environment }),
[environment, fn]
);
return (
<>
<SquigglePercentilesChart
data={{ facet: getPercentilesMemoized.percentiles }}
height={height}
actions={false}
signalListeners={signalListeners}
/>
{showChart}
{_.entries(getPercentilesMemoized.errors).map(
([errorName, errorPoints]) => (
<ErrorAlert key={errorName} heading={errorName}>
Values:{" "}
{errorPoints
.map((r, i) => <NumberShower key={i} number={r.x} />)
.reduce((a, b) => (
<>
{a}, {b}
</>
))}
</ErrorAlert>
)
)}
</>
);
};

View File

@ -1,119 +0,0 @@
import * as React from "react";
import _ from "lodash";
import type { Spec } from "vega";
import { result, SqLambda, environment, SqValueTag } from "@quri/squiggle-lang";
import { createClassFromSpec } from "react-vega";
import * as lineChartSpec from "../vega-specs/spec-line-chart.json";
import { ErrorAlert } from "./Alert";
import { squiggleValueTag } from "@quri/squiggle-lang/src/rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_tag";
let SquiggleLineChart = createClassFromSpec({
spec: lineChartSpec as Spec,
});
const _rangeByCount = (start: number, stop: number, count: number) => {
const step = (stop - start) / (count - 1);
const items = _.range(start, stop, step);
const result = items.concat([stop]);
return result;
};
export type FunctionChartSettings = {
start: number;
stop: number;
count: number;
};
interface FunctionChart1NumberProps {
fn: SqLambda;
chartSettings: FunctionChartSettings;
environment: environment;
height: number;
}
type point = { x: number; value: result<number, string> };
let getFunctionImage = ({
chartSettings,
fn,
environment,
}: {
chartSettings: FunctionChartSettings;
fn: SqLambda;
environment: environment;
}) => {
let chartPointsToRender = _rangeByCount(
chartSettings.start,
chartSettings.stop,
chartSettings.count
);
let chartPointsData: point[] = chartPointsToRender.map((x) => {
let result = fn.call([x]);
if (result.tag === "Ok") {
if (result.value.tag === SqValueTag.Number) {
return { x, value: { tag: "Ok", value: result.value.value } };
} else {
return {
x,
value: {
tag: "Error",
value: "This component expected number outputs",
},
};
}
} else {
return {
x,
value: { tag: "Error", value: result.value.toString() },
};
}
});
let initialPartition: [
{ x: number; value: number }[],
{ x: number; value: string }[]
] = [[], []];
let [functionImage, errors] = chartPointsData.reduce((acc, current) => {
if (current.value.tag === "Ok") {
acc[0].push({ x: current.x, value: current.value.value });
} else {
acc[1].push({ x: current.x, value: current.value.value });
}
return acc;
}, initialPartition);
return { errors, functionImage };
};
export const FunctionChart1Number: React.FC<FunctionChart1NumberProps> = ({
fn,
chartSettings,
environment,
height,
}: FunctionChart1NumberProps) => {
let getFunctionImageMemoized = React.useMemo(
() => getFunctionImage({ chartSettings, fn, environment }),
[environment, fn]
);
let data = getFunctionImageMemoized.functionImage.map(({ x, value }) => ({
x,
y: value,
}));
return (
<>
<SquiggleLineChart
data={{ facet: data }}
height={height}
actions={false}
/>
{getFunctionImageMemoized.errors.map(({ x, value }) => (
<ErrorAlert key={x} heading={value}>
Error at point ${x}
</ErrorAlert>
))}
</>
);
};

View File

@ -1,49 +0,0 @@
import _ from "lodash";
import React, { FC } from "react";
import AceEditor from "react-ace";
import "ace-builds/src-noconflict/mode-json";
import "ace-builds/src-noconflict/theme-github";
interface CodeEditorProps {
value: string;
onChange: (value: string) => void;
oneLine?: boolean;
width?: number;
height: number;
showGutter?: boolean;
}
export const JsonEditor: FC<CodeEditorProps> = ({
value,
onChange,
oneLine = false,
showGutter = false,
height,
}) => {
const lineCount = value.split("\n").length;
const id = _.uniqueId();
return (
<AceEditor
value={value}
mode="json"
theme="github"
width={"100%"}
height={String(height) + "px"}
minLines={oneLine ? lineCount : undefined}
maxLines={oneLine ? lineCount : undefined}
showGutter={showGutter}
highlightActiveLine={false}
showPrintMargin={false}
onChange={onChange}
name={id}
editorProps={{
$blockScrolling: true,
}}
setOptions={{
enableBasicAutocompletion: false,
enableLiveAutocompletion: false,
}}
/>
);
};

View File

@ -1,4 +1,5 @@
import * as React from "react";
import _ from "lodash";
const orderOfMagnitudeNum = (n: number) => {
return Math.pow(10, n);
@ -73,23 +74,25 @@ export interface NumberShowerProps {
precision?: number;
}
export const NumberShower: React.FC<NumberShowerProps> = ({
export let NumberShower: React.FC<NumberShowerProps> = ({
number,
precision = 2,
}) => {
const numberWithPresentation = numberShow(number, precision);
}: NumberShowerProps) => {
let numberWithPresentation = numberShow(number, precision);
return (
<span>
{numberWithPresentation.value}
{numberWithPresentation.symbol}
{numberWithPresentation.power ? (
<span>
{"\u00b7" /* dot symbol */}10
{"\u00b710"}
<span style={{ fontSize: "0.6em", verticalAlign: "super" }}>
{numberWithPresentation.power}
</span>
</span>
) : null}
) : (
<></>
)}
</span>
);
};

View File

@ -1,158 +1,174 @@
import * as React from "react";
import _ from "lodash";
import styled from "styled-components";
import {
SqValue,
environment,
SqProject,
defaultEnvironment,
run,
errorValueToString,
squiggleExpression,
} from "@quri/squiggle-lang";
import { useSquiggle } from "../lib/hooks";
import { SquiggleViewer } from "./SquiggleViewer";
import { JsImports } from "../lib/jsImports";
import { getValueToRender } from "../lib/utility";
import type { samplingParams } from "@quri/squiggle-lang";
import { NumberShower } from "./NumberShower";
import { DistributionChart } from "./DistributionChart";