JS parameters in squiggle lang
This commit is contained in:
parent
bb8ed5ce4f
commit
d4f929367d
|
@ -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",
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -6,11 +6,20 @@ import {
|
|||
errorValueToString,
|
||||
} from "../../src/js/index";
|
||||
|
||||
export function testRun(x: string, bindings = {}): squiggleExpression {
|
||||
let squiggleResult = run(x, bindings, {
|
||||
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, {
|
||||
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 {
|
||||
|
|
|
@ -99,25 +99,71 @@ export type squiggleExpression =
|
|||
export function run(
|
||||
squiggleString: string,
|
||||
bindings?: externalBindings,
|
||||
samplingInputs?: samplingParams
|
||||
samplingInputs?: samplingParams,
|
||||
parameters?: parameters
|
||||
): result<squiggleExpression, errorValue> {
|
||||
let b = bindings ? bindings : {};
|
||||
let p = parameters ? parameters : {};
|
||||
let si: samplingParams = samplingInputs
|
||||
? samplingInputs
|
||||
: defaultSamplingInputs;
|
||||
|
||||
let result: result<expressionValue, errorValue> =
|
||||
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<externalBindings, errorValue> {
|
||||
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(
|
||||
|
|
|
@ -19,6 +19,7 @@ let eval__: string => 'a = %raw(`function (expr) { return {value: Mathjs.evaluat
|
|||
*/
|
||||
let eval = (expr: string): result<expressionValue, errorValue> => {
|
||||
try {
|
||||
Js.log(expr)
|
||||
let answer = eval__(expr)
|
||||
answer["value"]->JavaScript.Gate.jsToEv
|
||||
} catch {
|
||||
|
|
Loading…
Reference in New Issue
Block a user