diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.res b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.res index eed48ffc..a0487e80 100644 --- a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.res +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Core.res @@ -10,8 +10,10 @@ type rec frType = | FRTypeDistOrNumber | FRTypeLambda | FRTypeRecord(frTypeRecord) + | FRTypeDict(frType) | FRTypeArray(frType) | FRTypeString + | FRTypeAny | FRTypeVariant(array) and frTypeRecord = array and frTypeRecordParam = (string, frType) @@ -29,8 +31,11 @@ type rec frValue = | FRValueLambda(ReducerInterface_ExpressionValue.lambdaValue) | FRValueString(string) | FRValueVariant(string) + | FRValueAny(frValue) + | FRValueDict(Js.Dict.t) and frValueRecord = array and frValueRecordParam = (string, frValue) +and frValueDictParam = (string, frValue) and frValueDistOrNumber = FRValueNumber(float) | FRValueDist(DistributionTypes.genericDist) type fnDefinition = { @@ -61,10 +66,28 @@ module FRType = { | FRTypeLambda => `lambda` | FRTypeString => `string` | FRTypeVariant(_) => "variant" + | FRTypeDict(r) => `dict(${toString(r)})` + | FRTypeAny => `any` + } + + let rec toFrValue = (r: expressionValue): option => + switch r { + | EvNumber(f) => Some(FRValueNumber(f)) + | EvDistribution(f) => Some(FRValueDistOrNumber(FRValueDist(f))) + | EvLambda(f) => Some(FRValueLambda(f)) + | EvArray(elements) => + elements->E.A2.fmap(toFrValue)->E.A.O.openIfAllSome->E.O2.fmap(r => FRValueArray(r)) + | EvRecord(record) => + Js.Dict.entries(record) + ->E.A2.fmap(((key, item)) => item->toFrValue->E.O2.fmap(o => (key, o))) + ->E.A.O.openIfAllSome + ->E.O2.fmap(r => FRValueRecord(r)) + | _ => None } let rec matchWithExpressionValue = (t: t, r: expressionValue): option => switch (t, r) { + | (FRTypeAny, f) => toFrValue(f) | (FRTypeNumber, EvNumber(f)) => Some(FRValueNumber(f)) | (FRTypeDistOrNumber, EvNumber(f)) => Some(FRValueDistOrNumber(FRValueNumber(f))) | (FRTypeDistOrNumber, EvDistribution(Symbolic(#Float(f)))) => @@ -77,6 +100,11 @@ module FRType = { let el = elements->E.A2.fmap(matchWithExpressionValue(intendedType)) E.A.O.openIfAllSome(el)->E.O2.fmap(r => FRValueArray(r)) } + | (FRTypeDict(r), EvRecord(record)) => record + ->Js.Dict.entries + ->E.A2.fmap(((key, item)) => matchWithExpressionValue(r, item)->E.O2.fmap(o => (key, o))) + ->E.A.O.openIfAllSome + ->E.O2.fmap(r => FRValueDict(Js.Dict.fromArray(r))) | (FRTypeRecord(recordParams), EvRecord(record)) => { let getAndMatch = (name, input) => E.Dict.get(record, name)->E.O.bind(matchWithExpressionValue(input)) @@ -103,9 +131,15 @@ module FRType = { frValueRecord->E.A2.fmap(((name, value)) => (name, matchReverse(value)))->E.Dict.fromArray EvRecord(record) } + | FRValueDict(frValueRecord) => { + let record = + frValueRecord->Js.Dict.entries->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) + | FRValueAny(f) => matchReverse(f) } let matchWithExpressionValueArray = (inputs: array, args: array): option< diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res index a78726e6..29535c05 100644 --- a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res @@ -54,6 +54,13 @@ module Prepare = { } } + let threeNumbers = (values: ts): result<(float, float, float), err> => { + switch values { + | [FRValueNumber(a1), FRValueNumber(a2), FRValueNumber(a3)] => Ok(a1, a2, a3) + | _ => Error(impossibleError) + } + } + let oneDistOrNumber = (values: ts): result => { switch values { | [FRValueDistOrNumber(a1)] => Ok(a1) diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res index 48abbfdb..21d61508 100644 --- a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res @@ -134,38 +134,17 @@ let registry = [ ~name="Bernoulli", ~definitions=[OneArgDist.make("bernoulli", SymbolicDist.Bernoulli.make)], ), - Function.make( - ~name="Floor", - ~definitions=[NumberToNumber.make("floor", Js.Math.floor_float)] - ), - Function.make( - ~name="Ceiling", - ~definitions=[NumberToNumber.make("ceil", Js.Math.ceil_float)] - ), + Function.make(~name="Floor", ~definitions=[NumberToNumber.make("floor", Js.Math.floor_float)]), + Function.make(~name="Ceiling", ~definitions=[NumberToNumber.make("ceil", Js.Math.ceil_float)]), Function.make( ~name="Absolute Value", - ~definitions=[NumberToNumber.make("abs", Js.Math.abs_float)] - ), - Function.make( - ~name="Exponent", - ~definitions=[NumberToNumber.make("exp", Js.Math.exp)] - ), - Function.make( - ~name="Log", - ~definitions=[NumberToNumber.make("log", Js.Math.log)] - ), - Function.make( - ~name="Log Base 10", - ~definitions=[NumberToNumber.make("log10", Js.Math.log10)] - ), - Function.make( - ~name="Log Base 2", - ~definitions=[NumberToNumber.make("log2", Js.Math.log2)] - ), - Function.make( - ~name="Round", - ~definitions=[NumberToNumber.make("round", Js.Math.round)] + ~definitions=[NumberToNumber.make("abs", Js.Math.abs_float)], ), + Function.make(~name="Exponent", ~definitions=[NumberToNumber.make("exp", Js.Math.exp)]), + Function.make(~name="Log", ~definitions=[NumberToNumber.make("log", Js.Math.log)]), + Function.make(~name="Log Base 10", ~definitions=[NumberToNumber.make("log10", Js.Math.log10)]), + Function.make(~name="Log Base 2", ~definitions=[NumberToNumber.make("log2", Js.Math.log2)]), + Function.make(~name="Round", ~definitions=[NumberToNumber.make("round", Js.Math.round)]), Function.make( ~name="Sum", ~definitions=[ArrayNumberDist.make("sum", r => r->E.A.Floats.sum->Wrappers.evNumber)], @@ -214,4 +193,34 @@ let registry = [ ), ], ), + Function.make( + ~name="List.make", + ~definitions=[ + //Todo: If the second item is a function with no args, it could be nice to run this function and return the result. + FnDefinition.make(~name="listMake", ~inputs=[FRTypeNumber, FRTypeAny], ~run=(inputs, _) => { + switch inputs { + | [FRValueNumber(number), value] => + Belt.Array.make(E.Float.toInt(number), value) + ->E.A2.fmap(FunctionRegistry_Core.FRType.matchReverse) + ->Wrappers.evArray + ->Ok + | _ => Error(impossibleError) + } + }), + ], + ), + Function.make( + ~name="Range", + ~definitions=[ + FnDefinition.make(~name="upTo", ~inputs=[FRTypeNumber, FRTypeNumber], ~run=(inputs, _) => + inputs + ->Prepare.ToValueTuple.twoNumbers + ->E.R2.fmap(((low, high)) => + E.A.Floats.range(low, high, (high -. low +. 1.0)->E.Float.toInt) + ->E.A2.fmap(Wrappers.evNumber) + ->Wrappers.evArray + ) + ), + ], + ), ] diff --git a/packages/squiggle-lang/src/rescript/Utility/E.res b/packages/squiggle-lang/src/rescript/Utility/E.res index 06acc25d..7dd1d5f2 100644 --- a/packages/squiggle-lang/src/rescript/Utility/E.res +++ b/packages/squiggle-lang/src/rescript/Utility/E.res @@ -207,6 +207,7 @@ module Float = { let toFixed = Js.Float.toFixed let toString = Js.Float.toString let isFinite = Js.Float.isFinite + let toInt = Belt.Float.toInt } module I = {