From 62f735efcb9bb178b709f82d820b3777175bdd0b Mon Sep 17 00:00:00 2001 From: Sam Nolan Date: Mon, 10 Oct 2022 17:37:21 +1100 Subject: [PATCH] Add plot function --- .github/workflows/ci.yml | 2 +- .../src/components/DistributionChart.tsx | 36 +++--- .../src/components/FunctionChart1Dist.tsx | 5 +- .../SquiggleViewer/ExpressionViewer.tsx | 112 +++++++++--------- packages/components/src/lib/plotParser.ts | 83 ------------- packages/squiggle-lang/src/js/SqPlot.ts | 25 ++++ packages/squiggle-lang/src/js/SqValue.ts | 11 ++ packages/squiggle-lang/src/js/index.ts | 3 +- .../squiggle-lang/src/rescript/FR/FR_Plot.res | 103 ++++++++++++++++ .../ForTS_SquiggleValue.res | 12 ++ .../ForTS_SquiggleValue_Plot.res | 6 + .../ForTS_SquiggleValue_tag.ts | 1 + .../FunctionRegistry_Library.res | 17 +-- .../src/rescript/Reducer/Reducer_T.res | 10 ++ .../src/rescript/Reducer/Reducer_Value.res | 9 ++ 15 files changed, 261 insertions(+), 174 deletions(-) delete mode 100644 packages/components/src/lib/plotParser.ts create mode 100644 packages/squiggle-lang/src/js/SqPlot.ts create mode 100644 packages/squiggle-lang/src/rescript/FR/FR_Plot.res create mode 100644 packages/squiggle-lang/src/rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_Plot.res diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 70f41327..60c889b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -135,7 +135,7 @@ jobs: run: yarn bundle - name: Build storybook run: yarn build - - name: Test components + - name: Test components run: yarn test website-lint: diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx index 3f1b8567..620eba60 100644 --- a/packages/components/src/components/DistributionChart.tsx +++ b/packages/components/src/components/DistributionChart.tsx @@ -3,8 +3,9 @@ import { SqDistribution, result, SqDistributionError, + LabeledDistribution, resultMap, - SqRecord, + SqPlot, environment, SqDistributionTag, } from "@quri/squiggle-lang"; @@ -17,7 +18,6 @@ import { DistributionChartSpecOptions, } from "../lib/distributionSpecBuilder"; import { NumberShower } from "./NumberShower"; -import { Plot, parsePlot } from "../lib/plotParser"; import { flattenResult } from "../lib/utility"; import { hasMassBelowZero } from "../lib/distributionUtils"; @@ -28,27 +28,15 @@ export type DistributionPlottingSettings = { } & DistributionChartSpecOptions; export type DistributionChartProps = { - plot: Plot; environment: environment; 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; - } -} +} & DistributionPlottingSettings & + ({ plot: SqPlot } | { distribution: SqDistribution }); export const DistributionChart: React.FC = (props) => { const { - plot, environment, height, showSummary, @@ -57,8 +45,14 @@ export const DistributionChart: React.FC = (props) => { actions = false, } = props; const [sized] = useSize((size) => { - const shapes = flattenResult( - plot.distributions.map((x) => + let distributions: LabeledDistribution[]; + if ("plot" in props) { + distributions = props.plot.getDistributions(); + } else { + distributions = [{ name: "default", distribution: props.distribution }]; + } + let shapes = flattenResult( + distributions.map((x) => resultMap(x.distribution.pointSet(environment), (pointSet) => ({ name: x.name, // color: x.color, // not supported yet @@ -77,7 +71,7 @@ export const DistributionChart: React.FC = (props) => { // if this is a sample set, include the samples const samples: number[] = []; - for (const { distribution } of plot?.distributions) { + for (const { distribution } of distributions) { if (distribution.tag === SqDistributionTag.SampleSet) { samples.push(...distribution.value()); } @@ -126,9 +120,9 @@ export const DistributionChart: React.FC = (props) => { /> )}
- {showSummary && plot.distributions.length === 1 && ( + {showSummary && distributions.length === 1 && ( )} diff --git a/packages/components/src/components/FunctionChart1Dist.tsx b/packages/components/src/components/FunctionChart1Dist.tsx index 16b5ad47..40aee43b 100644 --- a/packages/components/src/components/FunctionChart1Dist.tsx +++ b/packages/components/src/components/FunctionChart1Dist.tsx @@ -15,7 +15,6 @@ import * as percentilesSpec from "../vega-specs/spec-percentiles.json"; import { DistributionChart, DistributionPlottingSettings, - defaultPlot, } from "./DistributionChart"; import { NumberShower } from "./NumberShower"; import { ErrorAlert } from "./Alert"; @@ -184,7 +183,7 @@ export const FunctionChart1Dist: React.FC = ({ mouseItem.tag === "Ok" && mouseItem.value.tag === SqValueTag.Distribution ? ( = ({ let getPercentilesMemoized = React.useMemo( () => getPercentiles({ chartSettings, fn, environment }), - [environment, fn] + [chartSettings, environment, fn] ); return ( diff --git a/packages/components/src/components/SquiggleViewer/ExpressionViewer.tsx b/packages/components/src/components/SquiggleViewer/ExpressionViewer.tsx index 1c041dbf..9b5e4137 100644 --- a/packages/components/src/components/SquiggleViewer/ExpressionViewer.tsx +++ b/packages/components/src/components/SquiggleViewer/ExpressionViewer.tsx @@ -1,7 +1,7 @@ import React, { useContext } from "react"; import { SqDistributionTag, SqValue, SqValueTag } from "@quri/squiggle-lang"; import { NumberShower } from "../NumberShower"; -import { DistributionChart, defaultPlot, makePlot } from "../DistributionChart"; +import { DistributionChart } from "../DistributionChart"; import { FunctionChart } from "../FunctionChart"; import clsx from "clsx"; import { VariableBox } from "./VariableBox"; @@ -104,7 +104,7 @@ export const ExpressionViewer: React.FC = ({ value, width }) => { {(settings) => { return ( = ({ value, width }) => { ); } + case SqValueTag.Plot: + const plot = value.value; + return ( + { + let disableLogX = plot.getDistributions().some((x) => { + let pointSet = x.distribution.pointSet( + getMergedSettings(value.location).environment + ); + return ( + pointSet.tag === "Ok" && + hasMassBelowZero(pointSet.value.asShape()) + ); + }); + return ( + + ); + }} + > + {(settings) => { + return ( + + ); + }} + + ); case SqValueTag.Record: - const plot = makePlot(value.value); - if (plot) { - return ( - { - let disableLogX = plot.distributions.some((x) => { - let pointSet = x.distribution.pointSet( - getMergedSettings(value.location).environment - ); - return ( - pointSet.tag === "Ok" && - hasMassBelowZero(pointSet.value.asShape()) - ); - }); - return ( - + {(_) => + value.value + .entries() + .map(([key, r]) => ( + - ); - }} - > - {(settings) => { - return ( - - ); - }} - - ); - } else { - return ( - - {(_) => - value.value - .entries() - .map(([key, r]) => ( - - )) - } - - ); - } + )) + } + + ); case SqValueTag.Array: return ( diff --git a/packages/components/src/lib/plotParser.ts b/packages/components/src/lib/plotParser.ts deleted file mode 100644 index 64e757fc..00000000 --- a/packages/components/src/lib/plotParser.ts +++ /dev/null @@ -1,83 +0,0 @@ -import * as yup from "yup"; -import { - SqValue, - SqValueTag, - SqDistribution, - result, - SqRecord, -} from "@quri/squiggle-lang"; - -export type LabeledDistribution = { - name: string; - distribution: SqDistribution; - color?: string; -}; - -export type Plot = { - distributions: LabeledDistribution[]; -}; - -function error(err: b): result { - return { tag: "Error", value: err }; -} - -function ok(x: a): result { - return { tag: "Ok", value: x }; -} - -const schema = yup - .object() - .noUnknown() - .strict() - .shape({ - distributions: yup - .array() - .required() - .of( - yup.object().required().shape({ - name: yup.string().required(), - distribution: yup.mixed().required(), - }) - ), - }); - -type JsonObject = - | string - | { [key: string]: JsonObject } - | JsonObject[] - | SqDistribution; - -function toJson(val: SqValue): JsonObject { - if (val.tag === SqValueTag.String) { - return val.value; - } else if (val.tag === SqValueTag.Record) { - return toJsonRecord(val.value); - } else if (val.tag === SqValueTag.Array) { - return val.value.getValues().map(toJson); - } else if (val.tag === SqValueTag.Distribution) { - return val.value; - } else { - throw new Error("Could not parse object of type " + val.tag); - } -} - -function toJsonRecord(val: SqRecord): JsonObject { - let recordObject: JsonObject = {}; - val.entries().forEach(([key, value]) => (recordObject[key] = toJson(value))); - return recordObject; -} - -export function parsePlot(record: SqRecord): result { - try { - const plotRecord = schema.validateSync(toJsonRecord(record)); - if (plotRecord.distributions) { - return ok({ distributions: plotRecord.distributions.map((x) => x) }); - } else { - // I have no idea why yup's typings thinks this is possible - return error("no distributions field. Should never get here"); - } - } catch (e) { - const message = e instanceof Error ? e.message : "Unknown error"; - return error(message); - } -} diff --git a/packages/squiggle-lang/src/js/SqPlot.ts b/packages/squiggle-lang/src/js/SqPlot.ts new file mode 100644 index 00000000..3a935797 --- /dev/null +++ b/packages/squiggle-lang/src/js/SqPlot.ts @@ -0,0 +1,25 @@ +import * as RSPlot from "../rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_Plot.gen"; +import { SqDistribution, wrapDistribution } from "./SqDistribution"; +import { SqValueLocation } from "./SqValueLocation"; + +type T = RSPlot.squiggleValue_Plot; + +export type LabeledDistribution = { + name: string; + distribution: SqDistribution; +}; + +export class SqPlot { + constructor(private _value: T, public location: SqValueLocation) {} + + getDistributions(): LabeledDistribution[] { + return this._value.distributions.map((v: RSPlot.labeledDistribution) => ({ + ...v, + distribution: wrapDistribution(v.distribution), + })); + } + + toString() { + return RSPlot.toString(this._value); + } +} diff --git a/packages/squiggle-lang/src/js/SqValue.ts b/packages/squiggle-lang/src/js/SqValue.ts index ef2cfca6..7e6719e0 100644 --- a/packages/squiggle-lang/src/js/SqValue.ts +++ b/packages/squiggle-lang/src/js/SqValue.ts @@ -4,6 +4,7 @@ import { wrapDistribution } from "./SqDistribution"; import { SqLambda } from "./SqLambda"; import { SqLambdaDeclaration } from "./SqLambdaDeclaration"; import { SqRecord } from "./SqRecord"; +import { SqPlot } from "./SqPlot"; import { SqArray } from "./SqArray"; import { SqValueLocation } from "./SqValueLocation"; @@ -91,6 +92,14 @@ export class SqNumberValue extends SqAbstractValue { } } +export class SqPlotValue extends SqAbstractValue { + tag = Tag.Plot as const; + + get value() { + return new SqPlot(this.valueMethod(RSValue.getPlot), this.location); + } +} + export class SqRecordValue extends SqAbstractValue { tag = Tag.Record as const; @@ -131,6 +140,7 @@ const tagToClass = { [Tag.Distribution]: SqDistributionValue, [Tag.Lambda]: SqLambdaValue, [Tag.Number]: SqNumberValue, + [Tag.Plot]: SqPlotValue, [Tag.Record]: SqRecordValue, [Tag.String]: SqStringValue, [Tag.TimeDuration]: SqTimeDurationValue, @@ -148,6 +158,7 @@ export type SqValue = | SqLambdaValue | SqNumberValue | SqRecordValue + | SqPlotValue | SqStringValue | SqTimeDurationValue | SqVoidValue; diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index 886c830a..1866e414 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -6,6 +6,7 @@ export { result } from "../rescript/ForTS/ForTS_Result_tag"; export { SqDistribution, SqDistributionTag } from "./SqDistribution"; export { SqDistributionError } from "./SqDistributionError"; export { SqRecord } from "./SqRecord"; +export { SqPlot, LabeledDistribution } from "./SqPlot"; export { SqLambda } from "./SqLambda"; export { SqProject }; export { SqValue, SqValueTag }; @@ -14,7 +15,7 @@ export { defaultEnvironment, } from "../rescript/ForTS/ForTS_Distribution/ForTS_Distribution.gen"; export { SqError, SqFrame, SqLocation } from "./SqError"; -export { SqShape } from "./SqPointSetDist"; +export { SqShape, SqPoint } from "./SqPointSetDist"; export { resultMap } from "./types"; diff --git a/packages/squiggle-lang/src/rescript/FR/FR_Plot.res b/packages/squiggle-lang/src/rescript/FR/FR_Plot.res new file mode 100644 index 00000000..d291fd32 --- /dev/null +++ b/packages/squiggle-lang/src/rescript/FR/FR_Plot.res @@ -0,0 +1,103 @@ +open FunctionRegistry_Core +open FunctionRegistry_Helpers + +let nameSpace = "Plot" + +module Internals = { + let parseString = (a: Reducer_T.value): result => { + switch a { + | IEvString(s) => Ok(s) + | _ => Error(SqError.Message.REOther("Expected to be a string")) + } + } + + let parseDistributionOrNumber = (a: Reducer_T.value): result< + GenericDist.t, + SqError.Message.t, + > => { + switch a { + | IEvDistribution(s) => Ok(s) + | IEvNumber(s) => Ok(GenericDist.fromFloat(s)) + | _ => Error(SqError.Message.REOther("Expected to be a distribution")) + } + } + + let parseArray = ( + parser: Reducer_T.value => result<'a, SqError.Message.t>, + a: Reducer_T.value, + ): result, SqError.Message.t> => { + switch a { + | IEvArray(x) => x->E.A2.fmap(parser)->E.A.R.firstErrorOrOpen + | _ => Error(SqError.Message.REOther("Expected to be an array")) + } + } + + let parseRecord = ( + parser: Reducer_T.map => result<'b, SqError.Message.t>, + a: Reducer_T.value, + ): result<'b, SqError.Message.t> => { + switch a { + | IEvRecord(x) => parser(x) + | _ => Error(SqError.Message.REOther("Expected to be an array")) + } + } + + let parseField = ( + a: Reducer_T.map, + key: string, + parser: Reducer_T.value => result<'a, SqError.Message.t>, + ): result<'a, SqError.Message.t> => { + switch Belt.Map.String.get(a, key) { + | Some(x) => parser(x) + | None => Error(SqError.Message.REOther("expected field " ++ key ++ " in plot dictionary.")) + } + } + + let parseLabeledDistribution = (a: Reducer_T.map): result< + Reducer_T.labeledDistribution, + SqError.Message.t, + > => { + let name = parseField(a, "name", parseString) + let distribution = parseField(a, "value", parseDistributionOrNumber) + switch E.R.merge(name, distribution) { + | Ok(name, distribution) => Ok({name: name, distribution: distribution}) + | Error(err) => Error(err) + } + } + + let parsePlotValue = (a: Reducer_T.map): result => { + parseField(a, "show", parseArray(parseRecord(parseLabeledDistribution)))->E.R2.fmap(dists => { + let plot: Reducer_T.plotValue = {distributions: dists} + plot + }) + } + + let dist = (a: Reducer_T.map): result => + E.R2.fmap(parsePlotValue(a), x => Reducer_T.IEvPlot(x)) +} + +let library = [ + Function.make( + ~name="dist", + ~nameSpace, + ~requiresNamespace=true, + ~output=EvtPlot, + ~examples=[ + `Plot.dist({show: [{name: "Control", value: 1 to 2}, {name: "Treatment", value: 1.5 to 2.5}]}) `, + ], + ~definitions=[ + FnDefinition.make( + ~name="dist", + ~inputs=[FRTypeDict(FRTypeAny)], + ~run=(inputs, _, _) => { + switch inputs { + | [IEvRecord(plot)] => Internals.dist(plot) + | _ => impossibleError->Error + } + }, + (), + ), + ], + (), + ), +] diff --git a/packages/squiggle-lang/src/rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue.res b/packages/squiggle-lang/src/rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue.res index d116b74b..72f1a4a4 100644 --- a/packages/squiggle-lang/src/rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue.res +++ b/packages/squiggle-lang/src/rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue.res @@ -6,6 +6,7 @@ type error = SqError.t //use type squiggleValue_Declaration = ForTS_SquiggleValue_Declaration.squiggleValue_Declaration //use type squiggleValue_Distribution = ForTS_SquiggleValue_Distribution.squiggleValue_Distribution //use type squiggleValue_Lambda = ForTS_SquiggleValue_Lambda.squiggleValue_Lambda //use +@genType type squiggleValue_Plot = Reducer_T.plotValue //use // Return values are kept as they are if they are JavaScript types. @@ -30,6 +31,9 @@ external svtLambda_: string = "Lambda" @module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag") external svtNumber_: string = "Number" +@module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag") +external svtPlot_: string = "Plot" + @module("./ForTS_SquiggleValue_tag") @scope("squiggleValueTag") external svtRecord_: string = "Record" @@ -57,6 +61,7 @@ let getTag = (variant: squiggleValue): squiggleValueTag => | IEvDistribution(_) => svtDistribution_->castEnum | IEvLambda(_) => svtLambda_->castEnum | IEvNumber(_) => svtNumber_->castEnum + | IEvPlot(_) => svtPlot_->castEnum | IEvRecord(_) => svtRecord_->castEnum | IEvString(_) => svtString_->castEnum | IEvTimeDuration(_) => svtTimeDuration_->castEnum @@ -122,6 +127,13 @@ let getNumber = (variant: squiggleValue): option => | _ => None } +@genType +let getPlot = (variant: squiggleValue): option => + switch variant { + | IEvPlot(value) => value->Some + | _ => None + } + @genType let getRecord = (variant: squiggleValue): option => switch variant { diff --git a/packages/squiggle-lang/src/rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_Plot.res b/packages/squiggle-lang/src/rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_Plot.res new file mode 100644 index 00000000..cf5fe526 --- /dev/null +++ b/packages/squiggle-lang/src/rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_Plot.res @@ -0,0 +1,6 @@ +type squiggleValue = ForTS_SquiggleValue.squiggleValue //use +@genType type squiggleValue_Plot = ForTS_SquiggleValue.squiggleValue_Plot //re-export recursive type +@genType type labeledDistribution = Reducer_T.labeledDistribution // use + +@genType +let toString = (v: squiggleValue_Plot) => Reducer_Value.toStringPlot(v) diff --git a/packages/squiggle-lang/src/rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_tag.ts b/packages/squiggle-lang/src/rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_tag.ts index 11d82e6d..1ceafd4e 100644 --- a/packages/squiggle-lang/src/rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_tag.ts +++ b/packages/squiggle-lang/src/rescript/ForTS/ForTS_SquiggleValue/ForTS_SquiggleValue_tag.ts @@ -6,6 +6,7 @@ export enum squiggleValueTag { Distribution = "Distribution", Lambda = "Lambda", Number = "Number", + Plot = "Plot", Record = "Record", String = "String", TimeDuration = "TimeDuration", diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res index 7dc7aa0b..76455969 100644 --- a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res @@ -1,18 +1,19 @@ let fnList = Belt.Array.concatMany([ FR_Builtin.library, + FR_Danger.library, + FR_Date.library, FR_Dict.library, FR_Dist.library, - FR_Danger.library, FR_Fn.library, - FR_Sampleset.library, - FR_List.library, - FR_Number.library, - FR_Pointset.library, - FR_Scoring.library, FR_GenericDist.library, - FR_Units.library, - FR_Date.library, + FR_List.library, FR_Math.library, + FR_Number.library, + FR_Plot.library, + FR_Pointset.library, + FR_Sampleset.library, + FR_Scoring.library, + FR_Units.library, ]) let registry = FunctionRegistry_Core.Registry.make(fnList) diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_T.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_T.res index 36025e40..605c13e4 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_T.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_T.res @@ -9,10 +9,12 @@ type rec value = | IEvDistribution(DistributionTypes.genericDist) | IEvLambda(lambdaValue) | IEvNumber(float) + | IEvPlot(plotValue) | IEvRecord(map) | IEvString(string) | IEvTimeDuration(float) | IEvVoid + @genType.opaque and arrayValue = array @genType.opaque and map = Belt.Map.String.t and lambdaBody = (array, context, reducerFn) => value @@ -66,4 +68,12 @@ and context = { and reducerFn = (expression, context) => (value, context) +@genType and plotValue = {distributions: array} + +@genType +and labeledDistribution = { + name: string, + distribution: DistributionTypes.genericDist, +} + let topFrameName = "" diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Value.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Value.res index 01f97647..8199456f 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Value.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Value.res @@ -14,6 +14,7 @@ let rec toString = (aValue: T.value) => | IEvDistribution(dist) => toStringDistribution(dist) | IEvLambda(lambdaValue) => toStringLambda(lambdaValue) | IEvNumber(aNumber) => toStringNumber(aNumber) + | IEvPlot(aPlot) => toStringPlot(aPlot) | IEvRecord(aMap) => aMap->toStringRecord | IEvString(aString) => toStringString(aString) | IEvTimeDuration(t) => toStringTimeDuration(t) @@ -35,6 +36,10 @@ and toStringLambda = (lambdaValue: T.lambdaValue) => { } } and toStringNumber = aNumber => Js.String.make(aNumber) +and toStringPlot = aPlot => { + let chartNames = E.A.fmap((x: Reducer_T.labeledDistribution) => x.name, aPlot.distributions) + `Plot showing ${Js.Array2.toString(chartNames)}` +} and toStringRecord = aMap => aMap->toStringMap and toStringString = aString => `'${aString}'` and toStringSymbol = aString => `:${aString}` @@ -59,6 +64,7 @@ let toStringWithType = (aValue: T.value) => | IEvDistribution(_) => `Distribution::${toString(aValue)}` | IEvLambda(_) => `Lambda::${toString(aValue)}` | IEvNumber(_) => `Number::${toString(aValue)}` + | IEvPlot(_) => `Plot::${toString(aValue)}` | IEvRecord(_) => `Record::${toString(aValue)}` | IEvString(_) => `String::${toString(aValue)}` | IEvTimeDuration(_) => `Date::${toString(aValue)}` @@ -91,6 +97,7 @@ type internalExpressionValueType = | EvtDistribution | EvtLambda | EvtNumber + | EvtPlot | EvtRecord | EvtString | EvtTimeDuration @@ -109,6 +116,7 @@ let valueToValueType = (value: T.value) => | IEvDistribution(_) => EvtDistribution | IEvLambda(_) => EvtLambda | IEvNumber(_) => EvtNumber + | IEvPlot(_) => EvtPlot | IEvRecord(_) => EvtRecord | IEvString(_) => EvtString | IEvTimeDuration(_) => EvtTimeDuration @@ -129,6 +137,7 @@ let valueTypeToString = (valueType: internalExpressionValueType): string => | EvtDistribution => `Distribution` | EvtLambda => `Lambda` | EvtNumber => `Number` + | EvtPlot => `Plot` | EvtRecord => `Record` | EvtString => `String` | EvtTimeDuration => `Duration`