Add squiggle notebooks
This commit is contained in:
parent
fd6c5d3eb8
commit
f122b5fd7f
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@quri/squiggle-components",
|
"name": "@quri/squiggle-components",
|
||||||
"version": "0.1.5",
|
"version": "0.1.6",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@quri/squiggle-lang": "0.2.2",
|
"@quri/squiggle-lang": "0.2.2",
|
||||||
"@testing-library/jest-dom": "^5.16.2",
|
"@testing-library/jest-dom": "^5.16.2",
|
||||||
|
@ -72,7 +72,8 @@
|
||||||
"react-codejar": "^1.1.2",
|
"react-codejar": "^1.1.2",
|
||||||
"ts-loader": "^9.2.8",
|
"ts-loader": "^9.2.8",
|
||||||
"webpack": "^5.70.0",
|
"webpack": "^5.70.0",
|
||||||
"webpack-cli": "^4.9.2"
|
"webpack-cli": "^4.9.2",
|
||||||
|
"webpack-dev-server": "^4.7.4"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"@types/react": "17.0.39"
|
"@types/react": "17.0.39"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import type { Spec } from 'vega';
|
import type { Spec } from 'vega';
|
||||||
import { run } from '@squiggle/lang';
|
import { run } from '@quri/squiggle-lang';
|
||||||
import type { DistPlus, SamplingInputs } from '@squiggle/lang';
|
import type { DistPlus, SamplingInputs, exportEnv, exportDistribution } from '@quri/squiggle-lang';
|
||||||
import { createClassFromSpec } from 'react-vega';
|
import { createClassFromSpec } from 'react-vega';
|
||||||
import * as chartSpecification from './spec-distributions.json'
|
import * as chartSpecification from './spec-distributions.json'
|
||||||
import * as percentilesSpec from './spec-pertentiles.json'
|
import * as percentilesSpec from './spec-pertentiles.json'
|
||||||
|
@ -26,7 +26,11 @@ export interface SquiggleChartProps {
|
||||||
/** If the result is a function, where the function ends */
|
/** If the result is a function, where the function ends */
|
||||||
diagramStop? : number,
|
diagramStop? : number,
|
||||||
/** If the result is a function, how many points along the function it samples */
|
/** If the result is a function, how many points along the function it samples */
|
||||||
diagramCount? : number
|
diagramCount? : number,
|
||||||
|
/** variables declared before this expression */
|
||||||
|
environment? : exportEnv,
|
||||||
|
/** When the environment changes */
|
||||||
|
onEnvChange?(env: exportEnv): void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SquiggleChart : React.FC<SquiggleChartProps> = props => {
|
export const SquiggleChart : React.FC<SquiggleChartProps> = props => {
|
||||||
|
@ -38,11 +42,13 @@ export const SquiggleChart : React.FC<SquiggleChartProps> = props => {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let result = run(props.squiggleString, samplingInputs);
|
let result = run(props.squiggleString, samplingInputs, props.environment);
|
||||||
console.log(result)
|
|
||||||
if (result.tag === "Ok") {
|
if (result.tag === "Ok") {
|
||||||
let chartResults = result.value.map(chartResult => {
|
let environment = result.value.environment
|
||||||
console.log(chartResult)
|
let exports = result.value.exports
|
||||||
|
if(props.onEnvChange)
|
||||||
|
props.onEnvChange(environment)
|
||||||
|
let chartResults = exports.map((chartResult:exportDistribution )=> {
|
||||||
if(chartResult["NAME"] === "Float"){
|
if(chartResult["NAME"] === "Float"){
|
||||||
return <MakeNumberShower precision={3} number={chartResult["VAL"]} />;
|
return <MakeNumberShower precision={3} number={chartResult["VAL"]} />;
|
||||||
}
|
}
|
||||||
|
|
103
packages/components/src/SquiggleEditor.tsx
Normal file
103
packages/components/src/SquiggleEditor.tsx
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import * as ReactDOM from 'react-dom';
|
||||||
|
import { SquiggleChart } from './SquiggleChart'
|
||||||
|
import { ReactCodeJar } from "react-codejar";
|
||||||
|
import type { exportEnv } from '@quri/squiggle-lang'
|
||||||
|
|
||||||
|
|
||||||
|
export interface SquiggleEditorProps {
|
||||||
|
/** The input string for squiggle */
|
||||||
|
initialSquiggleString? : string,
|
||||||
|
|
||||||
|
/** If the output requires monte carlo sampling, the amount of samples */
|
||||||
|
sampleCount? : number,
|
||||||
|
/** The amount of points returned to draw the distribution */
|
||||||
|
outputXYPoints? : number,
|
||||||
|
kernelWidth? : number,
|
||||||
|
pointDistLength? : number,
|
||||||
|
/** If the result is a function, where the function starts */
|
||||||
|
diagramStart? : number,
|
||||||
|
/** If the result is a function, where the function ends */
|
||||||
|
diagramStop? : number,
|
||||||
|
/** If the result is a function, how many points along the function it samples */
|
||||||
|
diagramCount? : number,
|
||||||
|
/** The environment, other variables that were already declared */
|
||||||
|
environment?: exportEnv,
|
||||||
|
/** when the environment changes. Used again for notebook magic*/
|
||||||
|
onEnvChange?(env: exportEnv) : void
|
||||||
|
}
|
||||||
|
|
||||||
|
const highlight = (editor: HTMLInputElement) => {
|
||||||
|
let code = editor.textContent;
|
||||||
|
code = code.replace(/\((\w+?)(\b)/g, '(<font color="#8a2be2">$1</font>$2');
|
||||||
|
editor.innerHTML = code;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface SquiggleEditorState {
|
||||||
|
expression: string,
|
||||||
|
env: exportEnv
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SquiggleEditor extends React.Component<SquiggleEditorProps, SquiggleEditorState>{
|
||||||
|
constructor(props: SquiggleEditorProps) {
|
||||||
|
super(props)
|
||||||
|
let code = props.initialSquiggleString ? props.initialSquiggleString : ""
|
||||||
|
this.state = {expression: code, env: props.environment }
|
||||||
|
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
let {expression, env} = this.state
|
||||||
|
let props = this.props
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<ReactCodeJar
|
||||||
|
code={expression}
|
||||||
|
onUpdate={e => {
|
||||||
|
this.setState({expression: e})
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
borderRadius: "6px",
|
||||||
|
width: "530px",
|
||||||
|
border: "1px solid grey",
|
||||||
|
fontFamily: "'Source Code Pro', monospace",
|
||||||
|
fontSize: "14px",
|
||||||
|
fontWeight: "400",
|
||||||
|
letterSpacing: "normal",
|
||||||
|
lineHeight: "20px",
|
||||||
|
padding: "10px",
|
||||||
|
tabSize: "4"
|
||||||
|
}}
|
||||||
|
highlight={highlight}
|
||||||
|
lineNumbers={false}
|
||||||
|
/>
|
||||||
|
<SquiggleChart
|
||||||
|
squiggleString={expression}
|
||||||
|
sampleCount={props.sampleCount}
|
||||||
|
outputXYPoints={props.outputXYPoints}
|
||||||
|
kernelWidth={props.kernelWidth}
|
||||||
|
pointDistLength={props.pointDistLength}
|
||||||
|
diagramStart={props.diagramStart}
|
||||||
|
diagramStop={props.diagramStop}
|
||||||
|
diagramCount={props.diagramCount}
|
||||||
|
environment={env}
|
||||||
|
onEnvChange={props.onEnvChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderSquiggleEditor(props : SquiggleEditorProps) {
|
||||||
|
let parent = document.createElement("div")
|
||||||
|
ReactDOM.render(<SquiggleEditor {...props} onEnvChange={env => {
|
||||||
|
|
||||||
|
// I can set the value here because I need it for creating notebooks
|
||||||
|
// @ts-ignore
|
||||||
|
parent.value = env
|
||||||
|
|
||||||
|
parent.dispatchEvent(new CustomEvent("input"))
|
||||||
|
if(props.onEnvChange)
|
||||||
|
props.onEnvChange(env)
|
||||||
|
}} /> , parent)
|
||||||
|
return parent
|
||||||
|
}
|
|
@ -1 +1,2 @@
|
||||||
export { SquiggleChart } from './SquiggleChart';
|
export { SquiggleChart } from './SquiggleChart';
|
||||||
|
export { SquiggleEditor, renderSquiggleEditor } from './SquiggleEditor';
|
||||||
|
|
|
@ -2,6 +2,7 @@ const path = require('path');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
mode: 'production',
|
mode: 'production',
|
||||||
|
devtool: 'source-map',
|
||||||
entry: './src/index.ts',
|
entry: './src/index.ts',
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
|
@ -23,4 +24,11 @@ module.exports = {
|
||||||
type: 'umd',
|
type: 'umd',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
devServer: {
|
||||||
|
static: {
|
||||||
|
directory: path.join(__dirname, 'public'),
|
||||||
|
},
|
||||||
|
compress: true,
|
||||||
|
port: 9000,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
1
packages/squiggle-lang/.gitignore
vendored
1
packages/squiggle-lang/.gitignore
vendored
|
@ -14,5 +14,6 @@ yarn-error.log
|
||||||
.netlify
|
.netlify
|
||||||
.idea
|
.idea
|
||||||
*.gen.ts
|
*.gen.ts
|
||||||
|
*.gen.tsx
|
||||||
*.gen.js
|
*.gen.js
|
||||||
dist
|
dist
|
||||||
|
|
|
@ -1,19 +1,29 @@
|
||||||
import { run } from '../src/js/index';
|
import { run } from '../src/js/index';
|
||||||
|
|
||||||
|
let testRun = (x: string) => {
|
||||||
|
let result = run(x)
|
||||||
|
if(result.tag == 'Ok'){
|
||||||
|
return { tag: 'Ok', value: result.value.exports }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
describe("A simple result", () => {
|
describe("A simple result", () => {
|
||||||
test("mean(normal(5,2))", () => {
|
test("mean(normal(5,2))", () => {
|
||||||
expect(run("mean(normal(5,2))")).toEqual({ tag: 'Ok', value: [ { NAME: 'Float', VAL: 5 } ] })
|
expect(testRun("mean(normal(5,2))")).toEqual({ tag: 'Ok', value: [ { NAME: 'Float', VAL: 5 } ] })
|
||||||
})
|
})
|
||||||
test("10+10", () => {
|
test("10+10", () => {
|
||||||
let foo = run("10 + 10")
|
let foo = testRun("10 + 10")
|
||||||
expect(foo).toEqual({ tag: 'Ok', value: [ { NAME: 'Float', VAL: 20 } ] })
|
expect(foo).toEqual({ tag: 'Ok', value: [ { NAME: 'Float', VAL: 20 } ] })
|
||||||
})
|
})
|
||||||
test("log(1) = 0", () => {
|
test("log(1) = 0", () => {
|
||||||
let foo = run("log(1)")
|
let foo = testRun("log(1)")
|
||||||
expect(foo).toEqual({ tag: 'Ok', value: [ { NAME: 'Float', VAL: 0} ]})
|
expect(foo).toEqual({ tag: 'Ok', value: [ { NAME: 'Float', VAL: 0} ]})
|
||||||
})
|
})
|
||||||
test("mm(0,0,[0,0,0])", () => {
|
test("mm(0,0,[0,0,0])", () => {
|
||||||
let foo = run("mm(0,0,[0,0,0])")
|
let foo = testRun("mm(0,0,[0,0,0])")
|
||||||
expect(foo).toEqual({ "tag": "Error", "value": "Function multimodal error: Too many weights provided" })
|
expect(foo).toEqual({ "tag": "Error", "value": "Function multimodal error: Too many weights provided" })
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {runAll} from '../rescript/ProgramEvaluator.gen';
|
import {runAll} from '../rescript/ProgramEvaluator.gen';
|
||||||
import type { Inputs_SamplingInputs_t as SamplingInputs } from '../rescript/ProgramEvaluator.gen';
|
import type { Inputs_SamplingInputs_t as SamplingInputs,exportEnv, exportType, exportDistribution} from '../rescript/ProgramEvaluator.gen';
|
||||||
export type { SamplingInputs }
|
export type { SamplingInputs , exportEnv, exportDistribution }
|
||||||
export type {t as DistPlus} from '../rescript/pointSetDist/DistPlus.gen';
|
export type {t as DistPlus} from '../rescript/pointSetDist/DistPlus.gen';
|
||||||
|
|
||||||
export let defaultSamplingInputs : SamplingInputs = {
|
export let defaultSamplingInputs : SamplingInputs = {
|
||||||
|
@ -9,7 +9,9 @@ export let defaultSamplingInputs : SamplingInputs = {
|
||||||
pointDistLength : 1000
|
pointDistLength : 1000
|
||||||
}
|
}
|
||||||
|
|
||||||
export function run(squiggleString : string, samplingInputs? : SamplingInputs) {
|
export function run(squiggleString : string, samplingInputs? : SamplingInputs, environment?: exportEnv) : { tag: "Ok"; value: exportType }
|
||||||
|
| { tag: "Error"; value: string } {
|
||||||
let si : SamplingInputs = samplingInputs ? samplingInputs : defaultSamplingInputs
|
let si : SamplingInputs = samplingInputs ? samplingInputs : defaultSamplingInputs
|
||||||
return runAll(squiggleString, si)
|
let env : exportEnv = environment ? environment : []
|
||||||
|
return runAll(squiggleString, si, env)
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,12 +36,20 @@ module Inputs = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type exportType = [
|
type exportDistribution = [
|
||||||
| #DistPlus(DistPlus.t)
|
| #DistPlus(DistPlus.t)
|
||||||
| #Float(float)
|
| #Float(float)
|
||||||
| #Function((float) => Belt.Result.t<DistPlus.t,string>)
|
| #Function((float) => Belt.Result.t<DistPlus.t,string>)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
type exportEnv = array<(string, ASTTypes.node)>
|
||||||
|
|
||||||
|
type exportType = {
|
||||||
|
environment : exportEnv,
|
||||||
|
exports: array<exportDistribution>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
module Internals = {
|
module Internals = {
|
||||||
let addVariable = (
|
let addVariable = (
|
||||||
{samplingInputs, squiggleString, environment}: Inputs.inputs,
|
{samplingInputs, squiggleString, environment}: Inputs.inputs,
|
||||||
|
@ -71,135 +79,125 @@ module Internals = {
|
||||||
let runNode = (inputs, node) =>
|
let runNode = (inputs, node) =>
|
||||||
AST.toLeaf(makeInputs(inputs), inputs.environment, node)
|
AST.toLeaf(makeInputs(inputs), inputs.environment, node)
|
||||||
|
|
||||||
|
let renderIfNeeded = (inputs: Inputs.inputs, node: ASTTypes.node): result<
|
||||||
|
ASTTypes.node,
|
||||||
|
string,
|
||||||
|
> =>
|
||||||
|
node |> (
|
||||||
|
x =>
|
||||||
|
switch x {
|
||||||
|
| #Normalize(_) as n
|
||||||
|
| #SymbolicDist(_) as n =>
|
||||||
|
#Render(n)
|
||||||
|
|> runNode(inputs)
|
||||||
|
|> (
|
||||||
|
x =>
|
||||||
|
switch x {
|
||||||
|
| Ok(#RenderedDist(_)) as r => r
|
||||||
|
| Error(r) => Error(r)
|
||||||
|
| _ => Error("Didn't render, but intended to")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
| n => Ok(n)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
let outputToDistPlus = (inputs: Inputs.inputs, pointSetDist: PointSetTypes.pointSetDist) =>
|
||||||
|
DistPlus.make(~pointSetDist, ~squiggleString=Some(inputs.squiggleString), ())
|
||||||
|
|
||||||
|
let rec returnDist = (functionInfo : (array<string>, ASTTypes.node),
|
||||||
|
inputs : Inputs.inputs,
|
||||||
|
env : ASTTypes.environment) => {
|
||||||
|
(input : float) => {
|
||||||
|
let foo: Inputs.inputs = {...inputs, environment: env};
|
||||||
|
evaluateFunction(
|
||||||
|
foo,
|
||||||
|
functionInfo,
|
||||||
|
[#SymbolicDist(#Float(input))],
|
||||||
|
) |> E.R.bind(_, a =>
|
||||||
|
switch a {
|
||||||
|
| #DistPlus(d) => Ok(DistPlus.T.normalize(d))
|
||||||
|
| n =>
|
||||||
|
Js.log2("Error here", n)
|
||||||
|
Error("wrong type")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Consider using ExpressionTypes.ExpressionTree.getFloat or similar in this function
|
||||||
|
and coersionToExportedTypes = (
|
||||||
|
inputs,
|
||||||
|
env: ASTTypes.environment,
|
||||||
|
ex: ASTTypes.node,
|
||||||
|
): result<exportDistribution, string> =>
|
||||||
|
ex
|
||||||
|
|> renderIfNeeded(inputs)
|
||||||
|
|> E.R.bind(_, x =>
|
||||||
|
switch x {
|
||||||
|
| #RenderedDist(Discrete({xyShape: {xs: [x], ys: [1.0]}})) => Ok(#Float(x))
|
||||||
|
| #SymbolicDist(#Float(x)) => Ok(#Float(x))
|
||||||
|
| #RenderedDist(n) => Ok(#DistPlus(outputToDistPlus(inputs, n)))
|
||||||
|
| #Function(n) => Ok(#Function(returnDist(n, inputs, env)))
|
||||||
|
| n => Error("Didn't output a rendered distribution. Format:" ++ AST.toString(n))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
and evaluateFunction = (
|
||||||
|
inputs: Inputs.inputs,
|
||||||
|
fn: (array<string>, ASTTypes.node),
|
||||||
|
fnInputs,
|
||||||
|
) => {
|
||||||
|
let output = AST.runFunction(
|
||||||
|
makeInputs(inputs),
|
||||||
|
inputs.environment,
|
||||||
|
fnInputs,
|
||||||
|
fn,
|
||||||
|
)
|
||||||
|
output |> E.R.bind(_, coersionToExportedTypes(inputs, inputs.environment))
|
||||||
|
}
|
||||||
|
|
||||||
let runProgram = (inputs: Inputs.inputs, p: ASTTypes.program) => {
|
let runProgram = (inputs: Inputs.inputs, p: ASTTypes.program) => {
|
||||||
let ins = ref(inputs)
|
let ins = ref(inputs)
|
||||||
p
|
p
|
||||||
|> E.A.fmap(x =>
|
|> E.A.fmap(x =>
|
||||||
switch x {
|
switch x {
|
||||||
| #Assignment(name, node) =>
|
| #Assignment(name, node) =>
|
||||||
ins := addVariable(ins.contents, name, node)
|
ins := addVariable(ins.contents, name, node)
|
||||||
None
|
None
|
||||||
| #Expression(node) =>
|
| #Expression(node) =>
|
||||||
Some(runNode(ins.contents, node) |> E.R.fmap(r => (ins.contents.environment, r)))
|
Some(runNode(ins.contents, node))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|> E.A.O.concatSomes
|
|> E.A.O.concatSomes
|
||||||
|> E.A.R.firstErrorOrOpen
|
|> E.A.R.firstErrorOrOpen
|
||||||
|
|> E.R.bind(_, d =>
|
||||||
|
d
|
||||||
|
|> E.A.fmap(x => coersionToExportedTypes(inputs, ins.contents.environment, x))
|
||||||
|
|> E.A.R.firstErrorOrOpen
|
||||||
|
)
|
||||||
|
|> E.R.fmap(ex =>
|
||||||
|
{
|
||||||
|
environment: Belt.Map.String.toArray(ins.contents.environment),
|
||||||
|
exports: ex
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let inputsToLeaf = (inputs: Inputs.inputs) =>
|
let inputsToLeaf = (inputs: Inputs.inputs) =>
|
||||||
Parser.fromString(inputs.squiggleString) |> E.R.bind(_, g => runProgram(inputs, g))
|
Parser.fromString(inputs.squiggleString) |> E.R.bind(_, g => runProgram(inputs, g))
|
||||||
|
|
||||||
let outputToDistPlus = (inputs: Inputs.inputs, pointSetDist: PointSetTypes.pointSetDist) =>
|
|
||||||
DistPlus.make(~pointSetDist, ~squiggleString=Some(inputs.squiggleString), ())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let renderIfNeeded = (inputs: Inputs.inputs, node: ASTTypes.node): result<
|
|
||||||
ASTTypes.node,
|
|
||||||
string,
|
|
||||||
> =>
|
|
||||||
node |> (
|
|
||||||
x =>
|
|
||||||
switch x {
|
|
||||||
| #Normalize(_) as n
|
|
||||||
| #SymbolicDist(_) as n =>
|
|
||||||
#Render(n)
|
|
||||||
|> Internals.runNode(inputs)
|
|
||||||
|> (
|
|
||||||
x =>
|
|
||||||
switch x {
|
|
||||||
| Ok(#RenderedDist(_)) as r => r
|
|
||||||
| Error(r) => Error(r)
|
|
||||||
| _ => Error("Didn't render, but intended to")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
| n => Ok(n)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
let rec returnDist = (functionInfo : (array<string>, ASTTypes.node),
|
|
||||||
inputs : Inputs.inputs,
|
|
||||||
env : ASTTypes.environment) => {
|
|
||||||
(input : float) => {
|
|
||||||
let foo: Inputs.inputs = {...inputs, environment: env};
|
|
||||||
evaluateFunction(
|
|
||||||
foo,
|
|
||||||
functionInfo,
|
|
||||||
[#SymbolicDist(#Float(input))],
|
|
||||||
) |> E.R.bind(_, a =>
|
|
||||||
switch a {
|
|
||||||
| #DistPlus(d) => Ok(DistPlus.T.normalize(d))
|
|
||||||
| n =>
|
|
||||||
Js.log2("Error here", n)
|
|
||||||
Error("wrong type")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO: Consider using ExpressionTypes.ExpressionTree.getFloat or similar in this function
|
|
||||||
and coersionToExportedTypes = (
|
|
||||||
inputs,
|
|
||||||
env: ASTTypes.environment,
|
|
||||||
node: ASTTypes.node,
|
|
||||||
): result<exportType, string> =>
|
|
||||||
node
|
|
||||||
|> renderIfNeeded(inputs)
|
|
||||||
|> E.R.bind(_, x =>
|
|
||||||
switch x {
|
|
||||||
| #RenderedDist(Discrete({xyShape: {xs: [x], ys: [1.0]}})) => Ok(#Float(x))
|
|
||||||
| #SymbolicDist(#Float(x)) => Ok(#Float(x))
|
|
||||||
| #RenderedDist(n) => Ok(#DistPlus(Internals.outputToDistPlus(inputs, n)))
|
|
||||||
| #Function(n) => Ok(#Function(returnDist(n, inputs, env)))
|
|
||||||
| n => Error("Didn't output a rendered distribution. Format:" ++ AST.toString(n))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
and evaluateFunction = (
|
|
||||||
inputs: Inputs.inputs,
|
|
||||||
fn: (array<string>, ASTTypes.node),
|
|
||||||
fnInputs,
|
|
||||||
) => {
|
|
||||||
let output = AST.runFunction(
|
|
||||||
Internals.makeInputs(inputs),
|
|
||||||
inputs.environment,
|
|
||||||
fnInputs,
|
|
||||||
fn,
|
|
||||||
)
|
|
||||||
output |> E.R.bind(_, coersionToExportedTypes(inputs, inputs.environment))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let rec mapM = (f, xs) =>
|
|
||||||
switch xs {
|
|
||||||
| [] => Ok([])
|
|
||||||
| arr =>
|
|
||||||
switch f(arr[0]) {
|
|
||||||
| Error(err) => Error(err)
|
|
||||||
| Ok(val) =>
|
|
||||||
switch mapM(f, Belt.Array.sliceToEnd(arr, 1)) {
|
|
||||||
| Error(err) => Error(err)
|
|
||||||
| Ok(restList) => Ok(Belt.Array.concat([val], restList))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let evaluateProgram = (inputs: Inputs.inputs) =>
|
|
||||||
inputs
|
|
||||||
|> Internals.inputsToLeaf
|
|
||||||
|> E.R.bind(_, xs => mapM(((a, b)) => coersionToExportedTypes(inputs, a, b), xs))
|
|
||||||
|
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
let runAll = (squiggleString: string, samplingInputs: Inputs.SamplingInputs.t) => {
|
let runAll : (string, Inputs.SamplingInputs.t, exportEnv) => result<exportType,string> =
|
||||||
|
(squiggleString, samplingInputs, environment) => {
|
||||||
let inputs = Inputs.make(
|
let inputs = Inputs.make(
|
||||||
~samplingInputs,
|
~samplingInputs,
|
||||||
~squiggleString,
|
~squiggleString,
|
||||||
~environment=[]->Belt.Map.String.fromArray,
|
~environment=Belt.Map.String.fromArray(environment),
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
let response1 = evaluateProgram(inputs);
|
Internals.inputsToLeaf(inputs)
|
||||||
response1
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
@genType
|
||||||
type rec hash = array<(string, node)>
|
type rec hash = array<(string, node)>
|
||||||
and node = [
|
and node = [
|
||||||
| #SymbolicDist(SymbolicDistTypes.symbolicDist)
|
| #SymbolicDist(SymbolicDistTypes.symbolicDist)
|
||||||
|
@ -229,4 +230,4 @@ module SamplingDistribution = {
|
||||||
pointSetDist |> E.R.fmap(r => #Normalize(#RenderedDist(r)))
|
pointSetDist |> E.R.fmap(r => #Normalize(#RenderedDist(r)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ type triangular = {
|
||||||
high: float,
|
high: float,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@genType
|
||||||
type symbolicDist = [
|
type symbolicDist = [
|
||||||
| #Normal(normal)
|
| #Normal(normal)
|
||||||
| #Beta(beta)
|
| #Beta(beta)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// This file has no dependencies. It's used outside of the interpreter, but the interpreter depends on it.
|
// This file has no dependencies. It's used outside of the interpreter, but the interpreter depends on it.
|
||||||
|
|
||||||
|
@genType
|
||||||
type algebraicOperation = [
|
type algebraicOperation = [
|
||||||
| #Add
|
| #Add
|
||||||
| #Multiply
|
| #Multiply
|
||||||
|
@ -7,6 +8,7 @@ type algebraicOperation = [
|
||||||
| #Divide
|
| #Divide
|
||||||
| #Exponentiate
|
| #Exponentiate
|
||||||
]
|
]
|
||||||
|
@genType
|
||||||
type pointwiseOperation = [#Add | #Multiply | #Exponentiate]
|
type pointwiseOperation = [#Add | #Multiply | #Exponentiate]
|
||||||
type scaleOperation = [#Multiply | #Exponentiate | #Log]
|
type scaleOperation = [#Multiply | #Exponentiate | #Log]
|
||||||
type distToFloatOperation = [
|
type distToFloatOperation = [
|
||||||
|
@ -109,4 +111,4 @@ module Truncate = {
|
||||||
let right = right |> E.O.dimap(Js.Float.toString, () => "inf")
|
let right = right |> E.O.dimap(Js.Float.toString, () => "inf")
|
||||||
j`truncate($nodeToString, $left, $right)`
|
j`truncate($nodeToString, $left, $right)`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
|
"jsx": "react",
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"removeComments": true,
|
"removeComments": true,
|
||||||
|
|
|
@ -18696,7 +18696,7 @@ webpack-dev-middleware@^5.3.1:
|
||||||
range-parser "^1.2.1"
|
range-parser "^1.2.1"
|
||||||
schema-utils "^4.0.0"
|
schema-utils "^4.0.0"
|
||||||
|
|
||||||
webpack-dev-server@^4.6.0, webpack-dev-server@^4.7.1:
|
webpack-dev-server@^4.6.0, webpack-dev-server@^4.7.1, webpack-dev-server@^4.7.4:
|
||||||
version "4.7.4"
|
version "4.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz#d0ef7da78224578384e795ac228d8efb63d5f945"
|
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz#d0ef7da78224578384e795ac228d8efb63d5f945"
|
||||||
integrity sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A==
|
integrity sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A==
|
||||||
|
|
Loading…
Reference in New Issue
Block a user