Function registry first attempt
This commit is contained in:
parent
833175bce2
commit
e0f4809ad7
113
packages/squiggle-lang/src/rescript/FunctionRegistry.res
Normal file
113
packages/squiggle-lang/src/rescript/FunctionRegistry.res
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
||||||
|
|
||||||
|
type rec itype =
|
||||||
|
I_Number | I_DistOrNumber | I_Record(iRecord) | I_Array(array<itype>) | I_Option(itype)
|
||||||
|
and iRecord = array<iRecordParam>
|
||||||
|
and iRecordParam = (string, itype)
|
||||||
|
|
||||||
|
type rec value =
|
||||||
|
| Number(float)
|
||||||
|
| Dist(DistributionTypes.genericDist)
|
||||||
|
| Option(option<value>)
|
||||||
|
| DistOrNumber(distOrNumber)
|
||||||
|
| Record(record)
|
||||||
|
and record = array<(string, value)>
|
||||||
|
and distOrNumber = Number(float) | Dist(DistributionTypes.genericDist)
|
||||||
|
|
||||||
|
type runFn = array<value> => result<ReducerInterface_ExpressionValue.expressionValue, string>
|
||||||
|
|
||||||
|
type fnDefinition = {name: string, inputs: array<itype>, run: runFn}
|
||||||
|
|
||||||
|
type function = {
|
||||||
|
name: string,
|
||||||
|
definitions: array<fnDefinition>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let rec matchInput = (input: itype, r: expressionValue): option<value> =>
|
||||||
|
switch (input, r) {
|
||||||
|
| (I_Number, EvNumber(f)) => Some(Number(f))
|
||||||
|
| (I_DistOrNumber, EvNumber(f)) => Some(DistOrNumber(Number(f)))
|
||||||
|
| (I_DistOrNumber, EvDistribution(f)) => Some(DistOrNumber(Dist(f)))
|
||||||
|
| (I_Option(v), _) => Some(Option(matchInput(v, r)))
|
||||||
|
| (I_Record(recordParams), EvRecord(record)) => {
|
||||||
|
let getAndMatch = (name, input) =>
|
||||||
|
E.Dict.get(record, name)->E.O.bind(v => matchInput(input, v))
|
||||||
|
let arrayOfNameValues: array<(Js.Dict.key, option<value>)> =
|
||||||
|
recordParams->E.A2.fmap(((name, input)) => (name, getAndMatch(name, input)))
|
||||||
|
let hasNullValues = E.A.hasBy(arrayOfNameValues, ((_, value)) => E.O.isNone(value))
|
||||||
|
if hasNullValues {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
arrayOfNameValues
|
||||||
|
->E.A2.fmap(((name, value)) => (name, value->E.O2.toExn("")))
|
||||||
|
->(r => Some(Record(r)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| _ => None
|
||||||
|
}
|
||||||
|
|
||||||
|
type match = DifferentName | SameNameDifferentArguments(string) | Match(string, array<value>)
|
||||||
|
|
||||||
|
let isFullMatch = (match: match) =>
|
||||||
|
switch match {
|
||||||
|
| Match(_, _) => true
|
||||||
|
| _ => false
|
||||||
|
}
|
||||||
|
|
||||||
|
let isNameMatchOnly = (match: match) =>
|
||||||
|
switch match {
|
||||||
|
| SameNameDifferentArguments(_) => true
|
||||||
|
| _ => false
|
||||||
|
}
|
||||||
|
|
||||||
|
let matchSingle = (f: fnDefinition, fnName: string, args: array<expressionValue>) => {
|
||||||
|
if f.name !== fnName {
|
||||||
|
DifferentName
|
||||||
|
} else {
|
||||||
|
let inputTypes = f.inputs
|
||||||
|
if E.A.length(f.inputs) !== E.A.length(args) {
|
||||||
|
SameNameDifferentArguments(f.name)
|
||||||
|
} else {
|
||||||
|
let foo =
|
||||||
|
E.A.zip(inputTypes, args)
|
||||||
|
->E.A2.fmap(((input, arg)) => matchInput(input, arg))
|
||||||
|
->E.A.O.arrSomeToSomeArr
|
||||||
|
switch foo {
|
||||||
|
| Some(r) => Match(f.name, r)
|
||||||
|
| None => SameNameDifferentArguments(f.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let getByOpen = (a,op,bin) => switch(E.A.getBy(a, r => bin(op(r)))) {
|
||||||
|
| Some(r) => Some(op(r))
|
||||||
|
| None => None
|
||||||
|
}
|
||||||
|
|
||||||
|
let match = (f: function, fnName: string, args: array<expressionValue>) => {
|
||||||
|
let matchedDefinition = E.A.getBy(f.definitions, r => isFullMatch(matchSingle(r, fnName, args)))
|
||||||
|
switch matchedDefinition {
|
||||||
|
| Some(matchedDefinition) => {
|
||||||
|
let match = matchSingle(matchedDefinition, fnName, args)
|
||||||
|
switch match {
|
||||||
|
| Match(a, b) => Ok(Match(a, b))
|
||||||
|
| _ => Error("Should be Impossible")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| None => {
|
||||||
|
let matchedNameDefinition = E.A.getBy(f.definitions, r =>
|
||||||
|
isNameMatchOnly(matchSingle(r, fnName, args))
|
||||||
|
)
|
||||||
|
let foo = switch matchedNameDefinition {
|
||||||
|
| Some(matchedNameDefinition) =>
|
||||||
|
switch matchSingle(matchedNameDefinition, fnName, args) {
|
||||||
|
| SameNameDifferentArguments(r) => Ok(SameNameDifferentArguments(r))
|
||||||
|
| _ => Error("Should be Impossible")
|
||||||
|
}
|
||||||
|
| _ => Ok(DifferentName)
|
||||||
|
}
|
||||||
|
foo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -830,3 +830,9 @@ module JsArray = {
|
||||||
|> Js.Array.map(O.toExn("Warning: This should not have happened"))
|
|> Js.Array.map(O.toExn("Warning: This should not have happened"))
|
||||||
let filter = Js.Array.filter
|
let filter = Js.Array.filter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module Dict = {
|
||||||
|
type t<'a> = Js.Dict.t<'a>
|
||||||
|
let get = Js.Dict.get
|
||||||
|
let keys = Js.Dict.keys
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user