Merge pull request #591 from quantified-uncertainty/declare-test
Declare() functionality
This commit is contained in:
commit
70664c0a91
|
@ -11,12 +11,36 @@ import {
|
||||||
defaultImports,
|
defaultImports,
|
||||||
defaultBindings,
|
defaultBindings,
|
||||||
defaultEnvironment,
|
defaultEnvironment,
|
||||||
|
declarationArg,
|
||||||
|
declaration,
|
||||||
} from "@quri/squiggle-lang";
|
} from "@quri/squiggle-lang";
|
||||||
import { NumberShower } from "./NumberShower";
|
import { NumberShower } from "./NumberShower";
|
||||||
import { DistributionChart } from "./DistributionChart";
|
import { DistributionChart } from "./DistributionChart";
|
||||||
import { ErrorBox } from "./ErrorBox";
|
import { ErrorBox } from "./ErrorBox";
|
||||||
import { FunctionChart, FunctionChartSettings } from "./FunctionChart";
|
import { FunctionChart, FunctionChartSettings } from "./FunctionChart";
|
||||||
|
|
||||||
|
function getRange<a>(x: declaration<a>) {
|
||||||
|
let first = x.args[0];
|
||||||
|
switch (first.tag) {
|
||||||
|
case "Float": {
|
||||||
|
return { floats: { min: first.value.min, max: first.value.max } };
|
||||||
|
}
|
||||||
|
case "Date": {
|
||||||
|
return { time: { min: first.value.min, max: first.value.max } };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getChartSettings<a>(x: declaration<a>): FunctionChartSettings {
|
||||||
|
let range = getRange(x);
|
||||||
|
let min = range.floats ? range.floats.min : 0;
|
||||||
|
let max = range.floats ? range.floats.max : 10;
|
||||||
|
return {
|
||||||
|
start: min,
|
||||||
|
stop: max,
|
||||||
|
count: 20,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const variableBox = {
|
const variableBox = {
|
||||||
Component: styled.div`
|
Component: styled.div`
|
||||||
background: white;
|
background: white;
|
||||||
|
@ -216,6 +240,24 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
||||||
/>
|
/>
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
|
case "lambdaDeclaration": {
|
||||||
|
return (
|
||||||
|
<VariableBox heading="Function Declaration" showTypes={showTypes}>
|
||||||
|
<FunctionChart
|
||||||
|
fn={expression.value.fn}
|
||||||
|
chartSettings={getChartSettings(expression.value)}
|
||||||
|
height={height}
|
||||||
|
environment={{
|
||||||
|
sampleCount: environment.sampleCount / 10,
|
||||||
|
xyPointLength: environment.xyPointLength / 10,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</VariableBox>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return <>Should be unreachable</>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
"tickOpacity": 0.0,
|
"tickOpacity": 0.0,
|
||||||
"domainColor": "#fff",
|
"domainColor": "#fff",
|
||||||
"domainOpacity": 0.0,
|
"domainOpacity": 0.0,
|
||||||
"format": "~g",
|
"format": ".9~s",
|
||||||
"tickCount": 10
|
"tickCount": 10
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
"name": "x",
|
"name": "x",
|
||||||
"type": "linear",
|
"type": "linear",
|
||||||
"nice": true,
|
"nice": true,
|
||||||
|
"zero": false,
|
||||||
"domain": {
|
"domain": {
|
||||||
"data": "facet",
|
"data": "facet",
|
||||||
"field": "x"
|
"field": "x"
|
||||||
|
@ -31,7 +32,7 @@
|
||||||
"type": "linear",
|
"type": "linear",
|
||||||
"range": "height",
|
"range": "height",
|
||||||
"nice": true,
|
"nice": true,
|
||||||
"zero": true,
|
"zero": false,
|
||||||
"domain": {
|
"domain": {
|
||||||
"data": "facet",
|
"data": "facet",
|
||||||
"field": "y"
|
"field": "y"
|
||||||
|
@ -58,6 +59,7 @@
|
||||||
"tickOpacity": 0.0,
|
"tickOpacity": 0.0,
|
||||||
"domainColor": "#727d93",
|
"domainColor": "#727d93",
|
||||||
"domainOpacity": 0.1,
|
"domainOpacity": 0.1,
|
||||||
|
"format": ".9~s",
|
||||||
"tickCount": 5
|
"tickCount": 5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -69,6 +71,7 @@
|
||||||
"tickOpacity": 0.0,
|
"tickOpacity": 0.0,
|
||||||
"domainColor": "#727d93",
|
"domainColor": "#727d93",
|
||||||
"domainOpacity": 0.1,
|
"domainOpacity": 0.1,
|
||||||
|
"format": ".9~s",
|
||||||
"tickCount": 5
|
"tickCount": 5
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -75,6 +75,7 @@
|
||||||
"name": "xscale",
|
"name": "xscale",
|
||||||
"type": "linear",
|
"type": "linear",
|
||||||
"nice": true,
|
"nice": true,
|
||||||
|
"zero": false,
|
||||||
"domain": {
|
"domain": {
|
||||||
"data": "facet",
|
"data": "facet",
|
||||||
"field": "x"
|
"field": "x"
|
||||||
|
@ -86,10 +87,10 @@
|
||||||
"type": "linear",
|
"type": "linear",
|
||||||
"range": "height",
|
"range": "height",
|
||||||
"nice": true,
|
"nice": true,
|
||||||
"zero": true,
|
"zero": false,
|
||||||
"domain": {
|
"domain": {
|
||||||
"data": "facet",
|
"data": "facet",
|
||||||
"field": "p99"
|
"fields": ["p1", "p99"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -113,12 +114,14 @@
|
||||||
"tickOpacity": 0.0,
|
"tickOpacity": 0.0,
|
||||||
"domainColor": "#727d93",
|
"domainColor": "#727d93",
|
||||||
"domainOpacity": 0.1,
|
"domainOpacity": 0.1,
|
||||||
|
"format": ".9~s",
|
||||||
"tickCount": 5
|
"tickCount": 5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"orient": "left",
|
"orient": "left",
|
||||||
"scale": "yscale",
|
"scale": "yscale",
|
||||||
"grid": false,
|
"grid": false,
|
||||||
|
"format": ".9~s",
|
||||||
"labelColor": "#727d93",
|
"labelColor": "#727d93",
|
||||||
"tickColor": "#fff",
|
"tickColor": "#fff",
|
||||||
"tickOpacity": 0.0,
|
"tickOpacity": 0.0,
|
||||||
|
|
|
@ -14,6 +14,8 @@ export {
|
||||||
errorValueToString,
|
errorValueToString,
|
||||||
distributionErrorToString,
|
distributionErrorToString,
|
||||||
distributionError,
|
distributionError,
|
||||||
|
declarationArg,
|
||||||
|
declaration,
|
||||||
} from "../rescript/TypescriptInterface.gen";
|
} from "../rescript/TypescriptInterface.gen";
|
||||||
export type { errorValue, externalBindings as bindings, jsImports };
|
export type { errorValue, externalBindings as bindings, jsImports };
|
||||||
import {
|
import {
|
||||||
|
@ -185,5 +187,7 @@ function createTsExport(
|
||||||
return tag("date", x.value);
|
return tag("date", x.value);
|
||||||
case "EvTimeDuration":
|
case "EvTimeDuration":
|
||||||
return tag("timeDuration", x.value);
|
return tag("timeDuration", x.value);
|
||||||
|
case "EvDeclaration":
|
||||||
|
return tag("lambdaDeclaration", x.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ import {
|
||||||
discreteShape,
|
discreteShape,
|
||||||
continuousShape,
|
continuousShape,
|
||||||
lambdaValue,
|
lambdaValue,
|
||||||
|
lambdaDeclaration,
|
||||||
|
declarationArg,
|
||||||
} from "../rescript/TypescriptInterface.gen";
|
} from "../rescript/TypescriptInterface.gen";
|
||||||
import { Distribution } from "./distribution";
|
import { Distribution } from "./distribution";
|
||||||
import { tagged, tag } from "./types";
|
import { tagged, tag } from "./types";
|
||||||
|
@ -63,6 +65,10 @@ export type rescriptExport =
|
||||||
| {
|
| {
|
||||||
TAG: 11; // EvTimeDuration
|
TAG: 11; // EvTimeDuration
|
||||||
_0: number;
|
_0: number;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
TAG: 12; // EvDeclaration
|
||||||
|
_0: rescriptLambdaDeclaration;
|
||||||
};
|
};
|
||||||
|
|
||||||
type rescriptDist =
|
type rescriptDist =
|
||||||
|
@ -84,6 +90,23 @@ type rescriptPointSetDist =
|
||||||
_0: continuousShape;
|
_0: continuousShape;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type rescriptLambdaDeclaration = {
|
||||||
|
readonly fn: lambdaValue;
|
||||||
|
readonly args: rescriptDeclarationArg[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type rescriptDeclarationArg =
|
||||||
|
| {
|
||||||
|
TAG: 0; // Float
|
||||||
|
min: number;
|
||||||
|
max: number;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
TAG: 1; // Date
|
||||||
|
min: Date;
|
||||||
|
max: Date;
|
||||||
|
};
|
||||||
|
|
||||||
export type squiggleExpression =
|
export type squiggleExpression =
|
||||||
| tagged<"symbol", string>
|
| tagged<"symbol", string>
|
||||||
| tagged<"string", string>
|
| tagged<"string", string>
|
||||||
|
@ -96,6 +119,7 @@ export type squiggleExpression =
|
||||||
| tagged<"number", number>
|
| tagged<"number", number>
|
||||||
| tagged<"date", Date>
|
| tagged<"date", Date>
|
||||||
| tagged<"timeDuration", number>
|
| tagged<"timeDuration", number>
|
||||||
|
| tagged<"lambdaDeclaration", lambdaDeclaration>
|
||||||
| tagged<"record", { [key: string]: squiggleExpression }>;
|
| tagged<"record", { [key: string]: squiggleExpression }>;
|
||||||
|
|
||||||
export { lambdaValue };
|
export { lambdaValue };
|
||||||
|
@ -141,6 +165,22 @@ export function convertRawToTypescript(
|
||||||
return tag("date", result._0);
|
return tag("date", result._0);
|
||||||
case 11: // EvTimeDuration
|
case 11: // EvTimeDuration
|
||||||
return tag("number", result._0);
|
return tag("number", result._0);
|
||||||
|
case 12: // EvDeclaration
|
||||||
|
return tag("lambdaDeclaration", {
|
||||||
|
fn: result._0.fn,
|
||||||
|
args: result._0.args.map(convertDeclaration),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertDeclaration(
|
||||||
|
declarationArg: rescriptDeclarationArg
|
||||||
|
): declarationArg {
|
||||||
|
switch (declarationArg.TAG) {
|
||||||
|
case 0: // Float
|
||||||
|
return tag("Float", { min: declarationArg.min, max: declarationArg.max });
|
||||||
|
case 1: // Date
|
||||||
|
return tag("Date", { min: declarationArg.min, max: declarationArg.max });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,11 @@ type rec frType =
|
||||||
| FRTypeNumber
|
| FRTypeNumber
|
||||||
| FRTypeNumeric
|
| FRTypeNumeric
|
||||||
| FRTypeDistOrNumber
|
| FRTypeDistOrNumber
|
||||||
|
| FRTypeLambda
|
||||||
| FRTypeRecord(frTypeRecord)
|
| FRTypeRecord(frTypeRecord)
|
||||||
| FRTypeArray(array<frType>)
|
| FRTypeArray(frType)
|
||||||
| FRTypeOption(frType)
|
| FRTypeString
|
||||||
|
| FRTypeVariant(array<string>)
|
||||||
and frTypeRecord = array<frTypeRecordParam>
|
and frTypeRecord = array<frTypeRecordParam>
|
||||||
and frTypeRecordParam = (string, frType)
|
and frTypeRecordParam = (string, frType)
|
||||||
|
|
||||||
|
@ -21,9 +23,12 @@ and frTypeRecordParam = (string, frType)
|
||||||
type rec frValue =
|
type rec frValue =
|
||||||
| FRValueNumber(float)
|
| FRValueNumber(float)
|
||||||
| FRValueDist(DistributionTypes.genericDist)
|
| FRValueDist(DistributionTypes.genericDist)
|
||||||
| FRValueOption(option<frValue>)
|
| FRValueArray(array<frValue>)
|
||||||
| FRValueDistOrNumber(frValueDistOrNumber)
|
| FRValueDistOrNumber(frValueDistOrNumber)
|
||||||
| FRValueRecord(frValueRecord)
|
| FRValueRecord(frValueRecord)
|
||||||
|
| FRValueLambda(ReducerInterface_ExpressionValue.lambdaValue)
|
||||||
|
| FRValueString(string)
|
||||||
|
| FRValueVariant(string)
|
||||||
and frValueRecord = array<frValueRecordParam>
|
and frValueRecord = array<frValueRecordParam>
|
||||||
and frValueRecordParam = (string, frValue)
|
and frValueRecordParam = (string, frValue)
|
||||||
and frValueDistOrNumber = FRValueNumber(float) | FRValueDist(DistributionTypes.genericDist)
|
and frValueDistOrNumber = FRValueNumber(float) | FRValueDist(DistributionTypes.genericDist)
|
||||||
|
@ -52,8 +57,10 @@ module FRType = {
|
||||||
let input = ((name, frType): frTypeRecordParam) => `${name}: ${toString(frType)}`
|
let input = ((name, frType): frTypeRecordParam) => `${name}: ${toString(frType)}`
|
||||||
`record({${r->E.A2.fmap(input)->E.A2.joinWith(", ")}})`
|
`record({${r->E.A2.fmap(input)->E.A2.joinWith(", ")}})`
|
||||||
}
|
}
|
||||||
| FRTypeArray(r) => `record(${r->E.A2.fmap(toString)->E.A2.joinWith(", ")})`
|
| FRTypeArray(r) => `record(${toString(r)})`
|
||||||
| FRTypeOption(v) => `option(${toString(v)})`
|
| FRTypeLambda => `lambda`
|
||||||
|
| FRTypeString => `string`
|
||||||
|
| FRTypeVariant(_) => "variant"
|
||||||
}
|
}
|
||||||
|
|
||||||
let rec matchWithExpressionValue = (t: t, r: expressionValue): option<frValue> =>
|
let rec matchWithExpressionValue = (t: t, r: expressionValue): option<frValue> =>
|
||||||
|
@ -65,7 +72,11 @@ module FRType = {
|
||||||
| (FRTypeDistOrNumber, EvDistribution(f)) => Some(FRValueDistOrNumber(FRValueDist(f)))
|
| (FRTypeDistOrNumber, EvDistribution(f)) => Some(FRValueDistOrNumber(FRValueDist(f)))
|
||||||
| (FRTypeNumeric, EvNumber(f)) => Some(FRValueNumber(f))
|
| (FRTypeNumeric, EvNumber(f)) => Some(FRValueNumber(f))
|
||||||
| (FRTypeNumeric, EvDistribution(Symbolic(#Float(f)))) => Some(FRValueNumber(f))
|
| (FRTypeNumeric, EvDistribution(Symbolic(#Float(f)))) => Some(FRValueNumber(f))
|
||||||
| (FRTypeOption(v), _) => Some(FRValueOption(matchWithExpressionValue(v, r)))
|
| (FRTypeLambda, EvLambda(f)) => Some(FRValueLambda(f))
|
||||||
|
| (FRTypeArray(intendedType), EvArray(elements)) => {
|
||||||
|
let el = elements->E.A2.fmap(matchWithExpressionValue(intendedType))
|
||||||
|
E.A.O.openIfAllSome(el)->E.O2.fmap(r => FRValueArray(r))
|
||||||
|
}
|
||||||
| (FRTypeRecord(recordParams), EvRecord(record)) => {
|
| (FRTypeRecord(recordParams), EvRecord(record)) => {
|
||||||
let getAndMatch = (name, input) =>
|
let getAndMatch = (name, input) =>
|
||||||
E.Dict.get(record, name)->E.O.bind(matchWithExpressionValue(input))
|
E.Dict.get(record, name)->E.O.bind(matchWithExpressionValue(input))
|
||||||
|
@ -80,6 +91,23 @@ module FRType = {
|
||||||
| _ => None
|
| _ => None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let rec matchReverse = (e: frValue): expressionValue =>
|
||||||
|
switch e {
|
||||||
|
| FRValueNumber(f) => EvNumber(f)
|
||||||
|
| FRValueDistOrNumber(FRValueNumber(n)) => EvNumber(n)
|
||||||
|
| FRValueDistOrNumber(FRValueDist(n)) => EvDistribution(n)
|
||||||
|
| FRValueDist(dist) => EvDistribution(dist)
|
||||||
|
| FRValueArray(elements) => EvArray(elements->E.A2.fmap(matchReverse))
|
||||||
|
| FRValueRecord(frValueRecord) => {
|
||||||
|
let record =
|
||||||
|
frValueRecord->E.A2.fmap(((name, value)) => (name, matchReverse(value)))->E.Dict.fromArray
|
||||||
|
EvRecord(record)
|
||||||
|
}
|
||||||
|
| FRValueLambda(l) => EvLambda(l)
|
||||||
|
| FRValueString(string) => EvString(string)
|
||||||
|
| FRValueVariant(string) => EvString(string)
|
||||||
|
}
|
||||||
|
|
||||||
let matchWithExpressionValueArray = (inputs: array<t>, args: array<expressionValue>): option<
|
let matchWithExpressionValueArray = (inputs: array<t>, args: array<expressionValue>): option<
|
||||||
array<frValue>,
|
array<frValue>,
|
||||||
> => {
|
> => {
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
|
||||||
|
|
||||||
type rec frType =
|
|
||||||
| FRTypeNumber
|
|
||||||
| FRTypeNumeric
|
|
||||||
| FRTypeDistOrNumber
|
|
||||||
| FRTypeRecord(frTypeRecord)
|
|
||||||
| FRTypeArray(array<frType>)
|
|
||||||
| FRTypeOption(frType)
|
|
||||||
and frTypeRecord = array<frTypeRecordParam>
|
|
||||||
and frTypeRecordParam = (string, frType)
|
|
||||||
|
|
||||||
type rec frValue =
|
|
||||||
| FRValueNumber(float)
|
|
||||||
| FRValueDist(DistributionTypes.genericDist)
|
|
||||||
| FRValueOption(option<frValue>)
|
|
||||||
| FRValueDistOrNumber(frValueDistOrNumber)
|
|
||||||
| FRValueRecord(frValueRecord)
|
|
||||||
and frValueRecord = array<frValueRecordParam>
|
|
||||||
and frValueRecordParam = (string, frValue)
|
|
||||||
and frValueDistOrNumber = FRValueNumber(float) | FRValueDist(DistributionTypes.genericDist)
|
|
||||||
|
|
||||||
type fnDefinition = {
|
|
||||||
name: string,
|
|
||||||
inputs: array<frType>,
|
|
||||||
run: (array<frValue>, DistributionOperation.env) => result<expressionValue, string>,
|
|
||||||
}
|
|
||||||
|
|
||||||
type function = {
|
|
||||||
name: string,
|
|
||||||
definitions: array<fnDefinition>,
|
|
||||||
}
|
|
||||||
|
|
||||||
type registry = array<function>
|
|
||||||
|
|
||||||
// Note: The function "name" is just used for documentation purposes
|
|
||||||
module Function: {
|
|
||||||
type t = function
|
|
||||||
let make: (~name: string, ~definitions: array<fnDefinition>) => t
|
|
||||||
}
|
|
||||||
|
|
||||||
module FnDefinition: {
|
|
||||||
type t = fnDefinition
|
|
||||||
let make: (
|
|
||||||
~name: string,
|
|
||||||
~inputs: array<frType>,
|
|
||||||
~run: (array<frValue>, DistributionOperation.env) => result<expressionValue, string>,
|
|
||||||
) => t
|
|
||||||
}
|
|
||||||
|
|
||||||
module Registry: {
|
|
||||||
let matchAndRun: (
|
|
||||||
~registry: registry,
|
|
||||||
~fnName: string,
|
|
||||||
~args: array<expressionValue>,
|
|
||||||
~env: QuriSquiggleLang.DistributionOperation.env,
|
|
||||||
) => option<result<expressionValue, string>>
|
|
||||||
}
|
|
|
@ -19,6 +19,12 @@ module Prepare = {
|
||||||
| [FRValueRecord([(_, n1), (_, n2)])] => Ok([n1, n2])
|
| [FRValueRecord([(_, n1), (_, n2)])] => Ok([n1, n2])
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let toArgs = (inputs: ts): result<ts, err> =>
|
||||||
|
switch inputs {
|
||||||
|
| [FRValueRecord(args)] => args->E.A2.fmap(((_, b)) => b)->Ok
|
||||||
|
| _ => Error(impossibleError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +36,13 @@ module Prepare = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let twoNumbers = (values: ts): result<(float, float), err> => {
|
||||||
|
switch values {
|
||||||
|
| [FRValueNumber(a1), FRValueNumber(a2)] => Ok(a1, a2)
|
||||||
|
| _ => Error(impossibleError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let oneDistOrNumber = (values: ts): result<frValueDistOrNumber, err> => {
|
let oneDistOrNumber = (values: ts): result<frValueDistOrNumber, err> => {
|
||||||
switch values {
|
switch values {
|
||||||
| [FRValueDistOrNumber(a1)] => Ok(a1)
|
| [FRValueDistOrNumber(a1)] => Ok(a1)
|
||||||
|
|
|
@ -3,7 +3,42 @@ open FunctionRegistry_Helpers
|
||||||
|
|
||||||
let twoArgs = E.Tuple2.toFnCall
|
let twoArgs = E.Tuple2.toFnCall
|
||||||
|
|
||||||
|
module Declaration = {
|
||||||
|
let frType = FRTypeRecord([
|
||||||
|
("fn", FRTypeLambda),
|
||||||
|
("inputs", FRTypeArray(FRTypeRecord([("min", FRTypeNumber), ("max", FRTypeNumber)]))),
|
||||||
|
])
|
||||||
|
|
||||||
|
let fromExpressionValue = (e: frValue): result<expressionValue, string> => {
|
||||||
|
switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.twoArgs([e]) {
|
||||||
|
| Ok([FRValueLambda(lambda), FRValueArray(inputs)]) => {
|
||||||
|
open FunctionRegistry_Helpers.Prepare
|
||||||
|
let getMinMax = arg =>
|
||||||
|
ToValueArray.Record.toArgs([arg])
|
||||||
|
->E.R.bind(ToValueTuple.twoNumbers)
|
||||||
|
->E.R2.fmap(((min, max)) => Declaration.ContinuousFloatArg.make(min, max))
|
||||||
|
inputs
|
||||||
|
->E.A2.fmap(getMinMax)
|
||||||
|
->E.A.R.firstErrorOrOpen
|
||||||
|
->E.R2.fmap(args => ReducerInterface_ExpressionValue.EvDeclaration(
|
||||||
|
Declaration.make(lambda, args),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
| Error(r) => Error(r)
|
||||||
|
| Ok(_) => Error(FunctionRegistry_Helpers.impossibleError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let registry = [
|
let registry = [
|
||||||
|
Function.make(
|
||||||
|
~name="FnMake",
|
||||||
|
~definitions=[
|
||||||
|
FnDefinition.make(~name="declareFn", ~inputs=[Declaration.frType], ~run=(inputs, _) => {
|
||||||
|
inputs->E.A.unsafe_get(0)->Declaration.fromExpressionValue
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
Function.make(
|
Function.make(
|
||||||
~name="Normal",
|
~name="Normal",
|
||||||
~definitions=[
|
~definitions=[
|
||||||
|
|
|
@ -22,6 +22,7 @@ type rec expressionValue =
|
||||||
| EvSymbol(string)
|
| EvSymbol(string)
|
||||||
| EvDate(Js.Date.t)
|
| EvDate(Js.Date.t)
|
||||||
| EvTimeDuration(float)
|
| EvTimeDuration(float)
|
||||||
|
| EvDeclaration(lambdaDeclaration)
|
||||||
and record = Js.Dict.t<expressionValue>
|
and record = Js.Dict.t<expressionValue>
|
||||||
and externalBindings = record
|
and externalBindings = record
|
||||||
and lambdaValue = {
|
and lambdaValue = {
|
||||||
|
@ -29,6 +30,7 @@ and lambdaValue = {
|
||||||
context: externalBindings,
|
context: externalBindings,
|
||||||
body: internalCode,
|
body: internalCode,
|
||||||
}
|
}
|
||||||
|
and lambdaDeclaration = Declaration.declaration<lambdaValue>
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
let defaultExternalBindings: externalBindings = Js.Dict.empty()
|
let defaultExternalBindings: externalBindings = Js.Dict.empty()
|
||||||
|
@ -55,6 +57,7 @@ let rec toString = aValue =>
|
||||||
| EvDistribution(dist) => GenericDist.toString(dist)
|
| EvDistribution(dist) => GenericDist.toString(dist)
|
||||||
| EvDate(date) => DateTime.Date.toString(date)
|
| EvDate(date) => DateTime.Date.toString(date)
|
||||||
| EvTimeDuration(t) => DateTime.Duration.toString(t)
|
| EvTimeDuration(t) => DateTime.Duration.toString(t)
|
||||||
|
| EvDeclaration(d) => Declaration.toString(d, r => toString(EvLambda(r)))
|
||||||
}
|
}
|
||||||
and toStringRecord = aRecord => {
|
and toStringRecord = aRecord => {
|
||||||
let pairs =
|
let pairs =
|
||||||
|
@ -79,6 +82,7 @@ let toStringWithType = aValue =>
|
||||||
| EvSymbol(_) => `Symbol::${toString(aValue)}`
|
| EvSymbol(_) => `Symbol::${toString(aValue)}`
|
||||||
| EvDate(_) => `Date::${toString(aValue)}`
|
| EvDate(_) => `Date::${toString(aValue)}`
|
||||||
| EvTimeDuration(_) => `Date::${toString(aValue)}`
|
| EvTimeDuration(_) => `Date::${toString(aValue)}`
|
||||||
|
| EvDeclaration(_) => `Declaration::${toString(aValue)}`
|
||||||
}
|
}
|
||||||
|
|
||||||
let argsToString = (args: array<expressionValue>): string => {
|
let argsToString = (args: array<expressionValue>): string => {
|
||||||
|
@ -124,6 +128,7 @@ type expressionValueType =
|
||||||
| EvtSymbol
|
| EvtSymbol
|
||||||
| EvtDate
|
| EvtDate
|
||||||
| EvtTimeDuration
|
| EvtTimeDuration
|
||||||
|
| EvtDeclaration
|
||||||
|
|
||||||
type functionCallSignature = CallSignature(string, array<expressionValueType>)
|
type functionCallSignature = CallSignature(string, array<expressionValueType>)
|
||||||
type functionDefinitionSignature =
|
type functionDefinitionSignature =
|
||||||
|
@ -143,6 +148,7 @@ let valueToValueType = value =>
|
||||||
| EvSymbol(_) => EvtSymbol
|
| EvSymbol(_) => EvtSymbol
|
||||||
| EvDate(_) => EvtDate
|
| EvDate(_) => EvtDate
|
||||||
| EvTimeDuration(_) => EvtTimeDuration
|
| EvTimeDuration(_) => EvtTimeDuration
|
||||||
|
| EvDeclaration(_) => EvtDeclaration
|
||||||
}
|
}
|
||||||
|
|
||||||
let functionCallToCallSignature = (functionCall: functionCall): functionCallSignature => {
|
let functionCallToCallSignature = (functionCall: functionCall): functionCallSignature => {
|
||||||
|
@ -164,6 +170,7 @@ let valueTypeToString = (valueType: expressionValueType): string =>
|
||||||
| EvtSymbol => `Symbol`
|
| EvtSymbol => `Symbol`
|
||||||
| EvtDate => `Date`
|
| EvtDate => `Date`
|
||||||
| EvtTimeDuration => `Duration`
|
| EvtTimeDuration => `Duration`
|
||||||
|
| EvtDeclaration => `Declaration`
|
||||||
}
|
}
|
||||||
|
|
||||||
let functionCallSignatureToString = (functionCallSignature: functionCallSignature): string => {
|
let functionCallSignatureToString = (functionCallSignature: functionCallSignature): string => {
|
||||||
|
|
|
@ -76,6 +76,9 @@ let distributionErrorToString = DistributionTypes.Error.toString
|
||||||
@genType
|
@genType
|
||||||
type lambdaValue = ReducerInterface_ExpressionValue.lambdaValue
|
type lambdaValue = ReducerInterface_ExpressionValue.lambdaValue
|
||||||
|
|
||||||
|
@genType
|
||||||
|
type lambdaDeclaration = ReducerInterface_ExpressionValue.lambdaDeclaration
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
let defaultSamplingEnv = DistributionOperation.defaultEnv
|
let defaultSamplingEnv = DistributionOperation.defaultEnv
|
||||||
|
|
||||||
|
@ -87,3 +90,9 @@ let defaultEnvironment = ReducerInterface_ExpressionValue.defaultEnvironment
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
let foreignFunctionInterface = Reducer.foreignFunctionInterface
|
let foreignFunctionInterface = Reducer.foreignFunctionInterface
|
||||||
|
|
||||||
|
@genType
|
||||||
|
type declarationArg = Declaration.arg
|
||||||
|
|
||||||
|
@genType
|
||||||
|
type declaration<'a> = Declaration.declaration<'a>
|
||||||
|
|
42
packages/squiggle-lang/src/rescript/Utility/Declaration.res
Normal file
42
packages/squiggle-lang/src/rescript/Utility/Declaration.res
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
@genType
|
||||||
|
type arg = Float({min: float, max: float}) | Date({min: Js.Date.t, max: Js.Date.t})
|
||||||
|
|
||||||
|
@genType
|
||||||
|
type declaration<'a> = {
|
||||||
|
fn: 'a,
|
||||||
|
args: array<arg>,
|
||||||
|
}
|
||||||
|
|
||||||
|
module ContinuousFloatArg = {
|
||||||
|
let make = (min: float, max: float): arg => {
|
||||||
|
Float({min: min, max: max})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module ContinuousTimeArg = {
|
||||||
|
let make = (min: Js.Date.t, max: Js.Date.t): arg => {
|
||||||
|
Date({min: min, max: max})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module Arg = {
|
||||||
|
let toString = (arg: arg) => {
|
||||||
|
switch arg {
|
||||||
|
| Float({min, max}) =>
|
||||||
|
`Float({min: ${E.Float.with2DigitsPrecision(min)}, max: ${E.Float.with2DigitsPrecision(
|
||||||
|
max,
|
||||||
|
)}})`
|
||||||
|
| Date({min, max}) =>
|
||||||
|
`Date({min: ${DateTime.Date.toString(min)}, max: ${DateTime.Date.toString(max)}})`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let make = (fn: 'a, args: array<arg>): declaration<'a> => {
|
||||||
|
{fn: fn, args: args}
|
||||||
|
}
|
||||||
|
|
||||||
|
let toString = (r: declaration<'a>, fnToString): string => {
|
||||||
|
let args = r.args->E.A2.fmap(Arg.toString) |> E.A.joinWith(", ")
|
||||||
|
return`fn: ${fnToString(r.fn)}, args: [${args}]`
|
||||||
|
}
|
|
@ -870,4 +870,5 @@ module Dict = {
|
||||||
type t<'a> = Js.Dict.t<'a>
|
type t<'a> = Js.Dict.t<'a>
|
||||||
let get = Js.Dict.get
|
let get = Js.Dict.get
|
||||||
let keys = Js.Dict.keys
|
let keys = Js.Dict.keys
|
||||||
|
let fromArray = Js.Dict.fromArray
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user