From d4f929367d4a9d098d6694ff6cec63078481e649 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 29 Apr 2022 18:46:44 +0000 Subject: [PATCH 1/8] JS parameters in squiggle lang --- packages/components/package.json | 35 ++++++------ .../squiggle-lang/__tests__/TS/JS_test.ts | 23 ++++++++ .../squiggle-lang/__tests__/TS/TestHelpers.ts | 38 +++++++++---- packages/squiggle-lang/src/js/index.ts | 56 +++++++++++++++++-- .../Reducer_MathJs/Reducer_MathJs_Eval.res | 1 + 5 files changed, 120 insertions(+), 33 deletions(-) diff --git a/packages/components/package.json b/packages/components/package.json index de8efb96..3b50afbf 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,19 +1,19 @@ { "name": "@quri/squiggle-components", - "version": "0.2.14", + "version": "0.2.15", "license": "MIT", "dependencies": { - "react-ace": "10.1.0", "@quri/squiggle-lang": "^0.2.7", - "react-dom": "^18.1.0", - "vega": "^5.22.1", - "vega-embed": "^6.20.6", - "vega-lite": "^5.2.0", - "react-vega": "^7.5.0", - "react": "^18.1.0", "@react-hook/size": "^2.1.2", "lodash": "^4.17.21", - "styled-components": "^5.3.5" + "react": "^18.1.0", + "react-ace": "10.1.0", + "react-dom": "^18.1.0", + "react-vega": "^7.5.0", + "styled-components": "^5.3.5", + "vega": "^5.22.1", + "vega-embed": "^6.20.6", + "vega-lite": "^5.2.0" }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.16.7", @@ -25,27 +25,26 @@ "@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", - "style-loader": "^3.3.1", - "ts-loader": "^9.2.9", - "webpack": "^5.72.0", - "webpack-cli": "^4.9.2", - "webpack-dev-server": "^4.8.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", - "web-vitals": "^2.1.4", "@types/lodash": "^4.14.182", "@types/node": "^17.0.29", "@types/react": "^18.0.3", "@types/react-dom": "^18.0.2", + "@types/styled-components": "^5.1.24", + "@types/webpack": "^5.28.0", "cross-env": "^7.0.3", "react-scripts": "5.0.1", + "style-loader": "^3.3.1", + "ts-loader": "^9.2.9", "tsconfig-paths-webpack-plugin": "^3.5.2", "typescript": "^4.6.3", - "webpack-cli": "^4.9.2" + "web-vitals": "^2.1.4", + "webpack": "^5.72.0", + "webpack-cli": "^4.9.2", + "webpack-dev-server": "^4.8.1" }, "scripts": { "start": "cross-env REACT_APP_FAST_REFRESH=false && start-storybook -p 6006 -s public", diff --git a/packages/squiggle-lang/__tests__/TS/JS_test.ts b/packages/squiggle-lang/__tests__/TS/JS_test.ts index e522eb95..62051261 100644 --- a/packages/squiggle-lang/__tests__/TS/JS_test.ts +++ b/packages/squiggle-lang/__tests__/TS/JS_test.ts @@ -68,6 +68,29 @@ describe("Partials", () => { }); }); +describe("Parameters", () => { + test("Can pass parameters into partials and cells", () => { + let bindings = testRunPartial(`y = $x + 2`, {}, { x: 1 }); // y = 3 + let bindings2 = testRunPartial(`z = $x + y * $a`, bindings, { a: 3 }); // z = 1 + 3 * 3 = 10 + expect(testRun(`z + $x + $a + y`, bindings2)).toEqual({ + tag: "number", + value: 17, + }); + }); + test("Complicated deep parameters", () => { + expect( + testRun( + `$x.y[0][0].w + $x.z + $u.v`, + {}, + { x: { y: [[{ w: 1 }]], z: 2 }, u: { v: 3 } } + ) + ).toEqual({ + tag: "number", + value: 6, + }); + }); +}); + describe("Distribution", () => { //It's important that sampleCount is less than 9. If it's more, than that will create randomness //Also, note, the value should be created using makeSampleSetDist() later on. diff --git a/packages/squiggle-lang/__tests__/TS/TestHelpers.ts b/packages/squiggle-lang/__tests__/TS/TestHelpers.ts index 7d51c98e..3bbf42d8 100644 --- a/packages/squiggle-lang/__tests__/TS/TestHelpers.ts +++ b/packages/squiggle-lang/__tests__/TS/TestHelpers.ts @@ -6,11 +6,20 @@ import { errorValueToString, } from "../../src/js/index"; -export function testRun(x: string, bindings = {}): squiggleExpression { - let squiggleResult = run(x, bindings, { - sampleCount: 1000, - xyPointLength: 100, - }); +export function testRun( + x: string, + bindings = {}, + parameters = {} +): squiggleExpression { + let squiggleResult = run( + x, + bindings, + { + sampleCount: 1000, + xyPointLength: 100, + }, + parameters + ); // return squiggleResult.value if (squiggleResult.tag === "Ok") { return squiggleResult.value; @@ -23,11 +32,20 @@ export function testRun(x: string, bindings = {}): squiggleExpression { } } -export function testRunPartial(x: string, bindings: bindings = {}): bindings { - let squiggleResult = runPartial(x, bindings, { - sampleCount: 1000, - xyPointLength: 100, - }); +export function testRunPartial( + x: string, + bindings: bindings = {}, + parameters = {} +): bindings { + let squiggleResult = runPartial( + x, + bindings, + { + sampleCount: 1000, + xyPointLength: 100, + }, + parameters + ); if (squiggleResult.tag === "Ok") { return squiggleResult.value; } else { diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index fb67e47a..cd63c922 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -99,25 +99,71 @@ export type squiggleExpression = export function run( squiggleString: string, bindings?: externalBindings, - samplingInputs?: samplingParams + samplingInputs?: samplingParams, + parameters?: parameters ): result { let b = bindings ? bindings : {}; + let p = parameters ? parameters : {}; let si: samplingParams = samplingInputs ? samplingInputs : defaultSamplingInputs; let result: result = - evaluateUsingExternalBindings(squiggleString, b); + evaluateUsingExternalBindings(squiggleString, mergeParameters(b, p)); return resultMap(result, (x) => createTsExport(x, si)); } // Run Partial. A partial is a block of code that doesn't return a value export function runPartial( squiggleString: string, - bindings: externalBindings, - _samplingInputs?: samplingParams + bindings?: externalBindings, + _samplingInputs?: samplingParams, + parameters?: parameters ): result { - return evaluatePartialUsingExternalBindings(squiggleString, bindings); + let b = bindings ? bindings : {}; + let p = parameters ? parameters : {}; + + return evaluatePartialUsingExternalBindings( + squiggleString, + mergeParameters(b, p) + ); +} + +function mergeParameters( + bindings: externalBindings, + parameters: parameters +): externalBindings { + let transformedParemeters = Object.fromEntries( + Object.entries(parameters).map(([key, value]) => [ + "$" + key, + jsValueToBinding(value), + ]) + ); + return _.merge(bindings, transformedParemeters); +} + +type parameters = { [key: string]: jsValue }; + +type jsValue = + | string + | number + | jsValue[] + | { [key: string]: jsValue } + | boolean; + +function jsValueToBinding(value: jsValue): rescriptExport { + if (typeof value === "boolean") { + return { TAG: 1, _0: value as boolean }; + } else if (typeof value === "string") { + return { TAG: 6, _0: value as string }; + } else if (typeof value === "number") { + return { TAG: 4, _0: value as number }; + } else if (Array.isArray(value)) { + return { TAG: 0, _0: value.map(jsValueToBinding) }; + } else { + // Record + return { TAG: 5, _0: _.mapValues(value, jsValueToBinding) }; + } } function createTsExport( diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res index ab9fb711..86a7a593 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res @@ -19,6 +19,7 @@ let eval__: string => 'a = %raw(`function (expr) { return {value: Mathjs.evaluat */ let eval = (expr: string): result => { try { + Js.log(expr) let answer = eval__(expr) answer["value"]->JavaScript.Gate.jsToEv } catch { From 39be07cac0d7136d74078beba0097da79da74665 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 29 Apr 2022 19:02:43 +0000 Subject: [PATCH 2/8] Add parameters to components interface --- .../src/components/SquiggleChart.tsx | 17 +++++++++--- .../src/components/SquiggleEditor.tsx | 26 +++++++++++++++---- packages/squiggle-lang/src/js/index.ts | 18 +++++++++---- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index 8730beaa..235a4cee 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -3,16 +3,17 @@ import _ from "lodash"; import styled from "styled-components"; import { run, - runPartial, errorValueToString, squiggleExpression, bindings, samplingParams, + parameters, + defaultParameters, + defaultBindings, } from "@quri/squiggle-lang"; import { NumberShower } from "./NumberShower"; import { DistributionChart } from "./DistributionChart"; import { ErrorBox } from "./ErrorBox"; -import useSize from "@react-hook/size"; const variableBox = { Component: styled.div` @@ -152,6 +153,8 @@ export interface SquiggleChartProps { height?: number; /** Bindings of previous variables declared */ bindings?: bindings; + /** JS imported parameters */ + parameters?: parameters; } const ChartWrapper = styled.div` @@ -166,14 +169,20 @@ export const SquiggleChart: React.FC = ({ outputXYPoints = 1000, onChange = () => {}, height = 60, - bindings = {}, + bindings = defaultBindings, + parameters = defaultParameters, width = NaN, }: SquiggleChartProps) => { let samplingInputs: samplingParams = { sampleCount: sampleCount, xyPointLength: outputXYPoints, }; - let expressionResult = run(squiggleString, bindings, samplingInputs); + let expressionResult = run( + squiggleString, + bindings, + samplingInputs, + parameters + ); let internal: JSX.Element; if (expressionResult.tag === "Ok") { let expression = expressionResult.value; diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx index f85cf1e8..67f2e73b 100644 --- a/packages/components/src/components/SquiggleEditor.tsx +++ b/packages/components/src/components/SquiggleEditor.tsx @@ -3,8 +3,17 @@ import * as ReactDOM from "react-dom"; import { SquiggleChart } from "./SquiggleChart"; import { CodeEditor } from "./CodeEditor"; import styled from "styled-components"; -import type { squiggleExpression, bindings } from "@quri/squiggle-lang"; -import { runPartial, errorValueToString } from "@quri/squiggle-lang"; +import type { + squiggleExpression, + bindings, + parameters, +} from "@quri/squiggle-lang"; +import { + runPartial, + errorValueToString, + defaultParameters, + defaultBindings, +} from "@quri/squiggle-lang"; import { ErrorBox } from "./ErrorBox"; export interface SquiggleEditorProps { @@ -30,6 +39,8 @@ export interface SquiggleEditorProps { width: number; /** Previous variable declarations */ bindings: bindings; + /** JS Imported parameters */ + parameters: parameters; } const Input = styled.div` @@ -50,7 +61,8 @@ export let SquiggleEditor: React.FC = ({ diagramCount, onChange, environment, - bindings = {}, + bindings = defaultBindings, + parameters = defaultParameters, }: SquiggleEditorProps) => { let [expression, setExpression] = React.useState(initialSquiggleString); return ( @@ -77,6 +89,7 @@ export let SquiggleEditor: React.FC = ({ environment={environment} onChange={onChange} bindings={bindings} + parameters={parameters} /> ); @@ -134,13 +147,16 @@ export interface SquigglePartialProps { /** The width of the element */ width: number; /** Previously declared variables */ - bindings: bindings; + bindings?: bindings; + /** Parameters imported from js */ + parameters?: parameters; } export let SquigglePartial: React.FC = ({ initialSquiggleString = "", onChange, - bindings, + bindings = defaultBindings, + parameters = defaultParameters, }: SquigglePartialProps) => { let [expression, setExpression] = React.useState(initialSquiggleString); let squiggleResult = runPartial(expression, bindings); diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index cd63c922..1c0fb4e3 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -48,7 +48,12 @@ import { Constructors_pointwiseLogarithm, Constructors_pointwisePower, } from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen"; -export type { samplingParams, errorValue, externalBindings as bindings }; +export type { + samplingParams, + errorValue, + externalBindings as bindings, + parameters, +}; export let defaultSamplingInputs: samplingParams = { sampleCount: 10000, @@ -102,8 +107,8 @@ export function run( samplingInputs?: samplingParams, parameters?: parameters ): result { - let b = bindings ? bindings : {}; - let p = parameters ? parameters : {}; + let b = bindings ? bindings : defaultBindings; + let p = parameters ? parameters : defaultParameters; let si: samplingParams = samplingInputs ? samplingInputs : defaultSamplingInputs; @@ -120,8 +125,8 @@ export function runPartial( _samplingInputs?: samplingParams, parameters?: parameters ): result { - let b = bindings ? bindings : {}; - let p = parameters ? parameters : {}; + let b = bindings ? bindings : defaultBindings; + let p = parameters ? parameters : defaultParameters; return evaluatePartialUsingExternalBindings( squiggleString, @@ -144,6 +149,9 @@ function mergeParameters( type parameters = { [key: string]: jsValue }; +export let defaultParameters: parameters = {}; +export let defaultBindings: externalBindings = {}; + type jsValue = | string | number From 237cdf12f9f925324af99a3f215dc46e03990895 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 29 Apr 2022 19:13:30 +0000 Subject: [PATCH 3/8] Remove accidental log --- .../src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res index 86a7a593..ab9fb711 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Eval.res @@ -19,7 +19,6 @@ let eval__: string => 'a = %raw(`function (expr) { return {value: Mathjs.evaluat */ let eval = (expr: string): result => { try { - Js.log(expr) let answer = eval__(expr) answer["value"]->JavaScript.Gate.jsToEv } catch { From 74df093a42539f3255577a9cce54ccd8b7371860 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 29 Apr 2022 20:10:39 +0000 Subject: [PATCH 4/8] Cleanup TS code (and fix rescript build warning) --- .../squiggle-lang/__tests__/TS/JS_test.ts | 17 +- packages/squiggle-lang/src/js/distribution.ts | 247 ++++++++++ packages/squiggle-lang/src/js/index.ts | 439 +----------------- .../squiggle-lang/src/js/rescript_interop.ts | 155 +++++++ packages/squiggle-lang/src/js/types.ts | 30 ++ .../squiggle-lang/src/rescript/Utility/E.res | 2 +- 6 files changed, 454 insertions(+), 436 deletions(-) create mode 100644 packages/squiggle-lang/src/js/distribution.ts create mode 100644 packages/squiggle-lang/src/js/rescript_interop.ts create mode 100644 packages/squiggle-lang/src/js/types.ts diff --git a/packages/squiggle-lang/__tests__/TS/JS_test.ts b/packages/squiggle-lang/__tests__/TS/JS_test.ts index 62051261..004d715e 100644 --- a/packages/squiggle-lang/__tests__/TS/JS_test.ts +++ b/packages/squiggle-lang/__tests__/TS/JS_test.ts @@ -1,4 +1,4 @@ -import { Distribution, resultMap } from "../../src/js/index"; +import { Distribution, resultMap, defaultBindings } from "../../src/js/index"; import { testRun, testRunPartial } from "./TestHelpers"; function Ok(x: b) { @@ -70,20 +70,19 @@ describe("Partials", () => { describe("Parameters", () => { test("Can pass parameters into partials and cells", () => { - let bindings = testRunPartial(`y = $x + 2`, {}, { x: 1 }); // y = 3 - let bindings2 = testRunPartial(`z = $x + y * $a`, bindings, { a: 3 }); // z = 1 + 3 * 3 = 10 - expect(testRun(`z + $x + $a + y`, bindings2)).toEqual({ + let bindings = testRunPartial(`y = $x + 2`, defaultBindings, { x: 1 }); + let bindings2 = testRunPartial(`z = y + $a`, bindings, { a: 3 }); + expect(testRun(`z`, bindings2)).toEqual({ tag: "number", value: 17, }); }); test("Complicated deep parameters", () => { expect( - testRun( - `$x.y[0][0].w + $x.z + $u.v`, - {}, - { x: { y: [[{ w: 1 }]], z: 2 }, u: { v: 3 } } - ) + testRun(`$x.y[0][0].w + $x.z + $u.v`, defaultBindings, { + x: { y: [[{ w: 1 }]], z: 2 }, + u: { v: 3 }, + }) ).toEqual({ tag: "number", value: 6, diff --git a/packages/squiggle-lang/src/js/distribution.ts b/packages/squiggle-lang/src/js/distribution.ts new file mode 100644 index 00000000..603dfaa9 --- /dev/null +++ b/packages/squiggle-lang/src/js/distribution.ts @@ -0,0 +1,247 @@ +import * as _ from "lodash"; +import { + genericDist, + continuousShape, + discreteShape, + samplingParams, + distributionError, + toPointSet, + distributionErrorToString, +} from "../rescript/TypescriptInterface.gen"; +import { result, resultMap, Ok } from "./types"; +import { + Constructors_mean, + Constructors_sample, + Constructors_pdf, + Constructors_cdf, + Constructors_inv, + Constructors_normalize, + Constructors_isNormalized, + Constructors_toPointSet, + Constructors_toSampleSet, + Constructors_truncate, + Constructors_inspect, + Constructors_toString, + Constructors_toSparkline, + Constructors_algebraicAdd, + Constructors_algebraicMultiply, + Constructors_algebraicDivide, + Constructors_algebraicSubtract, + Constructors_algebraicLogarithm, + Constructors_algebraicPower, + Constructors_pointwiseAdd, + Constructors_pointwiseMultiply, + Constructors_pointwiseDivide, + Constructors_pointwiseSubtract, + Constructors_pointwiseLogarithm, + Constructors_pointwisePower, +} from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen"; + +export type point = { x: number; y: number }; + +function shapePoints(x: continuousShape | discreteShape): point[] { + let xs = x.xyShape.xs; + let ys = x.xyShape.ys; + return _.zipWith(xs, ys, (x, y) => ({ x, y })); +} +export type shape = { + continuous: point[]; + discrete: point[]; +}; + +export class Distribution { + t: genericDist; + env: samplingParams; + + constructor(t: genericDist, env: samplingParams) { + this.t = t; + this.env = env; + return this; + } + + mapResultDist( + r: result + ): result { + return resultMap(r, (v: genericDist) => new Distribution(v, this.env)); + } + + mean(): result { + return Constructors_mean({ env: this.env }, this.t); + } + + sample(): result { + return Constructors_sample({ env: this.env }, this.t); + } + + pdf(n: number): result { + return Constructors_pdf({ env: this.env }, this.t, n); + } + + cdf(n: number): result { + return Constructors_cdf({ env: this.env }, this.t, n); + } + + inv(n: number): result { + return Constructors_inv({ env: this.env }, this.t, n); + } + + isNormalized(): result { + return Constructors_isNormalized({ env: this.env }, this.t); + } + + normalize(): result { + return this.mapResultDist( + Constructors_normalize({ env: this.env }, this.t) + ); + } + + type() { + return this.t.tag; + } + + pointSet(): result { + 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") { + return Ok({ + continuous: shapePoints(distribution.value), + discrete: [], + }); + } else if (distribution.tag === "Discrete") { + return Ok({ + discrete: shapePoints(distribution.value), + continuous: [], + }); + } else { + return Ok({ + discrete: shapePoints(distribution.value.discrete), + continuous: shapePoints(distribution.value.continuous), + }); + } + } else { + return pointSet; + } + } + + toPointSet(): result { + return this.mapResultDist( + Constructors_toPointSet({ env: this.env }, this.t) + ); + } + + toSampleSet(n: number): result { + return this.mapResultDist( + Constructors_toSampleSet({ env: this.env }, this.t, n) + ); + } + + truncate( + left: number, + right: number + ): result { + return this.mapResultDist( + Constructors_truncate({ env: this.env }, this.t, left, right) + ); + } + + inspect(): result { + return this.mapResultDist(Constructors_inspect({ env: this.env }, this.t)); + } + + toString(): string { + let result = Constructors_toString({ env: this.env }, this.t); + if (result.tag === "Ok") { + return result.value; + } else { + return distributionErrorToString(result.value); + } + } + + toSparkline(n: number): result { + return Constructors_toSparkline({ env: this.env }, this.t, n); + } + + algebraicAdd(d2: Distribution): result { + return this.mapResultDist( + Constructors_algebraicAdd({ env: this.env }, this.t, d2.t) + ); + } + + algebraicMultiply(d2: Distribution): result { + return this.mapResultDist( + Constructors_algebraicMultiply({ env: this.env }, this.t, d2.t) + ); + } + + algebraicDivide(d2: Distribution): result { + return this.mapResultDist( + Constructors_algebraicDivide({ env: this.env }, this.t, d2.t) + ); + } + + algebraicSubtract(d2: Distribution): result { + return this.mapResultDist( + Constructors_algebraicSubtract({ env: this.env }, this.t, d2.t) + ); + } + + algebraicLogarithm( + d2: Distribution + ): result { + return this.mapResultDist( + Constructors_algebraicLogarithm({ env: this.env }, this.t, d2.t) + ); + } + + algebraicPower(d2: Distribution): result { + return this.mapResultDist( + Constructors_algebraicPower({ env: this.env }, this.t, d2.t) + ); + } + + pointwiseAdd(d2: Distribution): result { + return this.mapResultDist( + Constructors_pointwiseAdd({ env: this.env }, this.t, d2.t) + ); + } + + pointwiseMultiply(d2: Distribution): result { + return this.mapResultDist( + Constructors_pointwiseMultiply({ env: this.env }, this.t, d2.t) + ); + } + + pointwiseDivide(d2: Distribution): result { + return this.mapResultDist( + Constructors_pointwiseDivide({ env: this.env }, this.t, d2.t) + ); + } + + pointwiseSubtract(d2: Distribution): result { + return this.mapResultDist( + Constructors_pointwiseSubtract({ env: this.env }, this.t, d2.t) + ); + } + + pointwiseLogarithm( + d2: Distribution + ): result { + return this.mapResultDist( + Constructors_pointwiseLogarithm({ env: this.env }, this.t, d2.t) + ); + } + + pointwisePower(d2: Distribution): result { + return this.mapResultDist( + Constructors_pointwisePower({ env: this.env }, this.t, d2.t) + ); + } +} diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index 1c0fb4e3..04d6050a 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -1,106 +1,40 @@ import * as _ from "lodash"; import { - genericDist, samplingParams, evaluateUsingExternalBindings, evaluatePartialUsingExternalBindings, externalBindings, expressionValue, errorValue, - distributionError, - toPointSet, - continuousShape, - discreteShape, - distributionErrorToString, - mixedShape, - sampleSetDist, - symbolicDist, } from "../rescript/TypescriptInterface.gen"; export { makeSampleSetDist, errorValueToString, distributionErrorToString, } from "../rescript/TypescriptInterface.gen"; -import { - Constructors_mean, - Constructors_sample, - Constructors_pdf, - Constructors_cdf, - Constructors_inv, - Constructors_normalize, - Constructors_isNormalized, - Constructors_toPointSet, - Constructors_toSampleSet, - Constructors_truncate, - Constructors_inspect, - Constructors_toString, - Constructors_toSparkline, - Constructors_algebraicAdd, - Constructors_algebraicMultiply, - Constructors_algebraicDivide, - Constructors_algebraicSubtract, - Constructors_algebraicLogarithm, - Constructors_algebraicPower, - Constructors_pointwiseAdd, - Constructors_pointwiseMultiply, - Constructors_pointwiseDivide, - Constructors_pointwiseSubtract, - Constructors_pointwiseLogarithm, - Constructors_pointwisePower, -} from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen"; export type { samplingParams, errorValue, externalBindings as bindings, parameters, }; +import { + jsValueToBinding, + jsValue, + rescriptExport, + squiggleExpression, + convertRawToTypescript, +} from "./rescript_interop"; +import { result, resultMap, tag, tagged } from "./types"; +import { Distribution } from "./distribution"; + +export { Distribution, squiggleExpression, result }; export let defaultSamplingInputs: samplingParams = { sampleCount: 10000, xyPointLength: 10000, }; -export type result = - | { - tag: "Ok"; - value: a; - } - | { - tag: "Error"; - value: b; - }; - -export function resultMap( - r: result, - mapFn: (x: a) => b -): result { - if (r.tag === "Ok") { - return { tag: "Ok", value: mapFn(r.value) }; - } else { - return r; - } -} - -function Ok(x: a): result { - return { tag: "Ok", value: x }; -} - -type tagged = { tag: a; value: b }; - -function tag(x: a, y: b): tagged { - return { tag: x, value: y }; -} - -export type squiggleExpression = - | tagged<"symbol", string> - | tagged<"string", string> - | tagged<"call", string> - | tagged<"array", squiggleExpression[]> - | tagged<"boolean", boolean> - | tagged<"distribution", Distribution> - | tagged<"number", number> - | tagged<"record", { [key: string]: squiggleExpression }>; - export function run( squiggleString: string, bindings?: externalBindings, @@ -138,13 +72,13 @@ function mergeParameters( bindings: externalBindings, parameters: parameters ): externalBindings { - let transformedParemeters = Object.fromEntries( + let transformedParameters = Object.fromEntries( Object.entries(parameters).map(([key, value]) => [ "$" + key, jsValueToBinding(value), ]) ); - return _.merge(bindings, transformedParemeters); + return _.merge(bindings, transformedParameters); } type parameters = { [key: string]: jsValue }; @@ -152,28 +86,6 @@ type parameters = { [key: string]: jsValue }; export let defaultParameters: parameters = {}; export let defaultBindings: externalBindings = {}; -type jsValue = - | string - | number - | jsValue[] - | { [key: string]: jsValue } - | boolean; - -function jsValueToBinding(value: jsValue): rescriptExport { - if (typeof value === "boolean") { - return { TAG: 1, _0: value as boolean }; - } else if (typeof value === "string") { - return { TAG: 6, _0: value as string }; - } else if (typeof value === "number") { - return { TAG: 4, _0: value as number }; - } else if (Array.isArray(value)) { - return { TAG: 0, _0: value.map(jsValueToBinding) }; - } else { - // Record - return { TAG: 5, _0: _.mapValues(value, jsValueToBinding) }; - } -} - function createTsExport( x: expressionValue, sampEnv: samplingParams @@ -235,328 +147,3 @@ function createTsExport( } } -// Helper functions to convert the rescript representations that genType doesn't -// cover -function convertRawToTypescript( - result: rescriptExport, - sampEnv: samplingParams -): squiggleExpression { - switch (result.TAG) { - case 0: // EvArray - return tag( - "array", - result._0.map((x) => convertRawToTypescript(x, sampEnv)) - ); - case 1: // EvBool - return tag("boolean", result._0); - case 2: // EvCall - return tag("call", result._0); - case 3: // EvDistribution - return tag( - "distribution", - new Distribution( - convertRawDistributionToGenericDist(result._0), - sampEnv - ) - ); - case 4: // EvNumber - return tag("number", result._0); - case 5: // EvRecord - return tag( - "record", - _.mapValues(result._0, (x) => convertRawToTypescript(x, sampEnv)) - ); - case 6: // EvString - return tag("string", result._0); - case 7: // EvSymbol - return tag("symbol", result._0); - } -} - -function convertRawDistributionToGenericDist( - result: rescriptDist -): genericDist { - switch (result.TAG) { - case 0: // Point Set Dist - switch (result._0.TAG) { - case 0: // Mixed - return tag("PointSet", tag("Mixed", result._0._0)); - case 1: // Discrete - return tag("PointSet", tag("Discrete", result._0._0)); - case 2: // Continuous - return tag("PointSet", tag("Continuous", result._0._0)); - } - case 1: // Sample Set Dist - return tag("SampleSet", result._0); - case 2: // Symbolic Dist - return tag("Symbolic", result._0); - } -} - -// Raw rescript types. -type rescriptExport = - | { - TAG: 0; // EvArray - _0: rescriptExport[]; - } - | { - TAG: 1; // EvBool - _0: boolean; - } - | { - TAG: 2; // EvCall - _0: string; - } - | { - TAG: 3; // EvDistribution - _0: rescriptDist; - } - | { - TAG: 4; // EvNumber - _0: number; - } - | { - TAG: 5; // EvRecord - _0: { [key: string]: rescriptExport }; - } - | { - TAG: 6; // EvString - _0: string; - } - | { - TAG: 7; // EvSymbol - _0: string; - }; - -type rescriptDist = - | { TAG: 0; _0: rescriptPointSetDist } - | { TAG: 1; _0: sampleSetDist } - | { TAG: 2; _0: symbolicDist }; - -type rescriptPointSetDist = - | { - TAG: 0; // Mixed - _0: mixedShape; - } - | { - TAG: 1; // Discrete - _0: discreteShape; - } - | { - TAG: 2; // ContinuousShape - _0: continuousShape; - }; - -export function resultExn(r: result): a | c { - return r.value; -} - -export type point = { x: number; y: number }; - -export type shape = { - continuous: point[]; - discrete: 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 })); -} - -export class Distribution { - t: genericDist; - env: samplingParams; - - constructor(t: genericDist, env: samplingParams) { - this.t = t; - this.env = env; - return this; - } - - mapResultDist( - r: result - ): result { - return resultMap(r, (v: genericDist) => new Distribution(v, this.env)); - } - - mean(): result { - return Constructors_mean({ env: this.env }, this.t); - } - - sample(): result { - return Constructors_sample({ env: this.env }, this.t); - } - - pdf(n: number): result { - return Constructors_pdf({ env: this.env }, this.t, n); - } - - cdf(n: number): result { - return Constructors_cdf({ env: this.env }, this.t, n); - } - - inv(n: number): result { - return Constructors_inv({ env: this.env }, this.t, n); - } - - isNormalized(): result { - return Constructors_isNormalized({ env: this.env }, this.t); - } - - normalize(): result { - return this.mapResultDist( - Constructors_normalize({ env: this.env }, this.t) - ); - } - - type() { - return this.t.tag; - } - - pointSet(): result { - 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") { - return Ok({ - continuous: shapePoints(distribution.value), - discrete: [], - }); - } else if (distribution.tag === "Discrete") { - return Ok({ - discrete: shapePoints(distribution.value), - continuous: [], - }); - } else { - return Ok({ - discrete: shapePoints(distribution.value.discrete), - continuous: shapePoints(distribution.value.continuous), - }); - } - } else { - return pointSet; - } - } - - toPointSet(): result { - return this.mapResultDist( - Constructors_toPointSet({ env: this.env }, this.t) - ); - } - - toSampleSet(n: number): result { - return this.mapResultDist( - Constructors_toSampleSet({ env: this.env }, this.t, n) - ); - } - - truncate( - left: number, - right: number - ): result { - return this.mapResultDist( - Constructors_truncate({ env: this.env }, this.t, left, right) - ); - } - - inspect(): result { - return this.mapResultDist(Constructors_inspect({ env: this.env }, this.t)); - } - - toString(): string { - let result = Constructors_toString({ env: this.env }, this.t); - if (result.tag === "Ok") { - return result.value; - } else { - return distributionErrorToString(result.value); - } - } - - toSparkline(n: number): result { - return Constructors_toSparkline({ env: this.env }, this.t, n); - } - - algebraicAdd(d2: Distribution): result { - return this.mapResultDist( - Constructors_algebraicAdd({ env: this.env }, this.t, d2.t) - ); - } - - algebraicMultiply(d2: Distribution): result { - return this.mapResultDist( - Constructors_algebraicMultiply({ env: this.env }, this.t, d2.t) - ); - } - - algebraicDivide(d2: Distribution): result { - return this.mapResultDist( - Constructors_algebraicDivide({ env: this.env }, this.t, d2.t) - ); - } - - algebraicSubtract(d2: Distribution): result { - return this.mapResultDist( - Constructors_algebraicSubtract({ env: this.env }, this.t, d2.t) - ); - } - - algebraicLogarithm( - d2: Distribution - ): result { - return this.mapResultDist( - Constructors_algebraicLogarithm({ env: this.env }, this.t, d2.t) - ); - } - - algebraicPower(d2: Distribution): result { - return this.mapResultDist( - Constructors_algebraicPower({ env: this.env }, this.t, d2.t) - ); - } - - pointwiseAdd(d2: Distribution): result { - return this.mapResultDist( - Constructors_pointwiseAdd({ env: this.env }, this.t, d2.t) - ); - } - - pointwiseMultiply(d2: Distribution): result { - return this.mapResultDist( - Constructors_pointwiseMultiply({ env: this.env }, this.t, d2.t) - ); - } - - pointwiseDivide(d2: Distribution): result { - return this.mapResultDist( - Constructors_pointwiseDivide({ env: this.env }, this.t, d2.t) - ); - } - - pointwiseSubtract(d2: Distribution): result { - return this.mapResultDist( - Constructors_pointwiseSubtract({ env: this.env }, this.t, d2.t) - ); - } - - pointwiseLogarithm( - d2: Distribution - ): result { - return this.mapResultDist( - Constructors_pointwiseLogarithm({ env: this.env }, this.t, d2.t) - ); - } - - pointwisePower(d2: Distribution): result { - return this.mapResultDist( - Constructors_pointwisePower({ env: this.env }, this.t, d2.t) - ); - } -} diff --git a/packages/squiggle-lang/src/js/rescript_interop.ts b/packages/squiggle-lang/src/js/rescript_interop.ts new file mode 100644 index 00000000..b017699f --- /dev/null +++ b/packages/squiggle-lang/src/js/rescript_interop.ts @@ -0,0 +1,155 @@ +import * as _ from "lodash"; +import { + mixedShape, + sampleSetDist, + genericDist, + samplingParams, + symbolicDist, + discreteShape, + continuousShape, +} from "../rescript/TypescriptInterface.gen"; +import { Distribution } from "./distribution"; +import { tagged, tag } from "./types"; +// This file is here to compensate for genType not fully recursively converting types + +// Raw rescript types. +export type rescriptExport = + | { + TAG: 0; // EvArray + _0: rescriptExport[]; + } + | { + TAG: 1; // EvBool + _0: boolean; + } + | { + TAG: 2; // EvCall + _0: string; + } + | { + TAG: 3; // EvDistribution + _0: rescriptDist; + } + | { + TAG: 4; // EvNumber + _0: number; + } + | { + TAG: 5; // EvRecord + _0: { [key: string]: rescriptExport }; + } + | { + TAG: 6; // EvString + _0: string; + } + | { + TAG: 7; // EvSymbol + _0: string; + }; + +type rescriptDist = + | { TAG: 0; _0: rescriptPointSetDist } + | { TAG: 1; _0: sampleSetDist } + | { TAG: 2; _0: symbolicDist }; + +type rescriptPointSetDist = + | { + TAG: 0; // Mixed + _0: mixedShape; + } + | { + TAG: 1; // Discrete + _0: discreteShape; + } + | { + TAG: 2; // ContinuousShape + _0: continuousShape; + }; + +export type squiggleExpression = + | tagged<"symbol", string> + | tagged<"string", string> + | tagged<"call", string> + | tagged<"array", squiggleExpression[]> + | tagged<"boolean", boolean> + | tagged<"distribution", Distribution> + | tagged<"number", number> + | tagged<"record", { [key: string]: squiggleExpression }>; + +export function convertRawToTypescript( + result: rescriptExport, + sampEnv: samplingParams +): squiggleExpression { + switch (result.TAG) { + case 0: // EvArray + return tag( + "array", + result._0.map((x) => convertRawToTypescript(x, sampEnv)) + ); + case 1: // EvBool + return tag("boolean", result._0); + case 2: // EvCall + return tag("call", result._0); + case 3: // EvDistribution + return tag( + "distribution", + new Distribution( + convertRawDistributionToGenericDist(result._0), + sampEnv + ) + ); + case 4: // EvNumber + return tag("number", result._0); + case 5: // EvRecord + return tag( + "record", + _.mapValues(result._0, (x) => convertRawToTypescript(x, sampEnv)) + ); + case 6: // EvString + return tag("string", result._0); + case 7: // EvSymbol + return tag("symbol", result._0); + } +} + +function convertRawDistributionToGenericDist( + result: rescriptDist +): genericDist { + switch (result.TAG) { + case 0: // Point Set Dist + switch (result._0.TAG) { + case 0: // Mixed + return tag("PointSet", tag("Mixed", result._0._0)); + case 1: // Discrete + return tag("PointSet", tag("Discrete", result._0._0)); + case 2: // Continuous + return tag("PointSet", tag("Continuous", result._0._0)); + } + case 1: // Sample Set Dist + return tag("SampleSet", result._0); + case 2: // Symbolic Dist + return tag("Symbolic", result._0); + } +} + +export type jsValue = + | string + | number + | jsValue[] + | { [key: string]: jsValue } + | boolean; + +export function jsValueToBinding(value: jsValue): rescriptExport { + if (typeof value === "boolean") { + return { TAG: 1, _0: value as boolean }; + } else if (typeof value === "string") { + return { TAG: 6, _0: value as string }; + } else if (typeof value === "number") { + return { TAG: 4, _0: value as number }; + } else if (Array.isArray(value)) { + return { TAG: 0, _0: value.map(jsValueToBinding) }; + } else { + // Record + return { TAG: 5, _0: _.mapValues(value, jsValueToBinding) }; + } +} diff --git a/packages/squiggle-lang/src/js/types.ts b/packages/squiggle-lang/src/js/types.ts new file mode 100644 index 00000000..8851b520 --- /dev/null +++ b/packages/squiggle-lang/src/js/types.ts @@ -0,0 +1,30 @@ +export type result = + | { + tag: "Ok"; + value: a; + } + | { + tag: "Error"; + value: b; + }; + +export function resultMap( + r: result, + mapFn: (x: a) => b +): result { + if (r.tag === "Ok") { + return { tag: "Ok", value: mapFn(r.value) }; + } else { + return r; + } +} + +export function Ok(x: a): result { + return { tag: "Ok", value: x }; +} + +export type tagged = { tag: a; value: b }; + +export function tag(x: a, y: b): tagged { + return { tag: x, value: y }; +} diff --git a/packages/squiggle-lang/src/rescript/Utility/E.res b/packages/squiggle-lang/src/rescript/Utility/E.res index e0bcaf5c..f5b38be7 100644 --- a/packages/squiggle-lang/src/rescript/Utility/E.res +++ b/packages/squiggle-lang/src/rescript/Utility/E.res @@ -350,7 +350,7 @@ module JsDate = { /* List */ module L = { module Util = { - let eq = (a, b) => a == b + let eq = \"==" } let fmap = List.map let get = Belt.List.get From b710289096c3ca54e8556f8e18b7bfd82479b6bb Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 29 Apr 2022 20:29:42 +0000 Subject: [PATCH 5/8] Rename parameters to imports --- .../src/components/SquiggleChart.tsx | 15 +++------ .../src/components/SquiggleEditor.tsx | 32 +++++++++++++------ .../squiggle-lang/__tests__/TS/JS_test.ts | 4 +-- .../squiggle-lang/__tests__/TS/TestHelpers.ts | 16 ++++++---- packages/squiggle-lang/src/js/index.ts | 31 +++++++++--------- 5 files changed, 53 insertions(+), 45 deletions(-) diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index 235a4cee..be65d425 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -7,8 +7,8 @@ import { squiggleExpression, bindings, samplingParams, - parameters, - defaultParameters, + jsImports, + defaultImports, defaultBindings, } from "@quri/squiggle-lang"; import { NumberShower } from "./NumberShower"; @@ -154,7 +154,7 @@ export interface SquiggleChartProps { /** Bindings of previous variables declared */ bindings?: bindings; /** JS imported parameters */ - parameters?: parameters; + imports?: jsImports; } const ChartWrapper = styled.div` @@ -170,19 +170,14 @@ export const SquiggleChart: React.FC = ({ onChange = () => {}, height = 60, bindings = defaultBindings, - parameters = defaultParameters, + imports = defaultImports, width = NaN, }: SquiggleChartProps) => { let samplingInputs: samplingParams = { sampleCount: sampleCount, xyPointLength: outputXYPoints, }; - let expressionResult = run( - squiggleString, - bindings, - samplingInputs, - parameters - ); + let expressionResult = run(squiggleString, bindings, samplingInputs, imports); let internal: JSX.Element; if (expressionResult.tag === "Ok") { let expression = expressionResult.value; diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx index 67f2e73b..697e9426 100644 --- a/packages/components/src/components/SquiggleEditor.tsx +++ b/packages/components/src/components/SquiggleEditor.tsx @@ -5,13 +5,14 @@ import { CodeEditor } from "./CodeEditor"; import styled from "styled-components"; import type { squiggleExpression, + samplingParams, bindings, - parameters, + jsImports, } from "@quri/squiggle-lang"; import { runPartial, errorValueToString, - defaultParameters, + defaultImports, defaultBindings, } from "@quri/squiggle-lang"; import { ErrorBox } from "./ErrorBox"; @@ -39,8 +40,8 @@ export interface SquiggleEditorProps { width: number; /** Previous variable declarations */ bindings: bindings; - /** JS Imported parameters */ - parameters: parameters; + /** JS Imports */ + imports: jsImports; } const Input = styled.div` @@ -62,7 +63,7 @@ export let SquiggleEditor: React.FC = ({ onChange, environment, bindings = defaultBindings, - parameters = defaultParameters, + imports = defaultImports, }: SquiggleEditorProps) => { let [expression, setExpression] = React.useState(initialSquiggleString); return ( @@ -89,7 +90,7 @@ export let SquiggleEditor: React.FC = ({ environment={environment} onChange={onChange} bindings={bindings} - parameters={parameters} + imports={imports} /> ); @@ -148,18 +149,29 @@ export interface SquigglePartialProps { width: number; /** Previously declared variables */ bindings?: bindings; - /** Parameters imported from js */ - parameters?: parameters; + /** Variables imported from js */ + imports?: jsImports; } export let SquigglePartial: React.FC = ({ initialSquiggleString = "", onChange, bindings = defaultBindings, - parameters = defaultParameters, + sampleCount = 1000, + outputXYPoints = 1000, + imports = defaultImports, }: SquigglePartialProps) => { + let samplingInputs: samplingParams = { + sampleCount: sampleCount, + xyPointLength: outputXYPoints, + }; let [expression, setExpression] = React.useState(initialSquiggleString); - let squiggleResult = runPartial(expression, bindings); + let squiggleResult = runPartial( + expression, + bindings, + samplingInputs, + imports + ); if (squiggleResult.tag == "Ok") { if (onChange) onChange(squiggleResult.value); } diff --git a/packages/squiggle-lang/__tests__/TS/JS_test.ts b/packages/squiggle-lang/__tests__/TS/JS_test.ts index 004d715e..76871fc8 100644 --- a/packages/squiggle-lang/__tests__/TS/JS_test.ts +++ b/packages/squiggle-lang/__tests__/TS/JS_test.ts @@ -68,13 +68,13 @@ describe("Partials", () => { }); }); -describe("Parameters", () => { +describe("JS Imports", () => { test("Can pass parameters into partials and cells", () => { let bindings = testRunPartial(`y = $x + 2`, defaultBindings, { x: 1 }); let bindings2 = testRunPartial(`z = y + $a`, bindings, { a: 3 }); expect(testRun(`z`, bindings2)).toEqual({ tag: "number", - value: 17, + value: 6, }); }); test("Complicated deep parameters", () => { diff --git a/packages/squiggle-lang/__tests__/TS/TestHelpers.ts b/packages/squiggle-lang/__tests__/TS/TestHelpers.ts index 3bbf42d8..d9d8444f 100644 --- a/packages/squiggle-lang/__tests__/TS/TestHelpers.ts +++ b/packages/squiggle-lang/__tests__/TS/TestHelpers.ts @@ -4,12 +4,15 @@ import { bindings, squiggleExpression, errorValueToString, + defaultImports, + defaultBindings, + jsImports, } from "../../src/js/index"; export function testRun( x: string, - bindings = {}, - parameters = {} + bindings: bindings = defaultBindings, + imports: jsImports = defaultImports ): squiggleExpression { let squiggleResult = run( x, @@ -18,9 +21,8 @@ export function testRun( sampleCount: 1000, xyPointLength: 100, }, - parameters + imports ); - // return squiggleResult.value if (squiggleResult.tag === "Ok") { return squiggleResult.value; } else { @@ -34,8 +36,8 @@ export function testRun( export function testRunPartial( x: string, - bindings: bindings = {}, - parameters = {} + bindings: bindings = defaultBindings, + imports: jsImports = defaultImports ): bindings { let squiggleResult = runPartial( x, @@ -44,7 +46,7 @@ export function testRunPartial( sampleCount: 1000, xyPointLength: 100, }, - parameters + imports ); if (squiggleResult.tag === "Ok") { return squiggleResult.value; diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index 04d6050a..ce4d9428 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -16,7 +16,7 @@ export type { samplingParams, errorValue, externalBindings as bindings, - parameters, + jsImports, }; import { jsValueToBinding, @@ -28,7 +28,7 @@ import { import { result, resultMap, tag, tagged } from "./types"; import { Distribution } from "./distribution"; -export { Distribution, squiggleExpression, result }; +export { Distribution, squiggleExpression, result, resultMap }; export let defaultSamplingInputs: samplingParams = { sampleCount: 10000, @@ -39,16 +39,16 @@ export function run( squiggleString: string, bindings?: externalBindings, samplingInputs?: samplingParams, - parameters?: parameters + imports?: jsImports ): result { let b = bindings ? bindings : defaultBindings; - let p = parameters ? parameters : defaultParameters; + let i = imports ? imports : defaultImports; let si: samplingParams = samplingInputs ? samplingInputs : defaultSamplingInputs; let result: result = - evaluateUsingExternalBindings(squiggleString, mergeParameters(b, p)); + evaluateUsingExternalBindings(squiggleString, mergeImports(b, i)); return resultMap(result, (x) => createTsExport(x, si)); } @@ -57,33 +57,33 @@ export function runPartial( squiggleString: string, bindings?: externalBindings, _samplingInputs?: samplingParams, - parameters?: parameters + imports?: jsImports ): result { let b = bindings ? bindings : defaultBindings; - let p = parameters ? parameters : defaultParameters; + let i = imports ? imports : defaultImports; return evaluatePartialUsingExternalBindings( squiggleString, - mergeParameters(b, p) + mergeImports(b, i) ); } -function mergeParameters( +function mergeImports( bindings: externalBindings, - parameters: parameters + imports: jsImports ): externalBindings { - let transformedParameters = Object.fromEntries( - Object.entries(parameters).map(([key, value]) => [ + let transformedImports = Object.fromEntries( + Object.entries(imports).map(([key, value]) => [ "$" + key, jsValueToBinding(value), ]) ); - return _.merge(bindings, transformedParameters); + return _.merge(bindings, transformedImports); } -type parameters = { [key: string]: jsValue }; +type jsImports = { [key: string]: jsValue }; -export let defaultParameters: parameters = {}; +export let defaultImports: jsImports = {}; export let defaultBindings: externalBindings = {}; function createTsExport( @@ -146,4 +146,3 @@ function createTsExport( return tag("symbol", x.value); } } - From 2131e4eac165ce0fb6bf6bf1a87abe29b96b9491 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 29 Apr 2022 20:58:06 +0000 Subject: [PATCH 6/8] Rename imports to jsImports in components --- packages/components/src/components/SquiggleChart.tsx | 6 +++--- .../components/src/components/SquiggleEditor.tsx | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index be65d425..c0c5121d 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -154,7 +154,7 @@ export interface SquiggleChartProps { /** Bindings of previous variables declared */ bindings?: bindings; /** JS imported parameters */ - imports?: jsImports; + jsImports?: jsImports; } const ChartWrapper = styled.div` @@ -170,14 +170,14 @@ export const SquiggleChart: React.FC = ({ onChange = () => {}, height = 60, bindings = defaultBindings, - imports = defaultImports, + jsImports = defaultImports, width = NaN, }: SquiggleChartProps) => { let samplingInputs: samplingParams = { sampleCount: sampleCount, xyPointLength: outputXYPoints, }; - let expressionResult = run(squiggleString, bindings, samplingInputs, imports); + let expressionResult = run(squiggleString, bindings, samplingInputs, jsImports); let internal: JSX.Element; if (expressionResult.tag === "Ok") { let expression = expressionResult.value; diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx index 697e9426..2c01f72f 100644 --- a/packages/components/src/components/SquiggleEditor.tsx +++ b/packages/components/src/components/SquiggleEditor.tsx @@ -41,7 +41,7 @@ export interface SquiggleEditorProps { /** Previous variable declarations */ bindings: bindings; /** JS Imports */ - imports: jsImports; + jsImports: jsImports; } const Input = styled.div` @@ -63,7 +63,7 @@ export let SquiggleEditor: React.FC = ({ onChange, environment, bindings = defaultBindings, - imports = defaultImports, + jsImports = defaultImports, }: SquiggleEditorProps) => { let [expression, setExpression] = React.useState(initialSquiggleString); return ( @@ -90,7 +90,7 @@ export let SquiggleEditor: React.FC = ({ environment={environment} onChange={onChange} bindings={bindings} - imports={imports} + jsImports={jsImports} /> ); @@ -150,7 +150,7 @@ export interface SquigglePartialProps { /** Previously declared variables */ bindings?: bindings; /** Variables imported from js */ - imports?: jsImports; + jsImports?: jsImports; } export let SquigglePartial: React.FC = ({ @@ -159,7 +159,7 @@ export let SquigglePartial: React.FC = ({ bindings = defaultBindings, sampleCount = 1000, outputXYPoints = 1000, - imports = defaultImports, + jsImports = defaultImports, }: SquigglePartialProps) => { let samplingInputs: samplingParams = { sampleCount: sampleCount, @@ -170,7 +170,7 @@ export let SquigglePartial: React.FC = ({ expression, bindings, samplingInputs, - imports + jsImports ); if (squiggleResult.tag == "Ok") { if (onChange) onChange(squiggleResult.value); From d09dbeb812f6609e9c4605bdabbd120ea4c70581 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 29 Apr 2022 20:59:37 +0000 Subject: [PATCH 7/8] Format components code --- packages/components/src/components/SquiggleChart.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx index c0c5121d..31cd9787 100644 --- a/packages/components/src/components/SquiggleChart.tsx +++ b/packages/components/src/components/SquiggleChart.tsx @@ -177,7 +177,12 @@ export const SquiggleChart: React.FC = ({ sampleCount: sampleCount, xyPointLength: outputXYPoints, }; - let expressionResult = run(squiggleString, bindings, samplingInputs, jsImports); + let expressionResult = run( + squiggleString, + bindings, + samplingInputs, + jsImports + ); let internal: JSX.Element; if (expressionResult.tag === "Ok") { let expression = expressionResult.value; From 3117dd81d60955d72eed7aa75ad5a4aa6116d6d2 Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Fri, 29 Apr 2022 21:16:22 +0000 Subject: [PATCH 8/8] Remove si prefix from chart axis --- packages/components/src/vega-specs/spec-distributions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/vega-specs/spec-distributions.json b/packages/components/src/vega-specs/spec-distributions.json index 129183a5..5b6ed261 100644 --- a/packages/components/src/vega-specs/spec-distributions.json +++ b/packages/components/src/vega-specs/spec-distributions.json @@ -88,7 +88,7 @@ "tickOpacity": 0.0, "domainColor": "#fff", "domainOpacity": 0.0, - "format": "~s", + "format": "~g", "tickCount": 10 } ],