more FR
This commit is contained in:
parent
681a1b42c6
commit
757d458ecf
|
@ -41,8 +41,7 @@ let createProject = (): reducerProject => Private.createProject()
|
|||
Answer all the source ids of all the sources in the project.
|
||||
*/
|
||||
@genType
|
||||
let getSourceIds = (project: reducerProject): array<string> =>
|
||||
project->Private.getSourceIds
|
||||
let getSourceIds = (project: reducerProject): array<string> => project->Private.getSourceIds
|
||||
|
||||
/*
|
||||
Sets the source for a given source Id.
|
||||
|
@ -71,15 +70,13 @@ Cleans the compilation artifacts for a given source ID. The results stay untouch
|
|||
Normally, you would never need the compilation artifacts again as the results with the same sources would never change. However, they are needed in case of any debugging reruns
|
||||
*/
|
||||
@genType
|
||||
let clean = (project: reducerProject, sourceId: string): unit =>
|
||||
project->Private.clean(sourceId)
|
||||
let clean = (project: reducerProject, sourceId: string): unit => project->Private.clean(sourceId)
|
||||
|
||||
/*
|
||||
Cleans all the compilation artifacts in all of the project
|
||||
*/
|
||||
@genType
|
||||
let cleanAll = (project: reducerProject): unit =>
|
||||
project->Private.cleanAll
|
||||
let cleanAll = (project: reducerProject): unit => project->Private.cleanAll
|
||||
|
||||
/*
|
||||
Cleans results. Compilation stays untouched to be able to re-run the source.
|
||||
|
@ -93,8 +90,7 @@ let cleanResults = (project: reducerProject, sourceId: string): unit =>
|
|||
Cleans all results. Compilations remains untouched to rerun the source.
|
||||
*/
|
||||
@genType
|
||||
let cleanAllResults = (project: reducerProject): unit =>
|
||||
project->Private.cleanAllResults
|
||||
let cleanAllResults = (project: reducerProject): unit => project->Private.cleanAllResults
|
||||
|
||||
/*
|
||||
To set the includes one first has to call "parseIncludes". The parsed includes or the parser error is returned.
|
||||
|
@ -144,8 +140,7 @@ let getDependents = (project: reducerProject, sourceId: string): array<string> =
|
|||
Get the run order for the sources in the project.
|
||||
*/
|
||||
@genType
|
||||
let getRunOrder = (project: reducerProject): array<string> =>
|
||||
project->Private.getRunOrder
|
||||
let getRunOrder = (project: reducerProject): array<string> => project->Private.getRunOrder
|
||||
|
||||
/*
|
||||
Get the run order to get the results of this specific source
|
||||
|
@ -177,15 +172,13 @@ let rawParse = (project: reducerProject, sourceId: string): unit =>
|
|||
Runs a specific source code if it is not done already. The code is parsed if it is not already done. It runs the dependencies if it is not already done.
|
||||
*/
|
||||
@genType
|
||||
let run = (project: reducerProject, sourceId: string): unit =>
|
||||
project->Private.run(sourceId)
|
||||
let run = (project: reducerProject, sourceId: string): unit => project->Private.run(sourceId)
|
||||
|
||||
/*
|
||||
Runs all of the sources in a project. Their results and bindings will be available
|
||||
*/
|
||||
@genType
|
||||
let runAll = (project: reducerProject): unit =>
|
||||
project->Private.runAll
|
||||
let runAll = (project: reducerProject): unit => project->Private.runAll
|
||||
|
||||
/*
|
||||
Get the bindings after running this source fil. The bindings are local to the source
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
type internalExpressionValue = Reducer_T.value
|
||||
type internalExpressionValueType = ReducerInterface_InternalExpressionValue.internalExpressionValueType
|
||||
type errorValue = Reducer_ErrorValue.errorValue
|
||||
|
||||
/*
|
||||
Function Registry "Type". A type, without any other information.
|
||||
|
@ -48,7 +49,7 @@ type fnDefinition = {
|
|||
array<frValue>,
|
||||
Reducer_T.environment,
|
||||
Reducer_T.reducerFn,
|
||||
) => result<internalExpressionValue, string>,
|
||||
) => result<internalExpressionValue, errorValue>,
|
||||
}
|
||||
|
||||
type function = {
|
||||
|
@ -206,7 +207,7 @@ module FnDefinition = {
|
|||
let argValues = FRType.matchWithExpressionValueArray(t.inputs, args)
|
||||
switch argValues {
|
||||
| Some(values) => t.run(args, values, env, reducer)
|
||||
| None => Error("Incorrect Types")
|
||||
| None => REOther("Incorrect Types")->Error
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,9 +270,12 @@ module Registry = {
|
|||
let res: fnNameDict = Js.Dict.empty()
|
||||
r->Js.Array2.forEach(fn =>
|
||||
fn.definitions->Js.Array2.forEach(def => {
|
||||
let nameWithNamespace = `${fn.nameSpace}.${def.name}`
|
||||
let nameWithoutNamespace = def.name
|
||||
let names = fn.requiresNamespace ? [nameWithNamespace] : [nameWithNamespace, nameWithoutNamespace]
|
||||
let names =
|
||||
[
|
||||
fn.nameSpace == "" ? [] : [`${fn.nameSpace}.${def.name}`],
|
||||
fn.requiresNamespace ? [] : [def.name],
|
||||
]->E.A.concatMany
|
||||
|
||||
names->Js.Array2.forEach(name => {
|
||||
switch res->Js.Dict.get(name) {
|
||||
| Some(fns) => {
|
||||
|
@ -296,7 +300,7 @@ module Registry = {
|
|||
args: array<internalExpressionValue>,
|
||||
env: Reducer_T.environment,
|
||||
reducer: Reducer_T.reducerFn,
|
||||
): result<internalExpressionValue, Reducer_ErrorValue.errorValue> => {
|
||||
): result<internalExpressionValue, errorValue> => {
|
||||
switch Js.Dict.get(registry.fnNameDict, fnName) {
|
||||
| Some(definitions) => {
|
||||
let showNameMatchDefinitions = () => {
|
||||
|
@ -310,13 +314,12 @@ module Registry = {
|
|||
|
||||
let match = definitions->Js.Array2.find(def => def->FnDefinition.isMatch(args))
|
||||
switch match {
|
||||
| Some(def) => def->FnDefinition.run(args, env, reducer)->E.R2.errMap(e => Reducer_ErrorValue.REOther(e))
|
||||
| None => {
|
||||
Reducer_ErrorValue.REOther(showNameMatchDefinitions())->Error
|
||||
}
|
||||
}
|
||||
}
|
||||
| None => Reducer_ErrorValue.RESymbolNotFound(fnName)->Error
|
||||
| Some(def) =>
|
||||
def->FnDefinition.run(args, env, reducer)
|
||||
| None => REOther(showNameMatchDefinitions())->Error
|
||||
}
|
||||
}
|
||||
| None => RESymbolNotFound(fnName)->Error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
open FunctionRegistry_Core
|
||||
|
||||
let impossibleError = "Wrong inputs / Logically impossible"
|
||||
let impossibleErrorString = "Wrong inputs / Logically impossible"
|
||||
let impossibleError: errorValue = impossibleErrorString->REOther
|
||||
let wrapError = e => Reducer_ErrorValue.REOther(e)
|
||||
|
||||
module Wrappers = {
|
||||
let symbolic = r => DistributionTypes.Symbolic(r)
|
||||
|
@ -15,7 +17,7 @@ module Wrappers = {
|
|||
let evArrayOfEvNumber = xs => xs->Belt.Array.map(evNumber)->evArray
|
||||
}
|
||||
|
||||
let getOrError = (a, g) => E.A.get(a, g) |> E.O.toResult(impossibleError)
|
||||
let getOrError = (a, g) => E.A.get(a, g) |> E.O.toResult(impossibleErrorString)
|
||||
|
||||
module Prepare = {
|
||||
type t = frValue
|
||||
|
@ -27,19 +29,19 @@ module Prepare = {
|
|||
let twoArgs = (inputs: ts): result<ts, err> =>
|
||||
switch inputs {
|
||||
| [FRValueRecord([(_, n1), (_, n2)])] => Ok([n1, n2])
|
||||
| _ => Error(impossibleError)
|
||||
| _ => Error(impossibleErrorString)
|
||||
}
|
||||
|
||||
let threeArgs = (inputs: ts): result<ts, err> =>
|
||||
switch inputs {
|
||||
| [FRValueRecord([(_, n1), (_, n2), (_, n3)])] => Ok([n1, n2, n3])
|
||||
| _ => Error(impossibleError)
|
||||
| _ => Error(impossibleErrorString)
|
||||
}
|
||||
|
||||
let toArgs = (inputs: ts): result<ts, err> =>
|
||||
switch inputs {
|
||||
| [FRValueRecord(args)] => args->E.A2.fmap(((_, b)) => b)->Ok
|
||||
| _ => Error(impossibleError)
|
||||
| _ => Error(impossibleErrorString)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,13 +49,13 @@ module Prepare = {
|
|||
let openA = (inputs: t): result<ts, err> =>
|
||||
switch inputs {
|
||||
| FRValueArray(n) => Ok(n)
|
||||
| _ => Error(impossibleError)
|
||||
| _ => Error(impossibleErrorString)
|
||||
}
|
||||
|
||||
let arrayOfArrays = (inputs: t): result<array<ts>, err> =>
|
||||
switch inputs {
|
||||
| FRValueArray(n) => n->E.A2.fmap(openA)->E.A.R.firstErrorOrOpen
|
||||
| _ => Error(impossibleError)
|
||||
| _ => Error(impossibleErrorString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +64,7 @@ module Prepare = {
|
|||
let twoDistOrNumber = (values: ts): result<(frValueDistOrNumber, frValueDistOrNumber), err> => {
|
||||
switch values {
|
||||
| [FRValueDistOrNumber(a1), FRValueDistOrNumber(a2)] => Ok(a1, a2)
|
||||
| _ => Error(impossibleError)
|
||||
| _ => Error(impossibleErrorString)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,28 +74,28 @@ module Prepare = {
|
|||
> => {
|
||||
switch values {
|
||||
| [FRValueDist(a1), FRValueDist(a2)] => Ok(a1, a2)
|
||||
| _ => Error(impossibleError)
|
||||
| _ => Error(impossibleErrorString)
|
||||
}
|
||||
}
|
||||
|
||||
let twoNumbers = (values: ts): result<(float, float), err> => {
|
||||
switch values {
|
||||
| [FRValueNumber(a1), FRValueNumber(a2)] => Ok(a1, a2)
|
||||
| _ => Error(impossibleError)
|
||||
| _ => Error(impossibleErrorString)
|
||||
}
|
||||
}
|
||||
|
||||
let threeNumbers = (values: ts): result<(float, float, float), err> => {
|
||||
switch values {
|
||||
| [FRValueNumber(a1), FRValueNumber(a2), FRValueNumber(a3)] => Ok(a1, a2, a3)
|
||||
| _ => Error(impossibleError)
|
||||
| _ => Error(impossibleErrorString)
|
||||
}
|
||||
}
|
||||
|
||||
let oneDistOrNumber = (values: ts): result<frValueDistOrNumber, err> => {
|
||||
switch values {
|
||||
| [FRValueDistOrNumber(a1)] => Ok(a1)
|
||||
| _ => Error(impossibleError)
|
||||
| _ => Error(impossibleErrorString)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,14 +126,14 @@ module Prepare = {
|
|||
let oneNumber = (values: t): result<float, err> => {
|
||||
switch values {
|
||||
| FRValueNumber(a1) => Ok(a1)
|
||||
| _ => Error(impossibleError)
|
||||
| _ => Error(impossibleErrorString)
|
||||
}
|
||||
}
|
||||
|
||||
let oneDict = (values: t): result<Js.Dict.t<frValue>, err> => {
|
||||
switch values {
|
||||
| FRValueDict(a1) => Ok(a1)
|
||||
| _ => Error(impossibleError)
|
||||
| _ => Error(impossibleErrorString)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,6 +231,7 @@ module DefineFn = {
|
|||
->E.R.bind(Prepare.oneNumber)
|
||||
->E.R2.fmap(fn)
|
||||
->E.R2.fmap(Wrappers.evNumber)
|
||||
->E.R2.errMap(e => Reducer_ErrorValue.REOther(e))
|
||||
},
|
||||
(),
|
||||
)
|
||||
|
@ -237,7 +240,11 @@ module DefineFn = {
|
|||
~name,
|
||||
~inputs=[FRTypeNumber, FRTypeNumber],
|
||||
~run=(_, inputs, _, _) => {
|
||||
inputs->Prepare.ToValueTuple.twoNumbers->E.R2.fmap(fn)->E.R2.fmap(Wrappers.evNumber)
|
||||
inputs
|
||||
->Prepare.ToValueTuple.twoNumbers
|
||||
->E.R2.fmap(fn)
|
||||
->E.R2.fmap(Wrappers.evNumber)
|
||||
->E.R2.errMap(e => Reducer_ErrorValue.REOther(e))
|
||||
},
|
||||
(),
|
||||
)
|
||||
|
@ -246,7 +253,11 @@ module DefineFn = {
|
|||
~name,
|
||||
~inputs=[FRTypeNumber, FRTypeNumber, FRTypeNumber],
|
||||
~run=(_, inputs, _, _) => {
|
||||
inputs->Prepare.ToValueTuple.threeNumbers->E.R2.fmap(fn)->E.R2.fmap(Wrappers.evNumber)
|
||||
inputs
|
||||
->Prepare.ToValueTuple.threeNumbers
|
||||
->E.R2.fmap(fn)
|
||||
->E.R2.fmap(Wrappers.evNumber)
|
||||
->E.R2.errMap(e => Reducer_ErrorValue.REOther(e))
|
||||
},
|
||||
(),
|
||||
)
|
||||
|
|
|
@ -9,7 +9,14 @@ let fnList = Belt.Array.concatMany([
|
|||
FR_Number.library,
|
||||
FR_Pointset.library,
|
||||
FR_Scoring.library,
|
||||
FR_GenericDist.library,
|
||||
FR_Units.library,
|
||||
])
|
||||
|
||||
let registry = FunctionRegistry_Core.Registry.make(fnList)
|
||||
let call = FunctionRegistry_Core.Registry.call(registry)
|
||||
|
||||
let nonRegistryLambdas: array<(string, Reducer_T.lambdaValue)> = [
|
||||
("mx", FR_GenericDist.mxLambda),
|
||||
("mixture", FR_GenericDist.mxLambda),
|
||||
]
|
||||
|
|
|
@ -1,73 +1,47 @@
|
|||
open FunctionRegistry_Core
|
||||
open FunctionRegistry_Helpers
|
||||
|
||||
let nameSpace = "Builtin"
|
||||
let nameSpace = "" // no namespaced versions
|
||||
|
||||
type simpleDefinition = {
|
||||
inputs: array<frType>,
|
||||
fn: (array<internalExpressionValue>) => result<internalExpressionValue, string>,
|
||||
fn: array<internalExpressionValue> => result<internalExpressionValue, errorValue>,
|
||||
}
|
||||
|
||||
let makeFnMany = (name: string, definitions: array<simpleDefinition>) =>
|
||||
Function.make(
|
||||
~name=name,
|
||||
~name,
|
||||
~nameSpace,
|
||||
~requiresNamespace=false,
|
||||
~definitions=definitions->Js.Array2.map(
|
||||
({ inputs, fn }) => FnDefinition.make(
|
||||
~name=name,
|
||||
~inputs=inputs,
|
||||
~run=(inputs, _, _, _) => fn(inputs),
|
||||
()
|
||||
)
|
||||
~definitions=definitions->Js.Array2.map(({inputs, fn}) =>
|
||||
FnDefinition.make(~name, ~inputs, ~run=(inputs, _, _, _) => fn(inputs), ())
|
||||
),
|
||||
(),
|
||||
)
|
||||
|
||||
let makeFn = (name: string, inputs: array<frType>, fn: (array<internalExpressionValue>) => result<internalExpressionValue, string>) =>
|
||||
makeFnMany(name, [{ inputs, fn }])
|
||||
let makeFn = (
|
||||
name: string,
|
||||
inputs: array<frType>,
|
||||
fn: array<internalExpressionValue> => result<internalExpressionValue, errorValue>,
|
||||
) => makeFnMany(name, [{ inputs, fn }])
|
||||
|
||||
let makeBinaryFn = (name: string, fn: (float, float) => float) => {
|
||||
makeFn(
|
||||
name,
|
||||
[FRTypeNumber, FRTypeNumber],
|
||||
inputs => {
|
||||
switch inputs {
|
||||
| [IEvNumber(x), IEvNumber(y)] => fn(x, y)->IEvNumber->Ok
|
||||
| _ => Error(impossibleError)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
let library = [
|
||||
// TODO - other MathJS
|
||||
Function.make(
|
||||
~name="add",
|
||||
~nameSpace,
|
||||
~requiresNamespace=false,
|
||||
~definitions=[
|
||||
FnDefinition.make(
|
||||
~name="add",
|
||||
~inputs=[FRTypeNumber, FRTypeNumber],
|
||||
~run=(inputs, _, _, _) => {
|
||||
switch inputs {
|
||||
| [IEvNumber(x), IEvNumber(y)] => IEvNumber(x+.y)->Ok
|
||||
| _ => Error(impossibleError)
|
||||
}
|
||||
},
|
||||
()
|
||||
),
|
||||
FnDefinition.make(
|
||||
~name="add",
|
||||
~inputs=[FRTypeNumber, FRTypeNumber],
|
||||
~run=(inputs, _, _, _) => {
|
||||
switch inputs {
|
||||
| [IEvNumber(x), IEvNumber(y)] => IEvNumber(x+.y)->Ok
|
||||
| _ => Error(impossibleError)
|
||||
}
|
||||
},
|
||||
()
|
||||
),
|
||||
FnDefinition.make(
|
||||
~name="add",
|
||||
~inputs=[FRTypeNumber, FRTypeNumber],
|
||||
~run=(inputs, _, _, _) => {
|
||||
switch inputs {
|
||||
| [IEvNumber(x), IEvNumber(y)] => IEvNumber(x+.y)->Ok
|
||||
| _ => Error(impossibleError)
|
||||
}
|
||||
},
|
||||
()
|
||||
),
|
||||
],
|
||||
(),
|
||||
),
|
||||
makeBinaryFn("add", (x, y) => x +. y),
|
||||
makeBinaryFn("subtract", (x, y) => x -. y),
|
||||
makeBinaryFn("multiply", (x, y) => x *. y),
|
||||
makeBinaryFn("divide", (x, y) => x /. y),
|
||||
]
|
||||
|
|
|
@ -71,13 +71,14 @@ module Integration = {
|
|||
aLambda,
|
||||
[pointAsInternalExpression],
|
||||
environment,
|
||||
reducer
|
||||
reducer,
|
||||
)
|
||||
let result = switch resultAsInternalExpression {
|
||||
| Reducer_T.IEvNumber(x) => Ok(x)
|
||||
| _ =>
|
||||
Error(
|
||||
"Error 1 in Danger.integrate. It's possible that your function doesn't return a number, try definining auxiliaryFunction(x) = mean(yourFunction(x)) and integrate auxiliaryFunction instead",
|
||||
"Error 1 in Danger.integrate. It's possible that your function doesn't return a number, try definining auxiliaryFunction(x) = mean(yourFunction(x)) and integrate auxiliaryFunction instead"
|
||||
->Reducer_ErrorValue.REOther
|
||||
)
|
||||
}
|
||||
result
|
||||
|
@ -141,11 +142,11 @@ module Integration = {
|
|||
resultWithOuterPoints
|
||||
}
|
||||
| Error(b) =>
|
||||
Error(
|
||||
(
|
||||
"Integration error 2 in Danger.integrate. It's possible that your function doesn't return a number, try definining auxiliaryFunction(x) = mean(yourFunction(x)) and integrate auxiliaryFunction instead." ++
|
||||
"Original error: " ++
|
||||
b,
|
||||
)
|
||||
b->Reducer_ErrorValue.errorToString
|
||||
)->Reducer_ErrorValue.REOther->Error
|
||||
}
|
||||
result
|
||||
}
|
||||
|
@ -168,7 +169,7 @@ module Integration = {
|
|||
~run=(inputs, _, env, reducer) => {
|
||||
let result = switch inputs {
|
||||
| [_, _, _, IEvNumber(0.0)] =>
|
||||
Error("Integration error 4 in Danger.integrate: Increment can't be 0.")
|
||||
"Integration error 4 in Danger.integrate: Increment can't be 0."->Reducer_ErrorValue.REOther->Error
|
||||
| [
|
||||
IEvLambda(aLambda),
|
||||
IEvNumber(min),
|
||||
|
@ -185,7 +186,7 @@ module Integration = {
|
|||
)
|
||||
| _ =>
|
||||
Error(
|
||||
"Integration error 5 in Danger.integrate. Remember that inputs are (function, number (min), number (max), number(increment))",
|
||||
Reducer_ErrorValue.REOther("Integration error 5 in Danger.integrate. Remember that inputs are (function, number (min), number (max), number(increment))")
|
||||
)
|
||||
}
|
||||
result
|
||||
|
@ -208,7 +209,9 @@ module Integration = {
|
|||
~run=(inputs, _, env, reducer) => {
|
||||
let result = switch inputs {
|
||||
| [_, _, _, IEvNumber(0.0)] =>
|
||||
Error("Integration error in Danger.integrate: Increment can't be 0.")
|
||||
"Integration error in Danger.integrate: Increment can't be 0."
|
||||
->Reducer_ErrorValue.REOther
|
||||
->Error
|
||||
| [IEvLambda(aLambda), IEvNumber(min), IEvNumber(max), IEvNumber(epsilon)] =>
|
||||
Helpers.integrateFunctionBetweenWithNumIntegrationPoints(
|
||||
aLambda,
|
||||
|
@ -218,12 +221,13 @@ module Integration = {
|
|||
env,
|
||||
reducer,
|
||||
)->E.R2.errMap(b =>
|
||||
"Integration error 7 in Danger.integrate. Something went wrong along the way: " ++ b
|
||||
("Integration error 7 in Danger.integrate. Something went wrong along the way: " ++ b->Reducer_ErrorValue.errorToString)
|
||||
->Reducer_ErrorValue.REOther
|
||||
)
|
||||
| _ =>
|
||||
Error(
|
||||
"Integration error 8 in Danger.integrate. Remember that inputs are (function, number (min), number (max), number(increment))",
|
||||
)
|
||||
"Integration error 8 in Danger.integrate. Remember that inputs are (function, number (min), number (max), number(increment))"
|
||||
->Reducer_ErrorValue.REOther
|
||||
->Error
|
||||
}
|
||||
result
|
||||
},
|
||||
|
@ -239,7 +243,7 @@ module DiminishingReturns = {
|
|||
module Helpers = {
|
||||
type diminishingReturnsAccumulatorInner = {
|
||||
optimalAllocations: array<float>,
|
||||
currentMarginalReturns: result<array<float>, string>,
|
||||
currentMarginalReturns: result<array<float>, errorValue>,
|
||||
}
|
||||
let findBiggestElementIndex = xs =>
|
||||
E.A.reducei(xs, 0, (acc, newElement, index) => {
|
||||
|
@ -248,7 +252,7 @@ module DiminishingReturns = {
|
|||
| false => acc
|
||||
}
|
||||
})
|
||||
type diminishingReturnsAccumulator = result<diminishingReturnsAccumulatorInner, string>
|
||||
type diminishingReturnsAccumulator = result<diminishingReturnsAccumulatorInner, errorValue>
|
||||
// TODO: This is so complicated, it probably should be its own file. It might also make sense to have it work in Rescript directly, taking in a function rather than a reducer; then something else can wrap that function in the reducer/lambdas/environment.
|
||||
/*
|
||||
The key idea for this function is that
|
||||
|
@ -273,7 +277,7 @@ module DiminishingReturns = {
|
|||
funds,
|
||||
approximateIncrement,
|
||||
environment,
|
||||
reducer
|
||||
reducer,
|
||||
) => {
|
||||
switch (
|
||||
E.A.length(lambdas) > 1,
|
||||
|
@ -283,19 +287,23 @@ module DiminishingReturns = {
|
|||
) {
|
||||
| (false, _, _, _) =>
|
||||
Error(
|
||||
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, number of functions should be greater than 1.",
|
||||
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, number of functions should be greater than 1."
|
||||
->Reducer_ErrorValue.REOther
|
||||
)
|
||||
| (_, false, _, _) =>
|
||||
Error(
|
||||
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, funds should be greater than 0.",
|
||||
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, funds should be greater than 0."
|
||||
->Reducer_ErrorValue.REOther
|
||||
)
|
||||
| (_, _, false, _) =>
|
||||
Error(
|
||||
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, approximateIncrement should be greater than 0.",
|
||||
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, approximateIncrement should be greater than 0."
|
||||
->Reducer_ErrorValue.REOther
|
||||
)
|
||||
| (_, _, _, false) =>
|
||||
Error(
|
||||
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, approximateIncrement should be smaller than funds amount.",
|
||||
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, approximateIncrement should be smaller than funds amount."
|
||||
->Reducer_ErrorValue.REOther
|
||||
)
|
||||
| (true, true, true, true) => {
|
||||
let applyFunctionAtPoint = (lambda, point: float) => {
|
||||
|
@ -305,13 +313,14 @@ module DiminishingReturns = {
|
|||
lambda,
|
||||
[pointAsInternalExpression],
|
||||
environment,
|
||||
reducer
|
||||
reducer,
|
||||
)
|
||||
switch resultAsInternalExpression {
|
||||
| Reducer_T.IEvNumber(x) => Ok(x)
|
||||
| _ =>
|
||||
Error(
|
||||
"Error 1 in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions. It's possible that your function doesn't return a number, try definining auxiliaryFunction(x) = mean(yourFunction(x)) and integrate auxiliaryFunction instead",
|
||||
"Error 1 in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions. It's possible that your function doesn't return a number, try definining auxiliaryFunction(x) = mean(yourFunction(x)) and integrate auxiliaryFunction instead"
|
||||
->Reducer_ErrorValue.REOther
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -403,9 +412,9 @@ module DiminishingReturns = {
|
|||
switch innerLambda {
|
||||
| Reducer_T.IEvLambda(lambda) => Ok(lambda)
|
||||
| _ =>
|
||||
Error(
|
||||
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions. A member of the array wasn't a function",
|
||||
)
|
||||
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions. A member of the array wasn't a function"
|
||||
->Reducer_ErrorValue.REOther
|
||||
->Error
|
||||
}
|
||||
}, innerlambdas)
|
||||
let wrappedLambdas = E.A.R.firstErrorOrOpen(individuallyWrappedLambdas)
|
||||
|
@ -424,7 +433,7 @@ module DiminishingReturns = {
|
|||
}
|
||||
result
|
||||
}
|
||||
| _ => Error("Error in Danger.diminishingMarginalReturnsForTwoFunctions")
|
||||
| _ => "Error in Danger.diminishingMarginalReturnsForTwoFunctions"->Reducer_ErrorValue.REOther->Error
|
||||
},
|
||||
(),
|
||||
),
|
||||
|
|
|
@ -17,7 +17,7 @@ module Internals = {
|
|||
->E.A2.fmap(((key, value)) => Wrappers.evArray([IEvString(key), value]))
|
||||
->Wrappers.evArray
|
||||
|
||||
let fromList = (items: array<internalExpressionValue>): result<internalExpressionValue, string> =>
|
||||
let fromList = (items: array<internalExpressionValue>): result<internalExpressionValue, errorValue> =>
|
||||
items
|
||||
->E.A2.fmap(item => {
|
||||
switch (item: internalExpressionValue) {
|
||||
|
@ -80,7 +80,8 @@ let library = [
|
|||
->E.R2.fmap(E.Dict.concatMany)
|
||||
->E.R2.fmap(Js.Dict.map((. r) => FunctionRegistry_Core.FRType.matchReverse(r)))
|
||||
->E.R2.fmap(r => r->Js.Dict.entries->Belt.Map.String.fromArray)
|
||||
->E.R2.fmap(Wrappers.evRecord),
|
||||
->E.R2.fmap(Wrappers.evRecord)
|
||||
->E.R2.errMap(e => e->Reducer_ErrorValue.REOther),
|
||||
(),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -16,13 +16,14 @@ module DistributionCreation = {
|
|||
r
|
||||
->E.R.bind(Process.DistOrNumberToDist.twoValuesUsingSymbolicDist(~fn, ~values=_, ~env))
|
||||
->E.R2.fmap(Wrappers.evDistribution)
|
||||
->E.R2.errMap(e => Reducer_ErrorValue.REOther(e))
|
||||
|
||||
let make = (name, fn) => {
|
||||
FnDefinition.make(
|
||||
~name,
|
||||
~inputs=[FRTypeDistOrNumber, FRTypeDistOrNumber],
|
||||
~run=(_, inputs, env, _) =>
|
||||
inputs->Prepare.ToValueTuple.twoDistOrNumber->process(~fn, ~env=env),
|
||||
inputs->Prepare.ToValueTuple.twoDistOrNumber->process(~fn, ~env),
|
||||
(),
|
||||
)
|
||||
}
|
||||
|
@ -32,9 +33,7 @@ module DistributionCreation = {
|
|||
~name,
|
||||
~inputs=[FRTypeRecord([("p5", FRTypeDistOrNumber), ("p95", FRTypeDistOrNumber)])],
|
||||
~run=(_, inputs, env, _) =>
|
||||
inputs
|
||||
->Prepare.ToValueTuple.Record.twoDistOrNumber
|
||||
->process(~fn, ~env=env),
|
||||
inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env),
|
||||
(),
|
||||
)
|
||||
}
|
||||
|
@ -44,9 +43,7 @@ module DistributionCreation = {
|
|||
~name,
|
||||
~inputs=[FRTypeRecord([("mean", FRTypeDistOrNumber), ("stdev", FRTypeDistOrNumber)])],
|
||||
~run=(_, inputs, env, _) =>
|
||||
inputs
|
||||
->Prepare.ToValueTuple.Record.twoDistOrNumber
|
||||
->process(~fn, ~env=env),
|
||||
inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env),
|
||||
(),
|
||||
)
|
||||
}
|
||||
|
@ -57,13 +54,14 @@ module DistributionCreation = {
|
|||
r
|
||||
->E.R.bind(Process.DistOrNumberToDist.oneValueUsingSymbolicDist(~fn, ~value=_, ~env))
|
||||
->E.R2.fmap(Wrappers.evDistribution)
|
||||
->E.R2.errMap(e => Reducer_ErrorValue.REOther(e))
|
||||
|
||||
let make = (name, fn) =>
|
||||
FnDefinition.make(
|
||||
~name,
|
||||
~inputs=[FRTypeDistOrNumber],
|
||||
~run=(_, inputs, env, _) =>
|
||||
inputs->Prepare.ToValueTuple.oneDistOrNumber->process(~fn, ~env=env),
|
||||
inputs->Prepare.ToValueTuple.oneDistOrNumber->process(~fn, ~env),
|
||||
(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -18,12 +18,10 @@ module Declaration = {
|
|||
inputs
|
||||
->E.A2.fmap(getMinMax)
|
||||
->E.A.R.firstErrorOrOpen
|
||||
->E.R2.fmap(args => Reducer_T.IEvDeclaration(
|
||||
Declaration.make(lambda, args),
|
||||
))
|
||||
->E.R2.fmap(args => Reducer_T.IEvDeclaration(Declaration.make(lambda, args)))
|
||||
}
|
||||
| Error(r) => Error(r)
|
||||
| Ok(_) => Error(FunctionRegistry_Helpers.impossibleError)
|
||||
| Ok(_) => Error(impossibleErrorString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +50,7 @@ let library = [
|
|||
~name="declare",
|
||||
~inputs=[Declaration.frType],
|
||||
~run=(_, inputs, _, _) => {
|
||||
inputs->getOrError(0)->E.R.bind(Declaration.fromExpressionValue)
|
||||
inputs->getOrError(0)->E.R.bind(Declaration.fromExpressionValue)->E.R2.errMap(wrapError)
|
||||
},
|
||||
(),
|
||||
),
|
||||
|
|
|
@ -0,0 +1,412 @@
|
|||
open FunctionRegistry_Core
|
||||
|
||||
module Old = {
|
||||
module Helpers = {
|
||||
let arithmeticMap = r =>
|
||||
switch r {
|
||||
| "add" => #Add
|
||||
| "dotAdd" => #Add
|
||||
| "subtract" => #Subtract
|
||||
| "dotSubtract" => #Subtract
|
||||
| "divide" => #Divide
|
||||
| "log" => #Logarithm
|
||||
| "dotDivide" => #Divide
|
||||
| "pow" => #Power
|
||||
| "dotPow" => #Power
|
||||
| "multiply" => #Multiply
|
||||
| "dotMultiply" => #Multiply
|
||||
| _ => #Multiply
|
||||
}
|
||||
|
||||
let catchAndConvertTwoArgsToDists = (args: array<internalExpressionValue>): option<(
|
||||
DistributionTypes.genericDist,
|
||||
DistributionTypes.genericDist,
|
||||
)> =>
|
||||
switch args {
|
||||
| [IEvDistribution(a), IEvDistribution(b)] => Some((a, b))
|
||||
| [IEvNumber(a), IEvDistribution(b)] => Some((GenericDist.fromFloat(a), b))
|
||||
| [IEvDistribution(a), IEvNumber(b)] => Some((a, GenericDist.fromFloat(b)))
|
||||
| _ => None
|
||||
}
|
||||
|
||||
let toFloatFn = (
|
||||
fnCall: DistributionTypes.DistributionOperation.toFloat,
|
||||
dist: DistributionTypes.genericDist,
|
||||
~env: GenericDist.env,
|
||||
) => {
|
||||
FromDist(#ToFloat(fnCall), dist)->DistributionOperation.run(~env)->Some
|
||||
}
|
||||
|
||||
let toStringFn = (
|
||||
fnCall: DistributionTypes.DistributionOperation.toString,
|
||||
dist: DistributionTypes.genericDist,
|
||||
~env: GenericDist.env,
|
||||
) => {
|
||||
FromDist(#ToString(fnCall), dist)->DistributionOperation.run(~env)->Some
|
||||
}
|
||||
|
||||
let toBoolFn = (
|
||||
fnCall: DistributionTypes.DistributionOperation.toBool,
|
||||
dist: DistributionTypes.genericDist,
|
||||
~env: GenericDist.env,
|
||||
) => {
|
||||
FromDist(#ToBool(fnCall), dist)->DistributionOperation.run(~env)->Some
|
||||
}
|
||||
|
||||
let toDistFn = (
|
||||
fnCall: DistributionTypes.DistributionOperation.toDist,
|
||||
dist,
|
||||
~env: GenericDist.env,
|
||||
) => {
|
||||
FromDist(#ToDist(fnCall), dist)->DistributionOperation.run(~env)->Some
|
||||
}
|
||||
|
||||
let twoDiststoDistFn = (direction, arithmetic, dist1, dist2, ~env: GenericDist.env) => {
|
||||
FromDist(
|
||||
#ToDistCombination(direction, arithmeticMap(arithmetic), #Dist(dist2)),
|
||||
dist1,
|
||||
)->DistributionOperation.run(~env)
|
||||
}
|
||||
|
||||
let parseNumber = (args: internalExpressionValue): Belt.Result.t<float, string> =>
|
||||
switch args {
|
||||
| IEvNumber(x) => Ok(x)
|
||||
| _ => Error("Not a number")
|
||||
}
|
||||
|
||||
let parseNumberArray = (ags: array<internalExpressionValue>): Belt.Result.t<
|
||||
array<float>,
|
||||
string,
|
||||
> => E.A.fmap(parseNumber, ags) |> E.A.R.firstErrorOrOpen
|
||||
|
||||
let parseDist = (args: internalExpressionValue): Belt.Result.t<
|
||||
DistributionTypes.genericDist,
|
||||
string,
|
||||
> =>
|
||||
switch args {
|
||||
| IEvDistribution(x) => Ok(x)
|
||||
| IEvNumber(x) => Ok(GenericDist.fromFloat(x))
|
||||
| _ => Error("Not a distribution")
|
||||
}
|
||||
|
||||
let parseDistributionArray = (ags: array<internalExpressionValue>): Belt.Result.t<
|
||||
array<DistributionTypes.genericDist>,
|
||||
string,
|
||||
> => E.A.fmap(parseDist, ags) |> E.A.R.firstErrorOrOpen
|
||||
|
||||
let mixtureWithGivenWeights = (
|
||||
distributions: array<DistributionTypes.genericDist>,
|
||||
weights: array<float>,
|
||||
~env: GenericDist.env,
|
||||
): DistributionOperation.outputType =>
|
||||
E.A.length(distributions) == E.A.length(weights)
|
||||
? Mixture(Belt.Array.zip(distributions, weights))->DistributionOperation.run(~env)
|
||||
: GenDistError(
|
||||
ArgumentError("Error, mixture call has different number of distributions and weights"),
|
||||
)
|
||||
|
||||
let mixtureWithDefaultWeights = (
|
||||
distributions: array<DistributionTypes.genericDist>,
|
||||
~env: GenericDist.env,
|
||||
): DistributionOperation.outputType => {
|
||||
let length = E.A.length(distributions)
|
||||
let weights = Belt.Array.make(length, 1.0 /. Belt.Int.toFloat(length))
|
||||
mixtureWithGivenWeights(distributions, weights, ~env)
|
||||
}
|
||||
|
||||
let mixture = (
|
||||
args: array<internalExpressionValue>,
|
||||
~env: GenericDist.env,
|
||||
): DistributionOperation.outputType => {
|
||||
let error = (err: string): DistributionOperation.outputType =>
|
||||
err->DistributionTypes.ArgumentError->GenDistError
|
||||
switch args {
|
||||
| [IEvArray(distributions)] =>
|
||||
switch parseDistributionArray(distributions) {
|
||||
| Ok(distrs) => mixtureWithDefaultWeights(distrs, ~env)
|
||||
| Error(err) => error(err)
|
||||
}
|
||||
| [IEvArray(distributions), IEvArray(weights)] =>
|
||||
switch (parseDistributionArray(distributions), parseNumberArray(weights)) {
|
||||
| (Ok(distrs), Ok(wghts)) => mixtureWithGivenWeights(distrs, wghts, ~env)
|
||||
| (Error(err), Ok(_)) => error(err)
|
||||
| (Ok(_), Error(err)) => error(err)
|
||||
| (Error(err1), Error(err2)) => error(`${err1}|${err2}`)
|
||||
}
|
||||
| _ =>
|
||||
switch E.A.last(args) {
|
||||
| Some(IEvArray(b)) => {
|
||||
let weights = parseNumberArray(b)
|
||||
let distributions = parseDistributionArray(
|
||||
Belt.Array.slice(args, ~offset=0, ~len=E.A.length(args) - 1),
|
||||
)
|
||||
switch E.R.merge(distributions, weights) {
|
||||
| Ok(d, w) => mixtureWithGivenWeights(d, w, ~env)
|
||||
| Error(err) => error(err)
|
||||
}
|
||||
}
|
||||
| Some(IEvNumber(_))
|
||||
| Some(IEvDistribution(_)) =>
|
||||
switch parseDistributionArray(args) {
|
||||
| Ok(distributions) => mixtureWithDefaultWeights(distributions, ~env)
|
||||
| Error(err) => error(err)
|
||||
}
|
||||
| _ => error("Last argument of mx must be array or distribution")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module SymbolicConstructors = {
|
||||
let threeFloat = name =>
|
||||
switch name {
|
||||
| "triangular" => Ok(SymbolicDist.Triangular.make)
|
||||
| _ => Error("Unreachable state")
|
||||
}
|
||||
|
||||
let symbolicResultToOutput = (
|
||||
symbolicResult: result<SymbolicDistTypes.symbolicDist, string>,
|
||||
): option<DistributionOperation.outputType> =>
|
||||
switch symbolicResult {
|
||||
| Ok(r) => Some(Dist(Symbolic(r)))
|
||||
| Error(r) => Some(GenDistError(OtherError(r)))
|
||||
}
|
||||
}
|
||||
|
||||
let dispatchToGenericOutput = (
|
||||
call: ReducerInterface_InternalExpressionValue.functionCall,
|
||||
env: GenericDist.env,
|
||||
): option<DistributionOperation.outputType> => {
|
||||
let (fnName, args) = call
|
||||
switch (fnName, args) {
|
||||
| ("triangular" as fnName, [IEvNumber(f1), IEvNumber(f2), IEvNumber(f3)]) =>
|
||||
SymbolicConstructors.threeFloat(fnName)
|
||||
->E.R.bind(r => r(f1, f2, f3))
|
||||
->SymbolicConstructors.symbolicResultToOutput
|
||||
| ("sample", [IEvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist, ~env)
|
||||
| ("sampleN", [IEvDistribution(dist), IEvNumber(n)]) =>
|
||||
Some(FloatArray(GenericDist.sampleN(dist, Belt.Int.fromFloat(n))))
|
||||
| (("mean" | "stdev" | "variance" | "min" | "max" | "mode") as op, [IEvDistribution(dist)]) => {
|
||||
let fn = switch op {
|
||||
| "mean" => #Mean
|
||||
| "stdev" => #Stdev
|
||||
| "variance" => #Variance
|
||||
| "min" => #Min
|
||||
| "max" => #Max
|
||||
| "mode" => #Mode
|
||||
| _ => #Mean
|
||||
}
|
||||
Helpers.toFloatFn(fn, dist, ~env)
|
||||
}
|
||||
| ("integralSum", [IEvDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist, ~env)
|
||||
| ("toString", [IEvDistribution(dist)]) => Helpers.toStringFn(ToString, dist, ~env)
|
||||
| ("sparkline", [IEvDistribution(dist)]) =>
|
||||
Helpers.toStringFn(ToSparkline(MagicNumbers.Environment.sparklineLength), dist, ~env)
|
||||
| ("sparkline", [IEvDistribution(dist), IEvNumber(n)]) =>
|
||||
Helpers.toStringFn(ToSparkline(Belt.Float.toInt(n)), dist, ~env)
|
||||
| ("exp", [IEvDistribution(a)]) =>
|
||||
// https://mathjs.org/docs/reference/functions/exp.html
|
||||
Helpers.twoDiststoDistFn(
|
||||
Algebraic(AsDefault),
|
||||
"pow",
|
||||
GenericDist.fromFloat(MagicNumbers.Math.e),
|
||||
a,
|
||||
~env,
|
||||
)->Some
|
||||
| ("normalize", [IEvDistribution(dist)]) => Helpers.toDistFn(Normalize, dist, ~env)
|
||||
| ("isNormalized", [IEvDistribution(dist)]) => Helpers.toBoolFn(IsNormalized, dist, ~env)
|
||||
| ("toPointSet", [IEvDistribution(dist)]) => Helpers.toDistFn(ToPointSet, dist, ~env)
|
||||
| ("scaleLog", [IEvDistribution(dist)]) =>
|
||||
Helpers.toDistFn(Scale(#Logarithm, MagicNumbers.Math.e), dist, ~env)
|
||||
| ("scaleLog10", [IEvDistribution(dist)]) =>
|
||||
Helpers.toDistFn(Scale(#Logarithm, 10.0), dist, ~env)
|
||||
| ("scaleLog", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||
Helpers.toDistFn(Scale(#Logarithm, float), dist, ~env)
|
||||
| ("scaleLogWithThreshold", [IEvDistribution(dist), IEvNumber(base), IEvNumber(eps)]) =>
|
||||
Helpers.toDistFn(Scale(#LogarithmWithThreshold(eps), base), dist, ~env)
|
||||
| ("scaleMultiply", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||
Helpers.toDistFn(Scale(#Multiply, float), dist, ~env)
|
||||
| ("scalePow", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||
Helpers.toDistFn(Scale(#Power, float), dist, ~env)
|
||||
| ("scaleExp", [IEvDistribution(dist)]) =>
|
||||
Helpers.toDistFn(Scale(#Power, MagicNumbers.Math.e), dist, ~env)
|
||||
| ("cdf", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||
Helpers.toFloatFn(#Cdf(float), dist, ~env)
|
||||
| ("pdf", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||
Helpers.toFloatFn(#Pdf(float), dist, ~env)
|
||||
| ("inv", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||
Helpers.toFloatFn(#Inv(float), dist, ~env)
|
||||
| ("quantile", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||
Helpers.toFloatFn(#Inv(float), dist, ~env)
|
||||
| ("inspect", [IEvDistribution(dist)]) => Helpers.toDistFn(Inspect, dist, ~env)
|
||||
| ("truncateLeft", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||
Helpers.toDistFn(Truncate(Some(float), None), dist, ~env)
|
||||
| ("truncateRight", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||
Helpers.toDistFn(Truncate(None, Some(float)), dist, ~env)
|
||||
| ("truncate", [IEvDistribution(dist), IEvNumber(float1), IEvNumber(float2)]) =>
|
||||
Helpers.toDistFn(Truncate(Some(float1), Some(float2)), dist, ~env)
|
||||
| ("mx" | "mixture", args) => Helpers.mixture(args, ~env)->Some
|
||||
| ("log", [IEvDistribution(a)]) =>
|
||||
Helpers.twoDiststoDistFn(
|
||||
Algebraic(AsDefault),
|
||||
"log",
|
||||
a,
|
||||
GenericDist.fromFloat(MagicNumbers.Math.e),
|
||||
~env,
|
||||
)->Some
|
||||
| ("log10", [IEvDistribution(a)]) =>
|
||||
Helpers.twoDiststoDistFn(
|
||||
Algebraic(AsDefault),
|
||||
"log",
|
||||
a,
|
||||
GenericDist.fromFloat(10.0),
|
||||
~env,
|
||||
)->Some
|
||||
| ("unaryMinus", [IEvDistribution(a)]) =>
|
||||
Helpers.twoDiststoDistFn(
|
||||
Algebraic(AsDefault),
|
||||
"multiply",
|
||||
a,
|
||||
GenericDist.fromFloat(-1.0),
|
||||
~env,
|
||||
)->Some
|
||||
| (
|
||||
("add" | "multiply" | "subtract" | "divide" | "pow" | "log") as arithmetic,
|
||||
[_, _] as args,
|
||||
) =>
|
||||
Helpers.catchAndConvertTwoArgsToDists(args)->E.O2.fmap(((fst, snd)) =>
|
||||
Helpers.twoDiststoDistFn(Algebraic(AsDefault), arithmetic, fst, snd, ~env)
|
||||
)
|
||||
| (
|
||||
("dotAdd"
|
||||
| "dotMultiply"
|
||||
| "dotSubtract"
|
||||
| "dotDivide"
|
||||
| "dotPow") as arithmetic,
|
||||
[_, _] as args,
|
||||
) =>
|
||||
Helpers.catchAndConvertTwoArgsToDists(args)->E.O2.fmap(((fst, snd)) =>
|
||||
Helpers.twoDiststoDistFn(Pointwise, arithmetic, fst, snd, ~env)
|
||||
)
|
||||
| ("dotExp", [IEvDistribution(a)]) =>
|
||||
Helpers.twoDiststoDistFn(
|
||||
Pointwise,
|
||||
"dotPow",
|
||||
GenericDist.fromFloat(MagicNumbers.Math.e),
|
||||
a,
|
||||
~env,
|
||||
)->Some
|
||||
| _ => None
|
||||
}
|
||||
}
|
||||
|
||||
let genericOutputToReducerValue = (o: DistributionOperation.outputType): result<
|
||||
internalExpressionValue,
|
||||
Reducer_ErrorValue.errorValue,
|
||||
> =>
|
||||
switch o {
|
||||
| Dist(d) => Ok(Reducer_T.IEvDistribution(d))
|
||||
| Float(d) => Ok(IEvNumber(d))
|
||||
| String(d) => Ok(IEvString(d))
|
||||
| Bool(d) => Ok(IEvBool(d))
|
||||
| FloatArray(d) => Ok(IEvArray(d |> E.A.fmap(r => Reducer_T.IEvNumber(r))))
|
||||
// // FIXME - can't propagate error objects through FunctionRegistry
|
||||
// | GenDistError(err) => Error(REDistributionError(err))
|
||||
| GenDistError(err) => Error(REDistributionError(err))
|
||||
}
|
||||
|
||||
let dispatch = (call: ReducerInterface_InternalExpressionValue.functionCall, environment) =>
|
||||
switch dispatchToGenericOutput(call, environment) {
|
||||
| Some(o) => genericOutputToReducerValue(o)
|
||||
| None => Reducer_ErrorValue.REOther("Internal error in FR_GenericDist implementation")
|
||||
->Reducer_ErrorValue.ErrorException
|
||||
->raise
|
||||
}
|
||||
}
|
||||
|
||||
let makeProxyFn = (name: string, inputs: array<frType>) => {
|
||||
Function.make(
|
||||
~name,
|
||||
~nameSpace="",
|
||||
~requiresNamespace=false,
|
||||
~definitions=[
|
||||
FnDefinition.make(
|
||||
~name,
|
||||
~inputs,
|
||||
~run=(inputs, _, env, _) => Old.dispatch((name, inputs), env),
|
||||
(),
|
||||
),
|
||||
],
|
||||
(),
|
||||
)
|
||||
}
|
||||
|
||||
let makeOperationFns = (): array<function> => {
|
||||
let ops = ["add", "multiply", "subtract", "divide", "pow", "log", "dotAdd", "dotMultiply", "dotSubtract", "dotDivide", "dotPow"]
|
||||
let twoArgTypes = [
|
||||
// can't use numeric+numeric, since number+number should be delegated to builtin arithmetics
|
||||
[FRTypeDist, FRTypeNumber],
|
||||
[FRTypeNumber, FRTypeDist],
|
||||
[FRTypeDist, FRTypeDist],
|
||||
]
|
||||
|
||||
ops->E.A2.fmap(
|
||||
op => twoArgTypes->E.A2.fmap(
|
||||
types => makeProxyFn(op, types)
|
||||
)
|
||||
)->E.A.concatMany
|
||||
}
|
||||
|
||||
// TODO - duplicates the switch above, should rewrite with standard FR APIs
|
||||
let library = E.A.concatMany([
|
||||
[
|
||||
makeProxyFn("triangular", [FRTypeNumber, FRTypeNumber, FRTypeNumber]),
|
||||
makeProxyFn("sample", [FRTypeDist]),
|
||||
makeProxyFn("sampleN", [FRTypeDist, FRTypeNumber]),
|
||||
makeProxyFn("mean", [FRTypeDist]),
|
||||
makeProxyFn("stdev", [FRTypeDist]),
|
||||
makeProxyFn("variance", [FRTypeDist]),
|
||||
makeProxyFn("min", [FRTypeDist]),
|
||||
makeProxyFn("max", [FRTypeDist]),
|
||||
makeProxyFn("mode", [FRTypeDist]),
|
||||
makeProxyFn("integralSum", [FRTypeDist]),
|
||||
// // FIXME: doesn't work with Js.Dict in FunctionRegistry_Core
|
||||
// makeProxyFn("toString", [FRTypeDist]),
|
||||
makeProxyFn("sparkline", [FRTypeDist]),
|
||||
makeProxyFn("sparkline", [FRTypeDist, FRTypeNumber]),
|
||||
makeProxyFn("exp", [FRTypeDist]),
|
||||
makeProxyFn("normalize", [FRTypeDist]),
|
||||
makeProxyFn("isNormalized", [FRTypeDist]),
|
||||
makeProxyFn("toPointSet", [FRTypeDist]),
|
||||
makeProxyFn("scaleLog", [FRTypeDist]),
|
||||
makeProxyFn("scaleLog10", [FRTypeDist]),
|
||||
makeProxyFn("scaleLog", [FRTypeDist, FRTypeNumber]),
|
||||
makeProxyFn("scaleLogWithThreshold", [FRTypeDist, FRTypeNumber, FRTypeNumber]),
|
||||
makeProxyFn("scaleMultiply", [FRTypeDist, FRTypeNumber]),
|
||||
makeProxyFn("scalePow", [FRTypeDist, FRTypeNumber]),
|
||||
makeProxyFn("scaleExp", [FRTypeDist]),
|
||||
makeProxyFn("cdf", [FRTypeDist, FRTypeNumber]),
|
||||
makeProxyFn("pdf", [FRTypeDist, FRTypeNumber]),
|
||||
makeProxyFn("inv", [FRTypeDist, FRTypeNumber]),
|
||||
makeProxyFn("quantile", [FRTypeDist, FRTypeNumber]),
|
||||
makeProxyFn("inspect", [FRTypeDist]),
|
||||
makeProxyFn("truncateLeft", [FRTypeDist, FRTypeNumber]),
|
||||
makeProxyFn("truncateRight", [FRTypeDist, FRTypeNumber]),
|
||||
makeProxyFn("truncate", [FRTypeDist, FRTypeNumber, FRTypeNumber]),
|
||||
// // FIXME - impossible to implement with FR!!!
|
||||
// | ("mx" | "mixture", args) => Helpers.mixture(args, ~env)->Some
|
||||
makeProxyFn("log", [FRTypeDist]),
|
||||
makeProxyFn("log10", [FRTypeDist]),
|
||||
makeProxyFn("unaryMinus", [FRTypeDist]),
|
||||
makeProxyFn("dotExp", [FRTypeDist]),
|
||||
],
|
||||
makeOperationFns()
|
||||
])
|
||||
|
||||
// FIXME - impossible to implement with FR due to arbitrary parameters length;
|
||||
let mxLambda = Reducer_Expression_Lambda.makeFFILambda((inputs, env, _) => {
|
||||
switch Old.dispatch(("mx", inputs), env) {
|
||||
| Ok(value) => value
|
||||
| Error(e) => e->Reducer_ErrorValue.ErrorException->raise
|
||||
}
|
||||
})
|
|
@ -28,15 +28,10 @@ module Internals = {
|
|||
array: array<internalExpressionValue>,
|
||||
eLambdaValue,
|
||||
env: Reducer_T.environment,
|
||||
reducer: Reducer_T.reducerFn
|
||||
reducer: Reducer_T.reducerFn,
|
||||
): internalExpressionValue => {
|
||||
let mappedList = array->E.A.reduceReverse(list{}, (acc, elem) => {
|
||||
let newElem = Reducer_Expression_Lambda.doLambdaCall(
|
||||
eLambdaValue,
|
||||
[elem],
|
||||
env,
|
||||
reducer
|
||||
)
|
||||
let newElem = Reducer_Expression_Lambda.doLambdaCall(eLambdaValue, [elem], env, reducer)
|
||||
list{newElem, ...acc}
|
||||
})
|
||||
mappedList->Belt.List.toArray->Wrappers.evArray
|
||||
|
@ -47,7 +42,7 @@ module Internals = {
|
|||
initialValue,
|
||||
aLambdaValue,
|
||||
env: Reducer_T.environment,
|
||||
reducer: Reducer_T.reducerFn
|
||||
reducer: Reducer_T.reducerFn,
|
||||
) => {
|
||||
aValueArray->E.A.reduce(initialValue, (acc, elem) =>
|
||||
Reducer_Expression_Lambda.doLambdaCall(aLambdaValue, [acc, elem], env, reducer)
|
||||
|
@ -59,7 +54,7 @@ module Internals = {
|
|||
initialValue,
|
||||
aLambdaValue,
|
||||
env: Reducer_T.environment,
|
||||
reducer: Reducer_T.reducerFn
|
||||
reducer: Reducer_T.reducerFn,
|
||||
) => {
|
||||
aValueArray->Belt.Array.reduceReverse(initialValue, (acc, elem) =>
|
||||
Reducer_Expression_Lambda.doLambdaCall(aLambdaValue, [acc, elem], env, reducer)
|
||||
|
@ -70,15 +65,10 @@ module Internals = {
|
|||
aValueArray,
|
||||
aLambdaValue,
|
||||
env: Reducer_T.environment,
|
||||
reducer: Reducer_T.reducerFn
|
||||
reducer: Reducer_T.reducerFn,
|
||||
) => {
|
||||
let mappedList = aValueArray->Belt.Array.reduceReverse(list{}, (acc, elem) => {
|
||||
let newElem = Reducer_Expression_Lambda.doLambdaCall(
|
||||
aLambdaValue,
|
||||
[elem],
|
||||
env,
|
||||
reducer
|
||||
)
|
||||
let newElem = Reducer_Expression_Lambda.doLambdaCall(aLambdaValue, [elem], env, reducer)
|
||||
switch newElem {
|
||||
| IEvBool(true) => list{elem, ...acc}
|
||||
| _ => acc
|
||||
|
@ -124,7 +114,8 @@ let library = [
|
|||
~run=(_, inputs, _, _) =>
|
||||
inputs
|
||||
->Prepare.ToValueTuple.twoNumbers
|
||||
->E.R2.fmap(((low, high)) => Internals.upTo(low, high)),
|
||||
->E.R2.fmap(((low, high)) => Internals.upTo(low, high))
|
||||
->E.R2.errMap(wrapError),
|
||||
(),
|
||||
),
|
||||
],
|
||||
|
@ -141,7 +132,7 @@ let library = [
|
|||
~inputs=[FRTypeArray(FRTypeAny)],
|
||||
~run=(inputs, _, _, _) =>
|
||||
switch inputs {
|
||||
| [IEvArray(array)] => Internals.first(array)
|
||||
| [IEvArray(array)] => Internals.first(array)->E.R2.errMap(wrapError)
|
||||
| _ => Error(impossibleError)
|
||||
},
|
||||
(),
|
||||
|
@ -160,7 +151,7 @@ let library = [
|
|||
~inputs=[FRTypeArray(FRTypeAny)],
|
||||
~run=(inputs, _, _, _) =>
|
||||
switch inputs {
|
||||
| [IEvArray(array)] => Internals.last(array)
|
||||
| [IEvArray(array)] => Internals.last(array)->E.R2.errMap(wrapError)
|
||||
| _ => Error(impossibleError)
|
||||
},
|
||||
(),
|
||||
|
@ -200,8 +191,7 @@ let library = [
|
|||
~inputs=[FRTypeArray(FRTypeAny), FRTypeLambda],
|
||||
~run=(inputs, _, env, reducer) =>
|
||||
switch inputs {
|
||||
| [IEvArray(array), IEvLambda(lambda)] =>
|
||||
Ok(Internals.map(array, lambda, env, reducer))
|
||||
| [IEvArray(array), IEvLambda(lambda)] => Ok(Internals.map(array, lambda, env, reducer))
|
||||
| _ => Error(impossibleError)
|
||||
},
|
||||
(),
|
||||
|
|
|
@ -12,7 +12,8 @@ module ArrayNumberDist = {
|
|||
~run=(_, inputs, _, _) =>
|
||||
Prepare.ToTypedArray.numbers(inputs)
|
||||
->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r))
|
||||
->E.R.bind(fn),
|
||||
->E.R.bind(fn)
|
||||
->E.R2.errMap(wrapError),
|
||||
(),
|
||||
)
|
||||
}
|
||||
|
@ -23,7 +24,8 @@ module ArrayNumberDist = {
|
|||
~run=(_, inputs, _, _) =>
|
||||
Prepare.ToTypedArray.numbers(inputs)
|
||||
->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r))
|
||||
->E.R.bind(fn),
|
||||
->E.R.bind(fn)
|
||||
->E.R2.errMap(wrapError),
|
||||
(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -17,19 +17,14 @@ let inputsTodist = (inputs: array<FunctionRegistry_Core.frValue>, makeDist) => {
|
|||
let expressionValue =
|
||||
xyCoords
|
||||
->E.R.bind(r => r->XYShape.T.makeFromZipped->E.R2.errMap(XYShape.Error.toString))
|
||||
->E.R2.fmap(r => Reducer_T.IEvDistribution(
|
||||
PointSet(makeDist(r)),
|
||||
))
|
||||
->E.R2.fmap(r => Reducer_T.IEvDistribution(PointSet(makeDist(r))))
|
||||
expressionValue
|
||||
}
|
||||
|
||||
module Internal = {
|
||||
type t = PointSetDist.t
|
||||
|
||||
let toType = (r): result<
|
||||
Reducer_T.value,
|
||||
Reducer_ErrorValue.errorValue,
|
||||
> =>
|
||||
let toType = (r): result<Reducer_T.value, Reducer_ErrorValue.errorValue> =>
|
||||
switch r {
|
||||
| Ok(r) => Ok(Wrappers.evDistribution(PointSet(r)))
|
||||
| Error(err) => Error(REOperationError(err))
|
||||
|
@ -69,7 +64,7 @@ let library = [
|
|||
)
|
||||
->E.R2.fmap(Wrappers.pointSet)
|
||||
->E.R2.fmap(Wrappers.evDistribution)
|
||||
->E.R2.errMap(_ => "")
|
||||
->E.R2.errMap(e => Reducer_ErrorValue.REDistributionError(e))
|
||||
| _ => Error(impossibleError)
|
||||
},
|
||||
(),
|
||||
|
@ -90,7 +85,7 @@ let library = [
|
|||
~run=(inputs, _, env, reducer) =>
|
||||
switch inputs {
|
||||
| [IEvDistribution(PointSet(dist)), IEvLambda(lambda)] =>
|
||||
Internal.mapY(dist, lambda, env, reducer)->E.R2.errMap(Reducer_ErrorValue.errorToString)
|
||||
Internal.mapY(dist, lambda, env, reducer)
|
||||
| _ => Error(impossibleError)
|
||||
},
|
||||
(),
|
||||
|
@ -115,7 +110,9 @@ let library = [
|
|||
FnDefinition.make(
|
||||
~name="makeContinuous",
|
||||
~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))],
|
||||
~run=(_, inputs, _, _) => inputsTodist(inputs, r => Continuous(Continuous.make(r))),
|
||||
~run=(_, inputs, _, _) =>
|
||||
inputsTodist(inputs, r => Continuous(Continuous.make(r)))
|
||||
->E.R2.errMap(wrapError),
|
||||
(),
|
||||
),
|
||||
],
|
||||
|
@ -138,7 +135,9 @@ let library = [
|
|||
FnDefinition.make(
|
||||
~name="makeDiscrete",
|
||||
~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))],
|
||||
~run=(_, inputs, _, _) => inputsTodist(inputs, r => Discrete(Discrete.make(r))),
|
||||
~run=(_, inputs, _, _) =>
|
||||
inputsTodist(inputs, r => Discrete(Discrete.make(r)))
|
||||
->E.R2.errMap(wrapError),
|
||||
(),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -18,10 +18,7 @@ module Internal = {
|
|||
| _ => Error(Operation.SampleMapNeedsNtoNFunction)
|
||||
}
|
||||
|
||||
let toType = (r): result<
|
||||
Reducer_T.value,
|
||||
Reducer_ErrorValue.errorValue,
|
||||
> =>
|
||||
let toType = (r): result<Reducer_T.value, Reducer_ErrorValue.errorValue> =>
|
||||
switch r {
|
||||
| Ok(r) => Ok(Wrappers.evDistribution(SampleSet(r)))
|
||||
| Error(r) => Error(REDistributionError(SampleSetError(r)))
|
||||
|
@ -100,7 +97,7 @@ let libaryBase = [
|
|||
GenericDist.toSampleSetDist(dist, environment.sampleCount)
|
||||
->E.R2.fmap(Wrappers.sampleSet)
|
||||
->E.R2.fmap(Wrappers.evDistribution)
|
||||
->E.R2.errMap(DistributionTypes.Error.toString)
|
||||
->E.R2.errMap(e => Reducer_ErrorValue.REDistributionError(e))
|
||||
| _ => Error(impossibleError)
|
||||
},
|
||||
(),
|
||||
|
@ -123,7 +120,9 @@ let libaryBase = [
|
|||
Prepare.ToTypedArray.numbers(inputs) |> E.R2.bind(r =>
|
||||
SampleSetDist.make(r)->E.R2.errMap(_ => "AM I HERE? WHYERE AMI??")
|
||||
)
|
||||
sampleSet->E.R2.fmap(Wrappers.sampleSet)->E.R2.fmap(Wrappers.evDistribution)
|
||||
sampleSet->E.R2.fmap(Wrappers.sampleSet)
|
||||
->E.R2.fmap(Wrappers.evDistribution)
|
||||
->E.R2.errMap(wrapError)
|
||||
},
|
||||
(),
|
||||
),
|
||||
|
@ -166,7 +165,7 @@ let libaryBase = [
|
|||
| [IEvLambda(lambda)] =>
|
||||
switch Internal.fromFn(lambda, environment, reducer) {
|
||||
| Ok(r) => Ok(r->Wrappers.sampleSet->Wrappers.evDistribution)
|
||||
| Error(e) => Error(Operation.Error.toString(e))
|
||||
| Error(e) => e->Reducer_ErrorValue.REOperationError->Error
|
||||
}
|
||||
| _ => Error(impossibleError)
|
||||
},
|
||||
|
@ -188,7 +187,7 @@ let libaryBase = [
|
|||
~run=(inputs, _, environment, reducer) =>
|
||||
switch inputs {
|
||||
| [IEvDistribution(SampleSet(dist)), IEvLambda(lambda)] =>
|
||||
Internal.map1(dist, lambda, environment, reducer)->E.R2.errMap(_ => "")
|
||||
Internal.map1(dist, lambda, environment, reducer)
|
||||
| _ => Error(impossibleError)
|
||||
},
|
||||
(),
|
||||
|
@ -215,7 +214,7 @@ let libaryBase = [
|
|||
IEvDistribution(SampleSet(dist2)),
|
||||
IEvLambda(lambda),
|
||||
] =>
|
||||
Internal.map2(dist1, dist2, lambda, environment, reducer)->E.R2.errMap(_ => "")
|
||||
Internal.map2(dist1, dist2, lambda, environment, reducer)
|
||||
| _ => Error(impossibleError)
|
||||
}
|
||||
},
|
||||
|
@ -244,7 +243,7 @@ let libaryBase = [
|
|||
IEvDistribution(SampleSet(dist3)),
|
||||
IEvLambda(lambda),
|
||||
] =>
|
||||
Internal.map3(dist1, dist2, dist3, lambda, environment, reducer)->E.R2.errMap(_ => "")
|
||||
Internal.map3(dist1, dist2, dist3, lambda, environment, reducer)
|
||||
| _ => Error(impossibleError)
|
||||
},
|
||||
(),
|
||||
|
@ -267,9 +266,7 @@ let libaryBase = [
|
|||
~run=(inputs, _, environment, reducer) =>
|
||||
switch inputs {
|
||||
| [IEvArray(dists), IEvLambda(lambda)] =>
|
||||
Internal.mapN(dists, lambda, environment, reducer)->E.R2.errMap(_e => {
|
||||
"AHHH doesn't work"
|
||||
})
|
||||
Internal.mapN(dists, lambda, environment, reducer)
|
||||
| _ => Error(impossibleError)
|
||||
},
|
||||
(),
|
||||
|
@ -294,7 +291,7 @@ module Comparison = {
|
|||
let wrapper = r =>
|
||||
r
|
||||
->E.R2.fmap(r => r->Wrappers.sampleSet->Wrappers.evDistribution)
|
||||
->E.R2.errMap(SampleSetDist.Error.toString)
|
||||
->E.R2.errMap(e => e->DistributionTypes.Error.sampleErrorToDistErr->Reducer_ErrorValue.REDistributionError)
|
||||
|
||||
let mkBig = (name, withDist, withFloat) =>
|
||||
Function.make(
|
||||
|
|
|
@ -6,7 +6,7 @@ let requiresNamespace = true
|
|||
let runScoring = (estimate, answer, prior, env) => {
|
||||
GenericDist.Score.logScore(~estimate, ~answer, ~prior, ~env)
|
||||
->E.R2.fmap(FunctionRegistry_Helpers.Wrappers.evNumber)
|
||||
->E.R2.errMap(DistributionTypes.Error.toString)
|
||||
->E.R2.errMap(e => Reducer_ErrorValue.REDistributionError(e))
|
||||
}
|
||||
|
||||
let library = [
|
||||
|
@ -40,7 +40,7 @@ let library = [
|
|||
FRValueDist(prior),
|
||||
]) =>
|
||||
runScoring(estimate, Score_Scalar(d), Some(prior), environment)
|
||||
| Error(e) => Error(e)
|
||||
| Error(e) => Error(e->FunctionRegistry_Helpers.wrapError)
|
||||
| _ => Error(FunctionRegistry_Helpers.impossibleError)
|
||||
}
|
||||
},
|
||||
|
@ -55,7 +55,7 @@ let library = [
|
|||
runScoring(estimate, Score_Dist(d), None, environment)
|
||||
| Ok([FRValueDist(estimate), FRValueDistOrNumber(FRValueNumber(d))]) =>
|
||||
runScoring(estimate, Score_Scalar(d), None, environment)
|
||||
| Error(e) => Error(e)
|
||||
| Error(e) => Error(e->FunctionRegistry_Helpers.wrapError)
|
||||
| _ => Error(FunctionRegistry_Helpers.impossibleError)
|
||||
}
|
||||
},
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
open FunctionRegistry_Core
|
||||
|
||||
let makeUnitFn = (name: string, multiplier: float) => {
|
||||
Function.make(
|
||||
~name="fromUnit_" ++ name,
|
||||
~nameSpace="",
|
||||
~requiresNamespace=false,
|
||||
~definitions=[
|
||||
FnDefinition.make(
|
||||
~name="fromUnit_" ++ name,
|
||||
~inputs=[FRTypeNumber],
|
||||
~run=(inputs, _, _, _) => {
|
||||
switch inputs {
|
||||
| [IEvNumber(f)] => IEvNumber(f *. multiplier)->Ok
|
||||
| _ => FunctionRegistry_Helpers.impossibleError->Error
|
||||
}
|
||||
},
|
||||
(),
|
||||
),
|
||||
],
|
||||
(),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
let library = [
|
||||
makeUnitFn("n", 1E-9),
|
||||
makeUnitFn("m", 1E-3),
|
||||
makeUnitFn("k", 1E3),
|
||||
makeUnitFn("M", 1E6),
|
||||
makeUnitFn("B", 1E9),
|
||||
makeUnitFn("G", 1E9),
|
||||
makeUnitFn("T", 1E12),
|
||||
makeUnitFn("P", 1E15),
|
||||
]
|
|
@ -12,7 +12,8 @@ let rec get = (nameSpace: t, id: string) => {
|
|||
|
||||
switch container->Belt.MutableMap.String.get(id) {
|
||||
| Some(v) => Some(v)
|
||||
| None => switch parent {
|
||||
| None =>
|
||||
switch parent {
|
||||
| Some(p) => get(p, id)
|
||||
| None => None
|
||||
}
|
||||
|
@ -35,16 +36,12 @@ let set = (nameSpace: t, id: string, value): t => {
|
|||
nameSpace
|
||||
}
|
||||
|
||||
let extend = (nameSpace: t) => T.NameSpace(
|
||||
makeEmptyMap(),
|
||||
nameSpace->Some
|
||||
)
|
||||
let extend = (nameSpace: t) => T.NameSpace(makeEmptyMap(), nameSpace->Some)
|
||||
|
||||
let toKeyValuePairs = (T.NameSpace(container, _): t): array<(string, internalExpressionValue)> => {
|
||||
container->Belt.MutableMap.String.toArray
|
||||
}
|
||||
|
||||
|
||||
let makeEmptyBindings = (): t => T.NameSpace(makeEmptyMap(), None)
|
||||
|
||||
let toExpressionValue = (nameSpace: t): internalExpressionValue => T.IEvBindings(nameSpace)
|
||||
|
@ -64,7 +61,7 @@ let mergeFrom = (T.NameSpace(container, _): t, T.NameSpace(newContainer, parent)
|
|||
}
|
||||
container
|
||||
}),
|
||||
parent
|
||||
parent,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -80,6 +77,8 @@ let removeResult = (nameSpace: t): t => {
|
|||
nameSpace
|
||||
}
|
||||
|
||||
let locals = (T.NameSpace(container, _): t) => T.NameSpace(container, None)
|
||||
|
||||
// let typeAliasesKey = "_typeAliases_"
|
||||
// let typeReferencesKey = "_typeReferences_"
|
||||
|
||||
|
@ -131,16 +130,6 @@ let removeResult = (nameSpace: t): t => {
|
|||
// )
|
||||
// }
|
||||
|
||||
// external castExpressionToInternalCode: ExpressionT.expressionOrFFI => internalCode = "%identity"
|
||||
|
||||
// let eLambdaFFIValue = (ffiFn: ExpressionT.ffiFn) => {
|
||||
// IEvLambda({
|
||||
// parameters: [],
|
||||
// context: emptyModule,
|
||||
// body: FFI(ffiFn)->castExpressionToInternalCode,
|
||||
// })
|
||||
// }
|
||||
|
||||
// let functionNotFoundError = (call: functionCall) =>
|
||||
// REFunctionNotFound(call->functionCallToCallSignature->functionCallSignatureToString)->Error
|
||||
|
||||
|
|
|
@ -3,12 +3,12 @@ type t = Reducer_T.context
|
|||
let createContext = (stdLib: Reducer_T.nameSpace, environment: Reducer_T.environment): t => {
|
||||
{
|
||||
bindings: stdLib->Reducer_Bindings.extend,
|
||||
environment,
|
||||
environment: environment,
|
||||
}
|
||||
}
|
||||
|
||||
let createDefaultContext = (): t =>
|
||||
createContext(
|
||||
ReducerInterface_StdLib.internalStdLib,
|
||||
ReducerInterface_InternalExpressionValue.defaultEnvironment
|
||||
ReducerInterface_InternalExpressionValue.defaultEnvironment,
|
||||
)
|
||||
|
|
|
@ -33,17 +33,17 @@ let callInternal = (
|
|||
| call => call->IEV.toStringFunctionCall->MathJs.Eval.eval
|
||||
}
|
||||
|
||||
let constructRecord = arrayOfPairs => {
|
||||
Belt.Array.map(arrayOfPairs, pairValue =>
|
||||
switch pairValue {
|
||||
| Reducer_T.IEvArray([IEvString(key), valueValue]) => (key, valueValue)
|
||||
| _ => ("wrong key type", pairValue->IEV.toStringWithType->IEvString)
|
||||
}
|
||||
)
|
||||
->Belt.Map.String.fromArray
|
||||
->Reducer_T.IEvRecord
|
||||
->Ok
|
||||
}
|
||||
// let constructRecord = arrayOfPairs => {
|
||||
// Belt.Array.map(arrayOfPairs, pairValue =>
|
||||
// switch pairValue {
|
||||
// | Reducer_T.IEvArray([IEvString(key), valueValue]) => (key, valueValue)
|
||||
// | _ => ("wrong key type", pairValue->IEV.toStringWithType->IEvString)
|
||||
// }
|
||||
// )
|
||||
// ->Belt.Map.String.fromArray
|
||||
// ->Reducer_T.IEvRecord
|
||||
// ->Ok
|
||||
// }
|
||||
|
||||
// let arrayAtIndex = (aValueArray: array<Reducer_T.value>, fIndex: float) =>
|
||||
// switch Belt.Array.get(aValueArray, Belt.Int.fromFloat(fIndex)) {
|
||||
|
@ -111,7 +111,7 @@ let callInternal = (
|
|||
| ("$_atIndex_$", [IEvBindings(dict), IEvString(sIndex)]) => moduleAtIndex(dict, sIndex)
|
||||
// | ("$_atIndex_$", [IEvRecord(dict), IEvString(sIndex)]) => recordAtIndex(dict, sIndex)
|
||||
// | ("$_constructArray_$", args) => IEvArray(args)->Ok
|
||||
| ("$_constructRecord_$", [IEvArray(arrayOfPairs)]) => constructRecord(arrayOfPairs)
|
||||
// | ("$_constructRecord_$", [IEvArray(arrayOfPairs)]) => constructRecord(arrayOfPairs)
|
||||
// | ("$_exportBindings_$", [IEvBindings(nameSpace)]) => doExportBindings(nameSpace)
|
||||
// | ("$_exportBindings_$", [evValue]) => doIdentity(evValue)
|
||||
// | ("$_setBindings_$", [IEvBindings(nameSpace), IEvSymbol(symbol), value]) =>
|
||||
|
@ -154,7 +154,9 @@ let callInternal = (
|
|||
| (_, [IEvString(_), IEvString(_)]) =>
|
||||
callMathJs(call)
|
||||
| call =>
|
||||
Error(REFunctionNotFound(call->IEV.functionCallToCallSignature->IEV.functionCallSignatureToString)) // Report full type signature as error
|
||||
Error(
|
||||
REFunctionNotFound(call->IEV.functionCallToCallSignature->IEV.functionCallSignatureToString),
|
||||
) // Report full type signature as error
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
@ -163,7 +165,7 @@ let callInternal = (
|
|||
let dispatch = (
|
||||
call: IEV.functionCall,
|
||||
env: Reducer_T.environment,
|
||||
reducer: Reducer_T.reducerFn
|
||||
reducer: Reducer_T.reducerFn,
|
||||
): Reducer_T.value =>
|
||||
try {
|
||||
let (fn, args) = call
|
||||
|
|
|
@ -21,3 +21,4 @@
|
|||
// }
|
||||
// dispatchChainPiece
|
||||
// }
|
||||
|
||||
|
|
|
@ -19,3 +19,4 @@
|
|||
// array<Reducer_T.value>,
|
||||
// ProjectAccessorsT.t,
|
||||
// ) => result<Reducer_T.value, Reducer_ErrorValue.errorValue>
|
||||
|
||||
|
|
|
@ -10,35 +10,28 @@ exception ErrorException = Reducer_ErrorValue.ErrorException
|
|||
/*
|
||||
Recursively evaluate the expression
|
||||
*/
|
||||
let rec evaluate: T.reducerFn = (
|
||||
expression,
|
||||
context
|
||||
) => {
|
||||
let rec evaluate: T.reducerFn = (expression, context) => {
|
||||
// Js.log(`reduce: ${expression->Reducer_Expression_T.toString}`)
|
||||
switch expression {
|
||||
| T.EBlock(statements) => {
|
||||
let innerContext = {...context, bindings: context.bindings->Bindings.extend}
|
||||
statements->Js.Array2.reduce(
|
||||
(_, statement) => statement->evaluate(innerContext),
|
||||
T.IEvVoid
|
||||
)
|
||||
statements->Js.Array2.reduce((_, statement) => statement->evaluate(innerContext), T.IEvVoid)
|
||||
}
|
||||
|
||||
| T.EProgram(statements) => {
|
||||
// Js.log(`bindings: ${context.bindings->Reducer_Bindings.toString}`)
|
||||
let res = statements->Js.Array2.reduce(
|
||||
(_, statement) => statement->evaluate(context),
|
||||
T.IEvVoid
|
||||
)
|
||||
let res =
|
||||
statements->Js.Array2.reduce((_, statement) => statement->evaluate(context), T.IEvVoid)
|
||||
|
||||
// Js.log(`bindings after: ${context.bindings->Reducer_Bindings.toString}`)
|
||||
res
|
||||
}
|
||||
|
||||
| T.EArray(elements) =>
|
||||
elements->Js.Array2.map(element => evaluate(element, context))->T.IEvArray
|
||||
| T.EArray(elements) => elements->Js.Array2.map(element => evaluate(element, context))->T.IEvArray
|
||||
|
||||
| T.ERecord(pairs) =>
|
||||
pairs->Js.Array2.map(((eKey, eValue)) => {
|
||||
pairs
|
||||
->Js.Array2.map(((eKey, eValue)) => {
|
||||
let key = eKey->evaluate(context)
|
||||
let keyString = switch key {
|
||||
| IEvString(s) => s
|
||||
|
@ -46,7 +39,9 @@ let rec evaluate: T.reducerFn = (
|
|||
}
|
||||
let value = eValue->evaluate(context)
|
||||
(keyString, value)
|
||||
})->Belt.Map.String.fromArray->IEvRecord
|
||||
})
|
||||
->Belt.Map.String.fromArray
|
||||
->IEvRecord
|
||||
|
||||
| T.EAssign(left, right) => {
|
||||
let result = right->evaluate(context)
|
||||
|
@ -60,14 +55,12 @@ let rec evaluate: T.reducerFn = (
|
|||
| None => Reducer_ErrorValue.RESymbolNotFound(name)->ErrorException->raise
|
||||
}
|
||||
|
||||
| T.EValue(value) =>
|
||||
value
|
||||
| T.EValue(value) => value
|
||||
|
||||
| T.ETernary(predicate, trueCase, falseCase) => {
|
||||
let predicateResult = predicate->evaluate(context)
|
||||
switch predicateResult {
|
||||
| T.IEvBool(value) =>
|
||||
(value ? trueCase : falseCase)->evaluate(context)
|
||||
| T.IEvBool(value) => (value ? trueCase : falseCase)->evaluate(context)
|
||||
| _ => REExpectedType("Boolean", "")->ErrorException->raise
|
||||
}
|
||||
}
|
||||
|
@ -79,8 +72,7 @@ let rec evaluate: T.reducerFn = (
|
|||
let lambda = fn->evaluate(context)
|
||||
let argValues = Js.Array2.map(args, arg => arg->evaluate(context))
|
||||
switch lambda {
|
||||
| T.IEvLambda(lambda) =>
|
||||
Lambda.doLambdaCall(lambda, argValues, context.environment, evaluate)
|
||||
| T.IEvLambda(lambda) => Lambda.doLambdaCall(lambda, argValues, context.environment, evaluate)
|
||||
| _ => REExpectedType("Lambda", "")->ErrorException->raise
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
module BBindingsReplacer = Reducer_Expression_BindingsReplacer
|
||||
module BErrorValue = Reducer_ErrorValue
|
||||
module T = Reducer_T
|
||||
|
||||
|
@ -14,13 +13,9 @@ let eBindings = (anArray: array<(string, T.value)>) =>
|
|||
|
||||
let eBool = aBool => aBool->T.IEvBool->T.EValue
|
||||
|
||||
let eCall = (fn: expression, args: array<expression>): expression =>
|
||||
T.ECall(fn, args)
|
||||
let eCall = (fn: expression, args: array<expression>): expression => T.ECall(fn, args)
|
||||
|
||||
let eLambda = (
|
||||
parameters: array<string>,
|
||||
expr: expression,
|
||||
) => T.ELambda(parameters, expr)
|
||||
let eLambda = (parameters: array<string>, expr: expression) => T.ELambda(parameters, expr)
|
||||
|
||||
let eNumber = aNumber => aNumber->T.IEvNumber->T.EValue
|
||||
|
||||
|
@ -28,26 +23,26 @@ let eRecord = (aMap: array<(T.expression, T.expression)>) => aMap->T.ERecord
|
|||
|
||||
let eString = aString => aString->T.IEvString->T.EValue
|
||||
|
||||
let eSymbol = (name: string): expression =>
|
||||
T.ESymbol(name)
|
||||
let eSymbol = (name: string): expression => T.ESymbol(name)
|
||||
|
||||
let eBlock = (exprs: array<expression>): expression =>
|
||||
T.EBlock(exprs)
|
||||
let eBlock = (exprs: array<expression>): expression => T.EBlock(exprs)
|
||||
|
||||
let eProgram = (exprs: array<expression>): expression =>
|
||||
T.EProgram(exprs)
|
||||
let eProgram = (exprs: array<expression>): expression => T.EProgram(exprs)
|
||||
|
||||
let eModule = (nameSpace: T.nameSpace): expression =>
|
||||
nameSpace->T.IEvBindings->T.EValue
|
||||
let eModule = (nameSpace: T.nameSpace): expression => nameSpace->T.IEvBindings->T.EValue
|
||||
|
||||
let eLetStatement = (symbol: string, valueExpression: expression): expression =>
|
||||
T.EAssign(symbol, valueExpression)
|
||||
let eLetStatement = (symbol: string, valueExpression: expression): expression => T.EAssign(
|
||||
symbol,
|
||||
valueExpression,
|
||||
)
|
||||
|
||||
let eTernary = (predicate: expression, trueCase: expression, falseCase: expression): expression =>
|
||||
T.ETernary(predicate, trueCase, falseCase)
|
||||
let eTernary = (
|
||||
predicate: expression,
|
||||
trueCase: expression,
|
||||
falseCase: expression,
|
||||
): expression => T.ETernary(predicate, trueCase, falseCase)
|
||||
|
||||
let eIdentifier = (name: string): expression =>
|
||||
name->T.ESymbol
|
||||
let eIdentifier = (name: string): expression => name->T.ESymbol
|
||||
|
||||
// let eTypeIdentifier = (name: string): expression =>
|
||||
// name->T.IEvTypeIdentifier->T.EValue
|
||||
|
|
|
@ -7,7 +7,7 @@ let doLambdaCall = (
|
|||
lambdaValue: Reducer_T.lambdaValue,
|
||||
args,
|
||||
environment: Reducer_T.environment,
|
||||
reducer: Reducer_T.reducerFn
|
||||
reducer: Reducer_T.reducerFn,
|
||||
): Reducer_T.value => {
|
||||
lambdaValue.body(args, environment, reducer)
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ let makeLambda = (
|
|||
let lambda = (
|
||||
arguments: array<Reducer_T.value>,
|
||||
environment: Reducer_T.environment,
|
||||
reducer: Reducer_T.reducerFn
|
||||
reducer: Reducer_T.reducerFn,
|
||||
) => {
|
||||
let argsLength = arguments->Js.Array2.length
|
||||
let parametersLength = parameters->Js.Array2.length
|
||||
|
@ -34,23 +34,21 @@ let makeLambda = (
|
|||
}
|
||||
|
||||
let localBindings = bindings->Reducer_Bindings.extend
|
||||
parameters->Js.Array2.forEachi(
|
||||
(parameter, index) => {
|
||||
parameters->Js.Array2.forEachi((parameter, index) => {
|
||||
let _ = localBindings->Reducer_Bindings.set(parameter, arguments[index])
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
reducer(body, { bindings: localBindings, environment })
|
||||
reducer(body, {bindings: localBindings, environment: environment})
|
||||
}
|
||||
|
||||
{
|
||||
// context: bindings,
|
||||
body: lambda,
|
||||
parameters,
|
||||
parameters: parameters,
|
||||
}
|
||||
}
|
||||
|
||||
let makeFFILambda = (body: Reducer_T.lambdaBody): Reducer_T.lambdaValue => {
|
||||
body,
|
||||
parameters: ["..."]
|
||||
body: body,
|
||||
parameters: ["..."],
|
||||
}
|
||||
|
|
|
@ -27,15 +27,13 @@ let commaJoin = values => values->Reducer_Extra_Array.intersperse(", ")->Js.Stri
|
|||
*/
|
||||
let rec toString = (expression: expression) =>
|
||||
switch expression {
|
||||
| EBlock(statements) =>
|
||||
`{${Js.Array2.map(statements, aValue => toString(aValue))->commaJoin}}`
|
||||
| EProgram(statements) =>
|
||||
`<${Js.Array2.map(statements, aValue => toString(aValue))->commaJoin}>`
|
||||
| EArray(aList) =>
|
||||
`[${Js.Array2.map(aList, aValue => toString(aValue))->commaJoin}]`
|
||||
| EBlock(statements) => `{${Js.Array2.map(statements, aValue => toString(aValue))->commaJoin}}`
|
||||
| EProgram(statements) => `<${Js.Array2.map(statements, aValue => toString(aValue))->commaJoin}>`
|
||||
| EArray(aList) => `[${Js.Array2.map(aList, aValue => toString(aValue))->commaJoin}]`
|
||||
| ERecord(map) => "TODO"
|
||||
| ESymbol(name) => name
|
||||
| ETernary(predicate, trueCase, falseCase) => `${predicate->toString} ? (${trueCase->toString}) : (${falseCase->toString})`
|
||||
| ETernary(predicate, trueCase, falseCase) =>
|
||||
`${predicate->toString} ? (${trueCase->toString}) : (${falseCase->toString})`
|
||||
| EAssign(name, value) => `${name} = ${value->toString}`
|
||||
| ECall(fn, args) => `(${fn->toString})(${args->Js.Array2.map(toString)->commaJoin})`
|
||||
| ELambda(parameters, body) => `{|${parameters->commaJoin}| ${body->toString}}`
|
||||
|
@ -77,7 +75,3 @@ type optionFfiFnReturningResult = (
|
|||
array<internalExpressionValue>,
|
||||
environment,
|
||||
) => option<result<internalExpressionValue, Reducer_ErrorValue.errorValue>>
|
||||
|
||||
type expressionOrFFI =
|
||||
| NotFFI(expression)
|
||||
| FFI(ffiFn)
|
||||
|
|
|
@ -109,14 +109,17 @@ let rec pgToString = (peggyNode: peggyNode): string => {
|
|||
|
||||
switch peggyNode {
|
||||
| PgNodeBlock(node)
|
||||
| PgNodeProgram(node)
|
||||
=> "{" ++ node["statements"]->nodesToStringUsingSeparator("; ") ++ "}"
|
||||
| PgNodeArray(node)
|
||||
=> "[" ++ node["elements"]->nodesToStringUsingSeparator("; ") ++ "]"
|
||||
| PgNodeRecord(node)
|
||||
=> "{" ++ node["elements"]->Js.Array2.map(element => PgNodeKeyValue(element))->pgNodesToStringUsingSeparator(", ") ++ "}"
|
||||
| PgNodeProgram(node) =>
|
||||
"{" ++ node["statements"]->nodesToStringUsingSeparator("; ") ++ "}"
|
||||
| PgNodeArray(node) => "[" ++ node["elements"]->nodesToStringUsingSeparator("; ") ++ "]"
|
||||
| PgNodeRecord(node) =>
|
||||
"{" ++
|
||||
node["elements"]
|
||||
->Js.Array2.map(element => PgNodeKeyValue(element))
|
||||
->pgNodesToStringUsingSeparator(", ") ++ "}"
|
||||
| PgNodeBoolean(node) => node["value"]->Js.String.make
|
||||
| PgNodeCall(node) => "(" ++ node["fn"]->toString ++ " " ++ node["args"]->nodesToStringUsingSeparator(" ") ++ ")"
|
||||
| PgNodeCall(node) =>
|
||||
"(" ++ node["fn"]->toString ++ " " ++ node["args"]->nodesToStringUsingSeparator(" ") ++ ")"
|
||||
| PgNodeFloat(node) => node["value"]->Js.String.make
|
||||
| PgNodeIdentifier(node) => `:${node["value"]}`
|
||||
| PgNodeInteger(node) => node["value"]->Js.String.make
|
||||
|
|
|
@ -13,29 +13,30 @@ let rec fromNode = (node: Parse.node): expression => {
|
|||
|
||||
let caseLambda = (nodeLambda: Parse.nodeLambda): expression => {
|
||||
let args =
|
||||
nodeLambda["args"]
|
||||
->Js.Array2.map((argNode: Parse.nodeIdentifier) => argNode["value"])
|
||||
nodeLambda["args"]->Js.Array2.map((argNode: Parse.nodeIdentifier) => argNode["value"])
|
||||
let body = nodeLambda["body"]->fromNode
|
||||
|
||||
ExpressionBuilder.eLambda(args, body)
|
||||
|
||||
}
|
||||
|
||||
let caseRecord = (nodeRecord): expression => {
|
||||
nodeRecord["elements"]
|
||||
->Js.Array2.map(
|
||||
keyValueNode => (keyValueNode["key"]->fromNode, keyValueNode["value"]->fromNode)
|
||||
)
|
||||
->Js.Array2.map(keyValueNode => (
|
||||
keyValueNode["key"]->fromNode,
|
||||
keyValueNode["value"]->fromNode,
|
||||
))
|
||||
->ExpressionBuilder.eRecord
|
||||
}
|
||||
|
||||
switch Parse.castNodeType(node) {
|
||||
| PgNodeBlock(nodeBlock) => caseBlock(nodeBlock)
|
||||
| PgNodeProgram(nodeProgram) => caseProgram(nodeProgram)
|
||||
| PgNodeArray(nodeArray) => ExpressionBuilder.eArray(nodeArray["elements"]->Js.Array2.map(fromNode))
|
||||
| PgNodeArray(nodeArray) =>
|
||||
ExpressionBuilder.eArray(nodeArray["elements"]->Js.Array2.map(fromNode))
|
||||
| PgNodeRecord(nodeRecord) => caseRecord(nodeRecord)
|
||||
| PgNodeBoolean(nodeBoolean) => ExpressionBuilder.eBool(nodeBoolean["value"])
|
||||
| PgNodeCall(nodeCall) => ExpressionBuilder.eCall(fromNode(nodeCall["fn"]), nodeCall["args"]->Js.Array2.map(fromNode))
|
||||
| PgNodeCall(nodeCall) =>
|
||||
ExpressionBuilder.eCall(fromNode(nodeCall["fn"]), nodeCall["args"]->Js.Array2.map(fromNode))
|
||||
| PgNodeFloat(nodeFloat) => ExpressionBuilder.eNumber(nodeFloat["value"])
|
||||
| PgNodeIdentifier(nodeIdentifier) => ExpressionBuilder.eSymbol(nodeIdentifier["value"])
|
||||
| PgNodeInteger(nodeInteger) => ExpressionBuilder.eNumber(Belt.Int.toFloat(nodeInteger["value"]))
|
||||
|
@ -54,7 +55,7 @@ let rec fromNode = (node: Parse.node): expression => {
|
|||
ExpressionBuilder.eTernary(
|
||||
fromNode(nodeTernary["condition"]),
|
||||
fromNode(nodeTernary["trueExpression"]),
|
||||
fromNode(nodeTernary["falseExpression"])
|
||||
fromNode(nodeTernary["falseExpression"]),
|
||||
)
|
||||
// | PgNodeTypeIdentifier(nodeTypeIdentifier) =>
|
||||
// ExpressionBuilder.eTypeIdentifier(nodeTypeIdentifier["value"])
|
||||
|
|
|
@ -39,3 +39,4 @@
|
|||
// | Ok(value) => value
|
||||
// | _ => `Cannot compile ${typeExpressionSourceCode}`->Reducer_Exception.ImpossibleException->raise
|
||||
// }
|
||||
|
||||
|
|
|
@ -117,3 +117,4 @@
|
|||
// | IEvRecord(record) => record->Belt.Map.String.map(fromIEvValue)
|
||||
// | _ => raise(Reducer_Exception.ImpossibleException("Reducer_Type_T-ievRecord"))
|
||||
// }
|
||||
|
||||
|
|
|
@ -78,3 +78,4 @@
|
|||
// ])
|
||||
// newRecord->IEvType->Ok
|
||||
// }
|
||||
|
||||
|
|
|
@ -179,3 +179,4 @@
|
|||
// | Error(error) => Error(error) // Directly propagating - err => err - causes type mismatch
|
||||
// }
|
||||
// }
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
module T = Reducer_T
|
||||
|
||||
let dispatch = (call: ReducerInterface_InternalExpressionValue.functionCall, _: GenericDist.env): option<
|
||||
result<T.value, Reducer_ErrorValue.errorValue>,
|
||||
> => {
|
||||
let dispatch = (
|
||||
call: ReducerInterface_InternalExpressionValue.functionCall,
|
||||
_: GenericDist.env,
|
||||
): option<result<T.value, Reducer_ErrorValue.errorValue>> => {
|
||||
switch call {
|
||||
| ("toString", [IEvDate(t)]) => T.IEvString(DateTime.Date.toString(t))->Ok->Some
|
||||
| ("makeDateFromYear", [IEvNumber(year)]) =>
|
||||
|
|
|
@ -3,7 +3,7 @@ module T = Reducer_T
|
|||
type internalExpressionValue = IEV.t
|
||||
|
||||
let dispatch = (call: IEV.functionCall, _: T.environment): option<
|
||||
result<Reducer_T.value, Reducer_ErrorValue.errorValue>
|
||||
result<Reducer_T.value, Reducer_ErrorValue.errorValue>,
|
||||
> => {
|
||||
switch call {
|
||||
| ("toString", [IEvTimeDuration(t)]) => T.IEvString(DateTime.Duration.toString(t))->Ok->Some
|
||||
|
@ -14,8 +14,7 @@ let dispatch = (call: IEV.functionCall, _: T.environment): option<
|
|||
| ("fromUnit_hours", [IEvNumber(f)]) =>
|
||||
T.IEvTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some
|
||||
| ("days", [IEvNumber(f)]) => T.IEvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
|
||||
| ("fromUnit_days", [IEvNumber(f)]) =>
|
||||
T.IEvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
|
||||
| ("fromUnit_days", [IEvNumber(f)]) => T.IEvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
|
||||
| ("years", [IEvNumber(f)]) => T.IEvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
|
||||
| ("fromUnit_years", [IEvNumber(f)]) =>
|
||||
T.IEvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
|
||||
|
|
|
@ -10,7 +10,7 @@ let dispatch = (
|
|||
chain,
|
||||
): result<Reducer_T.value, 'e> => {
|
||||
E.A.O.firstSomeFn([
|
||||
() => ReducerInterface_GenericDistribution.dispatch(call, environment),
|
||||
// () => ReducerInterface_GenericDistribution.dispatch(call, environment),
|
||||
() => ReducerInterface_Date.dispatch(call, environment),
|
||||
() => ReducerInterface_Duration.dispatch(call, environment),
|
||||
() => ReducerInterface_Number.dispatch(call, environment),
|
||||
|
|
|
@ -1,310 +0,0 @@
|
|||
module IEV = ReducerInterface_InternalExpressionValue
|
||||
type internalExpressionValue = IEV.t
|
||||
|
||||
module Helpers = {
|
||||
let arithmeticMap = r =>
|
||||
switch r {
|
||||
| "add" => #Add
|
||||
| "dotAdd" => #Add
|
||||
| "subtract" => #Subtract
|
||||
| "dotSubtract" => #Subtract
|
||||
| "divide" => #Divide
|
||||
| "log" => #Logarithm
|
||||
| "dotDivide" => #Divide
|
||||
| "pow" => #Power
|
||||
| "dotPow" => #Power
|
||||
| "multiply" => #Multiply
|
||||
| "dotMultiply" => #Multiply
|
||||
| _ => #Multiply
|
||||
}
|
||||
|
||||
let catchAndConvertTwoArgsToDists = (args: array<internalExpressionValue>): option<(
|
||||
DistributionTypes.genericDist,
|
||||
DistributionTypes.genericDist,
|
||||
)> =>
|
||||
switch args {
|
||||
| [IEvDistribution(a), IEvDistribution(b)] => Some((a, b))
|
||||
| [IEvNumber(a), IEvDistribution(b)] => Some((GenericDist.fromFloat(a), b))
|
||||
| [IEvDistribution(a), IEvNumber(b)] => Some((a, GenericDist.fromFloat(b)))
|
||||
| _ => None
|
||||
}
|
||||
|
||||
let toFloatFn = (
|
||||
fnCall: DistributionTypes.DistributionOperation.toFloat,
|
||||
dist: DistributionTypes.genericDist,
|
||||
~env: GenericDist.env,
|
||||
) => {
|
||||
FromDist(#ToFloat(fnCall), dist)->DistributionOperation.run(~env)->Some
|
||||
}
|
||||
|
||||
let toStringFn = (
|
||||
fnCall: DistributionTypes.DistributionOperation.toString,
|
||||
dist: DistributionTypes.genericDist,
|
||||
~env: GenericDist.env,
|
||||
) => {
|
||||
FromDist(#ToString(fnCall), dist)->DistributionOperation.run(~env)->Some
|
||||
}
|
||||
|
||||
let toBoolFn = (
|
||||
fnCall: DistributionTypes.DistributionOperation.toBool,
|
||||
dist: DistributionTypes.genericDist,
|
||||
~env: GenericDist.env,
|
||||
) => {
|
||||
FromDist(#ToBool(fnCall), dist)->DistributionOperation.run(~env)->Some
|
||||
}
|
||||
|
||||
let toDistFn = (
|
||||
fnCall: DistributionTypes.DistributionOperation.toDist,
|
||||
dist,
|
||||
~env: GenericDist.env,
|
||||
) => {
|
||||
FromDist(#ToDist(fnCall), dist)->DistributionOperation.run(~env)->Some
|
||||
}
|
||||
|
||||
let twoDiststoDistFn = (direction, arithmetic, dist1, dist2, ~env: GenericDist.env) => {
|
||||
FromDist(
|
||||
#ToDistCombination(direction, arithmeticMap(arithmetic), #Dist(dist2)),
|
||||
dist1,
|
||||
)->DistributionOperation.run(~env)
|
||||
}
|
||||
|
||||
let parseNumber = (args: internalExpressionValue): Belt.Result.t<float, string> =>
|
||||
switch args {
|
||||
| IEvNumber(x) => Ok(x)
|
||||
| _ => Error("Not a number")
|
||||
}
|
||||
|
||||
let parseNumberArray = (ags: array<internalExpressionValue>): Belt.Result.t<
|
||||
array<float>,
|
||||
string,
|
||||
> => E.A.fmap(parseNumber, ags) |> E.A.R.firstErrorOrOpen
|
||||
|
||||
let parseDist = (args: internalExpressionValue): Belt.Result.t<
|
||||
DistributionTypes.genericDist,
|
||||
string,
|
||||
> =>
|
||||
switch args {
|
||||
| IEvDistribution(x) => Ok(x)
|
||||
| IEvNumber(x) => Ok(GenericDist.fromFloat(x))
|
||||
| _ => Error("Not a distribution")
|
||||
}
|
||||
|
||||
let parseDistributionArray = (ags: array<internalExpressionValue>): Belt.Result.t<
|
||||
array<DistributionTypes.genericDist>,
|
||||
string,
|
||||
> => E.A.fmap(parseDist, ags) |> E.A.R.firstErrorOrOpen
|
||||
|
||||
let mixtureWithGivenWeights = (
|
||||
distributions: array<DistributionTypes.genericDist>,
|
||||
weights: array<float>,
|
||||
~env: GenericDist.env,
|
||||
): DistributionOperation.outputType =>
|
||||
E.A.length(distributions) == E.A.length(weights)
|
||||
? Mixture(Belt.Array.zip(distributions, weights))->DistributionOperation.run(~env)
|
||||
: GenDistError(
|
||||
ArgumentError("Error, mixture call has different number of distributions and weights"),
|
||||
)
|
||||
|
||||
let mixtureWithDefaultWeights = (
|
||||
distributions: array<DistributionTypes.genericDist>,
|
||||
~env: GenericDist.env,
|
||||
): DistributionOperation.outputType => {
|
||||
let length = E.A.length(distributions)
|
||||
let weights = Belt.Array.make(length, 1.0 /. Belt.Int.toFloat(length))
|
||||
mixtureWithGivenWeights(distributions, weights, ~env)
|
||||
}
|
||||
|
||||
let mixture = (
|
||||
args: array<internalExpressionValue>,
|
||||
~env: GenericDist.env,
|
||||
): DistributionOperation.outputType => {
|
||||
let error = (err: string): DistributionOperation.outputType =>
|
||||
err->DistributionTypes.ArgumentError->GenDistError
|
||||
switch args {
|
||||
| [IEvArray(distributions)] =>
|
||||
switch parseDistributionArray(distributions) {
|
||||
| Ok(distrs) => mixtureWithDefaultWeights(distrs, ~env)
|
||||
| Error(err) => error(err)
|
||||
}
|
||||
| [IEvArray(distributions), IEvArray(weights)] =>
|
||||
switch (parseDistributionArray(distributions), parseNumberArray(weights)) {
|
||||
| (Ok(distrs), Ok(wghts)) => mixtureWithGivenWeights(distrs, wghts, ~env)
|
||||
| (Error(err), Ok(_)) => error(err)
|
||||
| (Ok(_), Error(err)) => error(err)
|
||||
| (Error(err1), Error(err2)) => error(`${err1}|${err2}`)
|
||||
}
|
||||
| _ =>
|
||||
switch E.A.last(args) {
|
||||
| Some(IEvArray(b)) => {
|
||||
let weights = parseNumberArray(b)
|
||||
let distributions = parseDistributionArray(
|
||||
Belt.Array.slice(args, ~offset=0, ~len=E.A.length(args) - 1),
|
||||
)
|
||||
switch E.R.merge(distributions, weights) {
|
||||
| Ok(d, w) => mixtureWithGivenWeights(d, w, ~env)
|
||||
| Error(err) => error(err)
|
||||
}
|
||||
}
|
||||
| Some(IEvNumber(_))
|
||||
| Some(IEvDistribution(_)) =>
|
||||
switch parseDistributionArray(args) {
|
||||
| Ok(distributions) => mixtureWithDefaultWeights(distributions, ~env)
|
||||
| Error(err) => error(err)
|
||||
}
|
||||
| _ => error("Last argument of mx must be array or distribution")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module SymbolicConstructors = {
|
||||
let threeFloat = name =>
|
||||
switch name {
|
||||
| "triangular" => Ok(SymbolicDist.Triangular.make)
|
||||
| _ => Error("Unreachable state")
|
||||
}
|
||||
|
||||
let symbolicResultToOutput = (
|
||||
symbolicResult: result<SymbolicDistTypes.symbolicDist, string>,
|
||||
): option<DistributionOperation.outputType> =>
|
||||
switch symbolicResult {
|
||||
| Ok(r) => Some(Dist(Symbolic(r)))
|
||||
| Error(r) => Some(GenDistError(OtherError(r)))
|
||||
}
|
||||
}
|
||||
|
||||
let dispatchToGenericOutput = (call: IEV.functionCall, env: GenericDist.env): option<
|
||||
DistributionOperation.outputType,
|
||||
> => {
|
||||
let (fnName, args) = call
|
||||
switch (fnName, args) {
|
||||
| ("triangular" as fnName, [IEvNumber(f1), IEvNumber(f2), IEvNumber(f3)]) =>
|
||||
SymbolicConstructors.threeFloat(fnName)
|
||||
->E.R.bind(r => r(f1, f2, f3))
|
||||
->SymbolicConstructors.symbolicResultToOutput
|
||||
| ("sample", [IEvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist, ~env)
|
||||
| ("sampleN", [IEvDistribution(dist), IEvNumber(n)]) =>
|
||||
Some(FloatArray(GenericDist.sampleN(dist, Belt.Int.fromFloat(n))))
|
||||
| (("mean" | "stdev" | "variance" | "min" | "max" | "mode") as op, [IEvDistribution(dist)]) => {
|
||||
let fn = switch op {
|
||||
| "mean" => #Mean
|
||||
| "stdev" => #Stdev
|
||||
| "variance" => #Variance
|
||||
| "min" => #Min
|
||||
| "max" => #Max
|
||||
| "mode" => #Mode
|
||||
| _ => #Mean
|
||||
}
|
||||
Helpers.toFloatFn(fn, dist, ~env)
|
||||
}
|
||||
| ("integralSum", [IEvDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist, ~env)
|
||||
| ("toString", [IEvDistribution(dist)]) => Helpers.toStringFn(ToString, dist, ~env)
|
||||
| ("sparkline", [IEvDistribution(dist)]) =>
|
||||
Helpers.toStringFn(ToSparkline(MagicNumbers.Environment.sparklineLength), dist, ~env)
|
||||
| ("sparkline", [IEvDistribution(dist), IEvNumber(n)]) =>
|
||||
Helpers.toStringFn(ToSparkline(Belt.Float.toInt(n)), dist, ~env)
|
||||
| ("exp", [IEvDistribution(a)]) =>
|
||||
// https://mathjs.org/docs/reference/functions/exp.html
|
||||
Helpers.twoDiststoDistFn(
|
||||
Algebraic(AsDefault),
|
||||
"pow",
|
||||
GenericDist.fromFloat(MagicNumbers.Math.e),
|
||||
a,
|
||||
~env,
|
||||
)->Some
|
||||
| ("normalize", [IEvDistribution(dist)]) => Helpers.toDistFn(Normalize, dist, ~env)
|
||||
| ("isNormalized", [IEvDistribution(dist)]) => Helpers.toBoolFn(IsNormalized, dist, ~env)
|
||||
| ("toPointSet", [IEvDistribution(dist)]) => Helpers.toDistFn(ToPointSet, dist, ~env)
|
||||
| ("scaleLog", [IEvDistribution(dist)]) =>
|
||||
Helpers.toDistFn(Scale(#Logarithm, MagicNumbers.Math.e), dist, ~env)
|
||||
| ("scaleLog10", [IEvDistribution(dist)]) => Helpers.toDistFn(Scale(#Logarithm, 10.0), dist, ~env)
|
||||
| ("scaleLog", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||
Helpers.toDistFn(Scale(#Logarithm, float), dist, ~env)
|
||||
| ("scaleLogWithThreshold", [IEvDistribution(dist), IEvNumber(base), IEvNumber(eps)]) =>
|
||||
Helpers.toDistFn(Scale(#LogarithmWithThreshold(eps), base), dist, ~env)
|
||||
| ("scaleMultiply", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||
Helpers.toDistFn(Scale(#Multiply, float), dist, ~env)
|
||||
| ("scalePow", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||
Helpers.toDistFn(Scale(#Power, float), dist, ~env)
|
||||
| ("scaleExp", [IEvDistribution(dist)]) =>
|
||||
Helpers.toDistFn(Scale(#Power, MagicNumbers.Math.e), dist, ~env)
|
||||
| ("cdf", [IEvDistribution(dist), IEvNumber(float)]) => Helpers.toFloatFn(#Cdf(float), dist, ~env)
|
||||
| ("pdf", [IEvDistribution(dist), IEvNumber(float)]) => Helpers.toFloatFn(#Pdf(float), dist, ~env)
|
||||
| ("inv", [IEvDistribution(dist), IEvNumber(float)]) => Helpers.toFloatFn(#Inv(float), dist, ~env)
|
||||
| ("quantile", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||
Helpers.toFloatFn(#Inv(float), dist, ~env)
|
||||
| ("inspect", [IEvDistribution(dist)]) => Helpers.toDistFn(Inspect, dist, ~env)
|
||||
| ("truncateLeft", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||
Helpers.toDistFn(Truncate(Some(float), None), dist, ~env)
|
||||
| ("truncateRight", [IEvDistribution(dist), IEvNumber(float)]) =>
|
||||
Helpers.toDistFn(Truncate(None, Some(float)), dist, ~env)
|
||||
| ("truncate", [IEvDistribution(dist), IEvNumber(float1), IEvNumber(float2)]) =>
|
||||
Helpers.toDistFn(Truncate(Some(float1), Some(float2)), dist, ~env)
|
||||
| ("mx" | "mixture", args) => Helpers.mixture(args, ~env)->Some
|
||||
| ("log", [IEvDistribution(a)]) =>
|
||||
Helpers.twoDiststoDistFn(
|
||||
Algebraic(AsDefault),
|
||||
"log",
|
||||
a,
|
||||
GenericDist.fromFloat(MagicNumbers.Math.e),
|
||||
~env,
|
||||
)->Some
|
||||
| ("log10", [IEvDistribution(a)]) =>
|
||||
Helpers.twoDiststoDistFn(
|
||||
Algebraic(AsDefault),
|
||||
"log",
|
||||
a,
|
||||
GenericDist.fromFloat(10.0),
|
||||
~env,
|
||||
)->Some
|
||||
| ("unaryMinus", [IEvDistribution(a)]) =>
|
||||
Helpers.twoDiststoDistFn(
|
||||
Algebraic(AsDefault),
|
||||
"multiply",
|
||||
a,
|
||||
GenericDist.fromFloat(-1.0),
|
||||
~env,
|
||||
)->Some
|
||||
| (("add" | "multiply" | "subtract" | "divide" | "pow" | "log") as arithmetic, [_, _] as args) =>
|
||||
Helpers.catchAndConvertTwoArgsToDists(args)->E.O2.fmap(((fst, snd)) =>
|
||||
Helpers.twoDiststoDistFn(Algebraic(AsDefault), arithmetic, fst, snd, ~env)
|
||||
)
|
||||
| (
|
||||
("dotAdd"
|
||||
| "dotMultiply"
|
||||
| "dotSubtract"
|
||||
| "dotDivide"
|
||||
| "dotPow") as arithmetic,
|
||||
[_, _] as args,
|
||||
) =>
|
||||
Helpers.catchAndConvertTwoArgsToDists(args)->E.O2.fmap(((fst, snd)) =>
|
||||
Helpers.twoDiststoDistFn(Pointwise, arithmetic, fst, snd, ~env)
|
||||
)
|
||||
| ("dotExp", [IEvDistribution(a)]) =>
|
||||
Helpers.twoDiststoDistFn(
|
||||
Pointwise,
|
||||
"dotPow",
|
||||
GenericDist.fromFloat(MagicNumbers.Math.e),
|
||||
a,
|
||||
~env,
|
||||
)->Some
|
||||
| _ => None
|
||||
}
|
||||
}
|
||||
|
||||
let genericOutputToReducerValue = (o: DistributionOperation.outputType): result<
|
||||
internalExpressionValue,
|
||||
Reducer_ErrorValue.errorValue,
|
||||
> =>
|
||||
switch o {
|
||||
| Dist(d) => Ok(Reducer_T.IEvDistribution(d))
|
||||
| Float(d) => Ok(IEvNumber(d))
|
||||
| String(d) => Ok(IEvString(d))
|
||||
| Bool(d) => Ok(IEvBool(d))
|
||||
| FloatArray(d) =>
|
||||
Ok(IEvArray(d |> E.A.fmap(r => Reducer_T.IEvNumber(r))))
|
||||
| GenDistError(err) => Error(REDistributionError(err))
|
||||
}
|
||||
|
||||
let dispatch = (call: IEV.functionCall, environment) =>
|
||||
dispatchToGenericOutput(call, environment)->E.O2.fmap(genericOutputToReducerValue)
|
|
@ -1,4 +0,0 @@
|
|||
let dispatch: (
|
||||
ReducerInterface_InternalExpressionValue.functionCall,
|
||||
ReducerInterface_InternalExpressionValue.environment,
|
||||
) => option<result<ReducerInterface_InternalExpressionValue.t, Reducer_ErrorValue.errorValue>>
|
|
@ -50,7 +50,8 @@ and toStringDeclaration = d => Declaration.toString(d, r => toString(IEvLambda(r
|
|||
and toStringDistribution = dist => GenericDist.toString(dist)
|
||||
and toStringLambda = (lambdaValue: T.lambdaValue) =>
|
||||
`lambda(${Js.Array2.toString(lambdaValue.parameters)}=>internal code)`
|
||||
and toStringFunction = (lambdaValue: T.lambdaValue) => `function(${Js.Array2.toString(lambdaValue.parameters)})`
|
||||
and toStringFunction = (lambdaValue: T.lambdaValue) =>
|
||||
`function(${Js.Array2.toString(lambdaValue.parameters)})`
|
||||
and toStringNumber = aNumber => Js.String.make(aNumber)
|
||||
and toStringRecord = aMap => aMap->toStringMap
|
||||
and toStringString = aString => `'${aString}'`
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
module IEV = ReducerInterface_InternalExpressionValue
|
||||
type internalExpressionValue = IEV.t
|
||||
|
||||
module ScientificUnit = {
|
||||
let nameToMultiplier = str =>
|
||||
switch str {
|
||||
| "n" => Some(1E-9)
|
||||
| "m" => Some(1E-3)
|
||||
| "k" => Some(1E3)
|
||||
| "M" => Some(1E6)
|
||||
| "B" => Some(1E9)
|
||||
| "G" => Some(1E9)
|
||||
| "T" => Some(1E12)
|
||||
| "P" => Some(1E15)
|
||||
| _ => None
|
||||
}
|
||||
|
||||
let getMultiplier = (r: string) => {
|
||||
let match = Js.String2.match_(r, %re(`/fromUnit_([_a-zA-Z]*)/`))
|
||||
switch match {
|
||||
| Some([_, unit]) => nameToMultiplier(unit)
|
||||
| _ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let dispatch = (call: IEV.functionCall, _: GenericDist.env): option<
|
||||
result<internalExpressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
|
||||
> => {
|
||||
switch call {
|
||||
| (
|
||||
("fromUnit_n"
|
||||
| "fromUnit_m"
|
||||
| "fromUnit_k"
|
||||
| "fromUnit_M"
|
||||
| "fromUnit_B"
|
||||
| "fromUnit_G"
|
||||
| "fromUnit_T"
|
||||
| "fromUnit_P") as op,
|
||||
[IEvNumber(f)],
|
||||
) =>
|
||||
op->ScientificUnit.getMultiplier->E.O2.fmap(multiplier => Reducer_T.IEvNumber(f *. multiplier)->Ok)
|
||||
| _ => None
|
||||
}
|
||||
}
|
|
@ -1,38 +1,39 @@
|
|||
exception ErrorException = Reducer_ErrorValue.ErrorException
|
||||
|
||||
let internalStdLib: Reducer_Bindings.t = {
|
||||
let res = Reducer_Bindings.makeEmptyBindings()
|
||||
let res =
|
||||
Reducer_Bindings.makeEmptyBindings()
|
||||
->SquiggleLibrary_Math.makeBindings
|
||||
->SquiggleLibrary_Versions.makeBindings
|
||||
|
||||
let _ = res->Reducer_Bindings.set("multiply", Reducer_Expression_Lambda.makeFFILambda(
|
||||
(arguments, _, _) => {
|
||||
switch arguments {
|
||||
| [IEvNumber(x), IEvNumber(y)] => IEvNumber(x *. y)
|
||||
| _ => raise(Not_found)
|
||||
}
|
||||
}
|
||||
)->Reducer_T.IEvLambda)
|
||||
|
||||
let _ = res->Reducer_Bindings.set("$_atIndex_$", Reducer_Expression_Lambda.makeFFILambda(
|
||||
(inputs, _, _) => {
|
||||
let _ = res->Reducer_Bindings.set(
|
||||
"$_atIndex_$",
|
||||
Reducer_Expression_Lambda.makeFFILambda((inputs, _, _) => {
|
||||
switch inputs {
|
||||
| [IEvArray(aValueArray), IEvNumber(fIndex)] => {
|
||||
switch Belt.Array.get(aValueArray, Belt.Int.fromFloat(fIndex)) {
|
||||
| [IEvArray(aValueArray), IEvNumber(fIndex)] => switch Belt.Array.get(
|
||||
aValueArray,
|
||||
Belt.Int.fromFloat(fIndex),
|
||||
) {
|
||||
| Some(value) => value
|
||||
| None => REArrayIndexNotFound("Array index not found", Belt.Int.fromFloat(fIndex))->ErrorException->raise
|
||||
| None =>
|
||||
REArrayIndexNotFound("Array index not found", Belt.Int.fromFloat(fIndex))
|
||||
->ErrorException
|
||||
->raise
|
||||
}
|
||||
}
|
||||
| [IEvRecord(dict), IEvString(sIndex)] => {
|
||||
switch Belt.Map.String.get(dict, sIndex) {
|
||||
| [IEvRecord(dict), IEvString(sIndex)] => switch Belt.Map.String.get(dict, sIndex) {
|
||||
| Some(value) => value
|
||||
| None => RERecordPropertyNotFound("Record index not found", sIndex)->ErrorException->raise
|
||||
}
|
||||
}
|
||||
| _ => REOther("Trying to access key on wrong value")->ErrorException->raise
|
||||
}
|
||||
})->Reducer_T.IEvLambda,
|
||||
)
|
||||
|
||||
FunctionRegistry_Library.nonRegistryLambdas->Js.Array2.forEach(
|
||||
((name, lambda)) => {
|
||||
let _ = res->Reducer_Bindings.set(name, lambda->Reducer_T.IEvLambda)
|
||||
}
|
||||
)->Reducer_T.IEvLambda)
|
||||
)
|
||||
|
||||
// TODO:
|
||||
// () => ReducerInterface_GenericDistribution.dispatch(call, environment),
|
||||
|
@ -45,8 +46,8 @@ let internalStdLib: Reducer_Bindings.t = {
|
|||
// [x] | ("$_atIndex_$", [IEvArray(aValueArray), IEvNumber(fIndex)]) => arrayAtIndex(aValueArray, fIndex)
|
||||
// [ ] | ("$_atIndex_$", [IEvBindings(dict), IEvString(sIndex)]) => moduleAtIndex(dict, sIndex)
|
||||
// [x] | ("$_atIndex_$", [IEvRecord(dict), IEvString(sIndex)]) => recordAtIndex(dict, sIndex)
|
||||
// [ ] | ("$_constructArray_$", args) => IEvArray(args)->Ok
|
||||
// [ ] | ("$_constructRecord_$", [IEvArray(arrayOfPairs)]) => constructRecord(arrayOfPairs)
|
||||
// [x] | ("$_constructArray_$", args) => IEvArray(args)->Ok
|
||||
// [x] | ("$_constructRecord_$", [IEvArray(arrayOfPairs)]) => constructRecord(arrayOfPairs)
|
||||
// [ ] | ("concat", [IEvArray(aValueArray), IEvArray(bValueArray)]) => doAddArray(aValueArray, bValueArray)
|
||||
// [ ] | ("concat", [IEvString(aValueString), IEvString(bValueString)]) => doAddString(aValueString, bValueString)
|
||||
// [ ] | ("inspect", [value, IEvString(label)]) => inspectLabel(value, label)
|
||||
|
@ -58,19 +59,19 @@ let internalStdLib: Reducer_Bindings.t = {
|
|||
// [ ] | (_, [IEvNumber(_), IEvNumber(_)])
|
||||
// [ ] | (_, [IEvString(_), IEvString(_)]) => callMathJs(call)
|
||||
|
||||
|
||||
FunctionRegistry_Library.registry.fnNameDict->Js.Dict.keys->Js.Array2.forEach(
|
||||
(name) => {
|
||||
let _ = res->Reducer_Bindings.set(name, Reducer_Expression_Lambda.makeFFILambda(
|
||||
(arguments, environment, reducer) => {
|
||||
FunctionRegistry_Library.registry.fnNameDict
|
||||
->Js.Dict.keys
|
||||
->Js.Array2.forEach(name => {
|
||||
let _ = res->Reducer_Bindings.set(
|
||||
name,
|
||||
Reducer_Expression_Lambda.makeFFILambda((arguments, environment, reducer) => {
|
||||
switch FunctionRegistry_Library.call(name, arguments, environment, reducer) {
|
||||
| Ok(value) => value
|
||||
| Error(error) => error->Reducer_ErrorValue.ErrorException->raise
|
||||
}
|
||||
}
|
||||
)->Reducer_T.IEvLambda)
|
||||
}
|
||||
})->Reducer_T.IEvLambda,
|
||||
)
|
||||
})
|
||||
|
||||
res
|
||||
}
|
||||
|
|
|
@ -85,10 +85,7 @@ let getIncludes = (project: t, sourceId: string): ProjectItem.T.includesType =>
|
|||
let getPastChain = (project: t, sourceId: string): array<string> =>
|
||||
project->getItem(sourceId)->ProjectItem.getPastChain
|
||||
|
||||
let getIncludesAsVariables = (
|
||||
project: t,
|
||||
sourceId: string,
|
||||
): ProjectItem.T.importAsVariablesType =>
|
||||
let getIncludesAsVariables = (project: t, sourceId: string): ProjectItem.T.importAsVariablesType =>
|
||||
project->getItem(sourceId)->ProjectItem.getIncludesAsVariables
|
||||
|
||||
let getDirectIncludes = (project: t, sourceId: string): array<string> =>
|
||||
|
@ -156,12 +153,10 @@ let setEnvironment = (project: t, value: InternalExpressionValue.environment): u
|
|||
}
|
||||
|
||||
let getBindings = (project: t, sourceId: string): ProjectItem.T.bindingsArgumentType => {
|
||||
project->getContinuation(sourceId) // TODO - locals method for cleaning parent?
|
||||
project->getContinuation(sourceId)->Reducer_Bindings.locals
|
||||
}
|
||||
|
||||
let getContinuationsBefore = (project: t, sourceId: string): array<
|
||||
ProjectItem.T.continuation,
|
||||
> => {
|
||||
let getContinuationsBefore = (project: t, sourceId: string): array<ProjectItem.T.continuation> => {
|
||||
let pastNameSpaces = project->getPastChain(sourceId)->Js.Array2.map(getBindings(project, _))
|
||||
let theLength = pastNameSpaces->Js.Array2.length
|
||||
if theLength == 0 {
|
||||
|
@ -177,7 +172,8 @@ let getContinuationsBefore = (project: t, sourceId: string): array<
|
|||
|
||||
let linkDependencies = (project: t, sourceId: string): ProjectItem.T.continuation => {
|
||||
let continuationsBefore = project->getContinuationsBefore(sourceId)
|
||||
let nameSpace = Reducer_Bindings.makeEmptyBindings()->Reducer_Bindings.chainTo(continuationsBefore)
|
||||
let nameSpace =
|
||||
Reducer_Bindings.makeEmptyBindings()->Reducer_Bindings.chainTo(continuationsBefore)
|
||||
let includesAsVariables = project->getIncludesAsVariables(sourceId)
|
||||
Belt.Array.reduce(includesAsVariables, nameSpace, (currentNameSpace, (variable, includeFile)) =>
|
||||
Bindings.set(
|
||||
|
@ -242,9 +238,7 @@ let evaluate = (sourceCode: string) => {
|
|||
runAll(project)
|
||||
|
||||
(
|
||||
getResultOption(project, "main")->Belt.Option.getWithDefault(
|
||||
Reducer_T.IEvVoid->Ok,
|
||||
),
|
||||
project->getBindings("main")
|
||||
getResultOption(project, "main")->Belt.Option.getWithDefault(Reducer_T.IEvVoid->Ok),
|
||||
project->getBindings("main"),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
"use strict";
|
||||
|
||||
function peg$subclass(child, parent) {
|
||||
function C() { this.constructor = child; }
|
||||
function C() {
|
||||
this.constructor = child;
|
||||
}
|
||||
C.prototype = parent.prototype;
|
||||
child.prototype = new C();
|
||||
}
|
||||
|
@ -27,7 +29,9 @@ peg$subclass(peg$SyntaxError, Error);
|
|||
|
||||
function peg$padEnd(str, targetLength, padString) {
|
||||
padString = padString || " ";
|
||||
if (str.length > targetLength) { return str; }
|
||||
if (str.length > targetLength) {
|
||||
return str;
|
||||
}
|
||||
targetLength -= str.length;
|
||||
padString += padString.repeat(targetLength);
|
||||
return str + padString.slice(0, targetLength);
|
||||
|
@ -48,15 +52,24 @@ peg$SyntaxError.prototype.format = function(sources) {
|
|||
var loc = this.location.source + ":" + s.line + ":" + s.column;
|
||||
if (src) {
|
||||
var e = this.location.end;
|
||||
var filler = peg$padEnd("", s.line.toString().length, ' ');
|
||||
var filler = peg$padEnd("", s.line.toString().length, " ");
|
||||
var line = src[s.line - 1];
|
||||
var last = s.line === e.line ? e.column : line.length + 1;
|
||||
var hatLen = (last - s.column) || 1;
|
||||
str += "\n --> " + loc + "\n"
|
||||
+ filler + " |\n"
|
||||
+ s.line + " | " + line + "\n"
|
||||
+ filler + " | " + peg$padEnd("", s.column - 1, ' ')
|
||||
+ peg$padEnd("", hatLen, "^");
|
||||
var hatLen = last - s.column || 1;
|
||||
str +=
|
||||
"\n --> " +
|
||||
loc +
|
||||
"\n" +
|
||||
filler +
|
||||
" |\n" +
|
||||
s.line +
|
||||
" | " +
|
||||
line +
|
||||
"\n" +
|
||||
filler +
|
||||
" | " +
|
||||
peg$padEnd("", s.column - 1, " ") +
|
||||
peg$padEnd("", hatLen, "^");
|
||||
} else {
|
||||
str += "\n at " + loc;
|
||||
}
|
||||
|
@ -67,7 +80,7 @@ peg$SyntaxError.prototype.format = function(sources) {
|
|||
peg$SyntaxError.buildMessage = function (expected, found) {
|
||||
var DESCRIBE_EXPECTATION_FNS = {
|
||||
literal: function (expectation) {
|
||||
return "\"" + literalEscape(expectation.text) + "\"";
|
||||
return '"' + literalEscape(expectation.text) + '"';
|
||||
},
|
||||
|
||||
class: function (expectation) {
|
||||
|
@ -77,7 +90,9 @@ peg$SyntaxError.buildMessage = function(expected, found) {
|
|||
: classEscape(part);
|
||||
});
|
||||
|
||||
return "[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]";
|
||||
return (
|
||||
"[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]"
|
||||
);
|
||||
},
|
||||
|
||||
any: function () {
|
||||
|
@ -90,7 +105,7 @@ peg$SyntaxError.buildMessage = function(expected, found) {
|
|||
|
||||
other: function (expectation) {
|
||||
return expectation.description;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function hex(ch) {
|
||||
|
@ -100,13 +115,17 @@ peg$SyntaxError.buildMessage = function(expected, found) {
|
|||
function literalEscape(s) {
|
||||
return s
|
||||
.replace(/\\/g, "\\\\")
|
||||
.replace(/"/g, "\\\"")
|
||||
.replace(/"/g, '\\"')
|
||||
.replace(/\0/g, "\\0")
|
||||
.replace(/\t/g, "\\t")
|
||||
.replace(/\n/g, "\\n")
|
||||
.replace(/\r/g, "\\r")
|
||||
.replace(/[\x00-\x0F]/g, function(ch) { return "\\x0" + hex(ch); })
|
||||
.replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return "\\x" + hex(ch); });
|
||||
.replace(/[\x00-\x0F]/g, function (ch) {
|
||||
return "\\x0" + hex(ch);
|
||||
})
|
||||
.replace(/[\x10-\x1F\x7F-\x9F]/g, function (ch) {
|
||||
return "\\x" + hex(ch);
|
||||
});
|
||||
}
|
||||
|
||||
function classEscape(s) {
|
||||
|
@ -119,8 +138,12 @@ peg$SyntaxError.buildMessage = function(expected, found) {
|
|||
.replace(/\t/g, "\\t")
|
||||
.replace(/\n/g, "\\n")
|
||||
.replace(/\r/g, "\\r")
|
||||
.replace(/[\x00-\x0F]/g, function(ch) { return "\\x0" + hex(ch); })
|
||||
.replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return "\\x" + hex(ch); });
|
||||
.replace(/[\x00-\x0F]/g, function (ch) {
|
||||
return "\\x0" + hex(ch);
|
||||
})
|
||||
.replace(/[\x10-\x1F\x7F-\x9F]/g, function (ch) {
|
||||
return "\\x" + hex(ch);
|
||||
});
|
||||
}
|
||||
|
||||
function describeExpectation(expectation) {
|
||||
|
@ -151,17 +174,25 @@ peg$SyntaxError.buildMessage = function(expected, found) {
|
|||
return descriptions[0] + " or " + descriptions[1];
|
||||
|
||||
default:
|
||||
return descriptions.slice(0, -1).join(", ")
|
||||
+ ", or "
|
||||
+ descriptions[descriptions.length - 1];
|
||||
return (
|
||||
descriptions.slice(0, -1).join(", ") +
|
||||
", or " +
|
||||
descriptions[descriptions.length - 1]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function describeFound(found) {
|
||||
return found ? "\"" + literalEscape(found) + "\"" : "end of input";
|
||||
return found ? '"' + literalEscape(found) + '"' : "end of input";
|
||||
}
|
||||
|
||||
return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
|
||||
return (
|
||||
"Expected " +
|
||||
describeExpected(expected) +
|
||||
" but " +
|
||||
describeFound(found) +
|
||||
" found."
|
||||
);
|
||||
};
|
||||
|
||||
function peg$parse(input, options) {
|
||||
|
@ -177,7 +208,7 @@ function peg$parse(input, options) {
|
|||
var peg$c1 = "#include";
|
||||
var peg$c2 = "as";
|
||||
var peg$c3 = "'";
|
||||
var peg$c4 = "\"";
|
||||
var peg$c4 = '"';
|
||||
var peg$c5 = "//";
|
||||
var peg$c6 = "/*";
|
||||
var peg$c7 = "*/";
|
||||
|
@ -197,8 +228,8 @@ function peg$parse(input, options) {
|
|||
var peg$e3 = peg$otherExpectation("string");
|
||||
var peg$e4 = peg$literalExpectation("'", false);
|
||||
var peg$e5 = peg$classExpectation(["'"], true, false);
|
||||
var peg$e6 = peg$literalExpectation("\"", false);
|
||||
var peg$e7 = peg$classExpectation(["\""], true, false);
|
||||
var peg$e6 = peg$literalExpectation('"', false);
|
||||
var peg$e7 = peg$classExpectation(['"'], true, false);
|
||||
var peg$e8 = peg$otherExpectation("comment");
|
||||
var peg$e9 = peg$literalExpectation("//", false);
|
||||
var peg$e10 = peg$literalExpectation("/*", false);
|
||||
|
@ -212,16 +243,36 @@ function peg$parse(input, options) {
|
|||
var peg$e18 = peg$classExpectation(["\r", "\n"], true, false);
|
||||
var peg$e19 = peg$otherExpectation("identifier");
|
||||
var peg$e20 = peg$classExpectation(["_", ["a", "z"]], false, false);
|
||||
var peg$e21 = peg$classExpectation(["_", ["a", "z"], ["0", "9"]], false, true);
|
||||
var peg$e21 = peg$classExpectation(
|
||||
["_", ["a", "z"], ["0", "9"]],
|
||||
false,
|
||||
true
|
||||
);
|
||||
|
||||
var peg$f0 = function(head, tail) {return [head, ...tail].filter( e => e != '');};
|
||||
var peg$f1 = function() {return [];};
|
||||
var peg$f2 = function(file, variable) {return [!variable ? '' : variable, file]};
|
||||
var peg$f3 = function(characters) {return characters.join('');};
|
||||
var peg$f4 = function(characters) {return characters.join('');};
|
||||
var peg$f5 = function() { return '';};
|
||||
var peg$f6 = function() { return '';};
|
||||
var peg$f7 = function() {return text();};
|
||||
var peg$f0 = function (head, tail) {
|
||||
return [head, ...tail].filter((e) => e != "");
|
||||
};
|
||||
var peg$f1 = function () {
|
||||
return [];
|
||||
};
|
||||
var peg$f2 = function (file, variable) {
|
||||
return [!variable ? "" : variable, file];
|
||||
};
|
||||
var peg$f3 = function (characters) {
|
||||
return characters.join("");
|
||||
};
|
||||
var peg$f4 = function (characters) {
|
||||
return characters.join("");
|
||||
};
|
||||
var peg$f5 = function () {
|
||||
return "";
|
||||
};
|
||||
var peg$f6 = function () {
|
||||
return "";
|
||||
};
|
||||
var peg$f7 = function () {
|
||||
return text();
|
||||
};
|
||||
var peg$currPos = 0;
|
||||
var peg$savedPos = 0;
|
||||
var peg$posDetailsCache = [{ line: 1, column: 1 }];
|
||||
|
@ -235,7 +286,9 @@ function peg$parse(input, options) {
|
|||
|
||||
if ("startRule" in options) {
|
||||
if (!(options.startRule in peg$startRuleFunctions)) {
|
||||
throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
|
||||
throw new Error(
|
||||
"Can't start parsing from rule \"" + options.startRule + '".'
|
||||
);
|
||||
}
|
||||
|
||||
peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
|
||||
|
@ -253,7 +306,7 @@ function peg$parse(input, options) {
|
|||
return {
|
||||
source: peg$source,
|
||||
start: peg$savedPos,
|
||||
end: peg$currPos
|
||||
end: peg$currPos,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -262,7 +315,8 @@ function peg$parse(input, options) {
|
|||
}
|
||||
|
||||
function expected(description, location) {
|
||||
location = location !== undefined
|
||||
location =
|
||||
location !== undefined
|
||||
? location
|
||||
: peg$computeLocation(peg$savedPos, peg$currPos);
|
||||
|
||||
|
@ -274,7 +328,8 @@ function peg$parse(input, options) {
|
|||
}
|
||||
|
||||
function error(message, location) {
|
||||
location = location !== undefined
|
||||
location =
|
||||
location !== undefined
|
||||
? location
|
||||
: peg$computeLocation(peg$savedPos, peg$currPos);
|
||||
|
||||
|
@ -286,7 +341,12 @@ function peg$parse(input, options) {
|
|||
}
|
||||
|
||||
function peg$classExpectation(parts, inverted, ignoreCase) {
|
||||
return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase };
|
||||
return {
|
||||
type: "class",
|
||||
parts: parts,
|
||||
inverted: inverted,
|
||||
ignoreCase: ignoreCase,
|
||||
};
|
||||
}
|
||||
|
||||
function peg$anyExpectation() {
|
||||
|
@ -316,7 +376,7 @@ function peg$parse(input, options) {
|
|||
details = peg$posDetailsCache[p];
|
||||
details = {
|
||||
line: details.line,
|
||||
column: details.column
|
||||
column: details.column,
|
||||
};
|
||||
|
||||
while (p < pos) {
|
||||
|
@ -345,18 +405,20 @@ function peg$parse(input, options) {
|
|||
start: {
|
||||
offset: startPos,
|
||||
line: startPosDetails.line,
|
||||
column: startPosDetails.column
|
||||
column: startPosDetails.column,
|
||||
},
|
||||
end: {
|
||||
offset: endPos,
|
||||
line: endPosDetails.line,
|
||||
column: endPosDetails.column
|
||||
}
|
||||
column: endPosDetails.column,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function peg$fail(expected) {
|
||||
if (peg$currPos < peg$maxFailPos) { return; }
|
||||
if (peg$currPos < peg$maxFailPos) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (peg$currPos > peg$maxFailPos) {
|
||||
peg$maxFailPos = peg$currPos;
|
||||
|
@ -516,7 +578,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s2 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e0); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e0);
|
||||
}
|
||||
}
|
||||
peg$silentFails--;
|
||||
if (s2 === peg$FAILED) {
|
||||
|
@ -586,7 +650,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos += 8;
|
||||
} else {
|
||||
s2 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e1); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e1);
|
||||
}
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = [];
|
||||
|
@ -619,7 +685,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos += 2;
|
||||
} else {
|
||||
s7 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e2); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e2);
|
||||
}
|
||||
}
|
||||
if (s7 !== peg$FAILED) {
|
||||
s8 = [];
|
||||
|
@ -716,7 +784,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s2 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e4); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e4);
|
||||
}
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = [];
|
||||
|
@ -725,7 +795,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s4 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e5); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e5);
|
||||
}
|
||||
}
|
||||
while (s4 !== peg$FAILED) {
|
||||
s3.push(s4);
|
||||
|
@ -734,7 +806,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s4 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e5); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e5);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (input.charCodeAt(peg$currPos) === 39) {
|
||||
|
@ -742,7 +816,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s4 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e4); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e4);
|
||||
}
|
||||
}
|
||||
if (s4 !== peg$FAILED) {
|
||||
s1 = s3;
|
||||
|
@ -767,7 +843,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s2 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e6); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e6);
|
||||
}
|
||||
}
|
||||
if (s2 !== peg$FAILED) {
|
||||
s3 = [];
|
||||
|
@ -776,7 +854,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s4 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e7); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e7);
|
||||
}
|
||||
}
|
||||
while (s4 !== peg$FAILED) {
|
||||
s3.push(s4);
|
||||
|
@ -785,7 +865,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s4 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e7); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e7);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (input.charCodeAt(peg$currPos) === 34) {
|
||||
|
@ -793,7 +875,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s4 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e6); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e6);
|
||||
}
|
||||
}
|
||||
if (s4 !== peg$FAILED) {
|
||||
s1 = s3;
|
||||
|
@ -814,7 +898,9 @@ function peg$parse(input, options) {
|
|||
peg$silentFails--;
|
||||
if (s0 === peg$FAILED) {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e3); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e3);
|
||||
}
|
||||
}
|
||||
|
||||
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
|
||||
|
@ -877,7 +963,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos += 2;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e9); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e9);
|
||||
}
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = [];
|
||||
|
@ -910,7 +998,9 @@ function peg$parse(input, options) {
|
|||
peg$silentFails--;
|
||||
if (s0 === peg$FAILED) {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e8); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e8);
|
||||
}
|
||||
}
|
||||
|
||||
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
|
||||
|
@ -937,7 +1027,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos += 2;
|
||||
} else {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e10); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e10);
|
||||
}
|
||||
}
|
||||
if (s1 !== peg$FAILED) {
|
||||
s2 = [];
|
||||
|
@ -946,7 +1038,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e11); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e11);
|
||||
}
|
||||
}
|
||||
while (s3 !== peg$FAILED) {
|
||||
s2.push(s3);
|
||||
|
@ -955,7 +1049,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e11); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e11);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (input.substr(peg$currPos, 2) === peg$c7) {
|
||||
|
@ -963,7 +1059,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos += 2;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e12); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e12);
|
||||
}
|
||||
}
|
||||
if (s3 !== peg$FAILED) {
|
||||
peg$savedPos = s0;
|
||||
|
@ -979,7 +1077,9 @@ function peg$parse(input, options) {
|
|||
peg$silentFails--;
|
||||
if (s0 === peg$FAILED) {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e8); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e8);
|
||||
}
|
||||
}
|
||||
|
||||
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
|
||||
|
@ -1005,12 +1105,16 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s0 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e14); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e14);
|
||||
}
|
||||
}
|
||||
peg$silentFails--;
|
||||
if (s0 === peg$FAILED) {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e13); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e13);
|
||||
}
|
||||
}
|
||||
|
||||
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
|
||||
|
@ -1036,12 +1140,16 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s0 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e16); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e16);
|
||||
}
|
||||
}
|
||||
peg$silentFails--;
|
||||
if (s0 === peg$FAILED) {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e15); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e15);
|
||||
}
|
||||
}
|
||||
|
||||
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
|
||||
|
@ -1067,12 +1175,16 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s0 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e18); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e18);
|
||||
}
|
||||
}
|
||||
peg$silentFails--;
|
||||
if (s0 === peg$FAILED) {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e17); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e17);
|
||||
}
|
||||
}
|
||||
|
||||
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
|
||||
|
@ -1101,7 +1213,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e20); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e20);
|
||||
}
|
||||
}
|
||||
if (s3 !== peg$FAILED) {
|
||||
while (s3 !== peg$FAILED) {
|
||||
|
@ -1111,7 +1225,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s3 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e20); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e20);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1124,7 +1240,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s4 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e21); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e21);
|
||||
}
|
||||
}
|
||||
while (s4 !== peg$FAILED) {
|
||||
s3.push(s4);
|
||||
|
@ -1133,7 +1251,9 @@ function peg$parse(input, options) {
|
|||
peg$currPos++;
|
||||
} else {
|
||||
s4 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e21); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e21);
|
||||
}
|
||||
}
|
||||
}
|
||||
s2 = [s2, s3];
|
||||
|
@ -1150,7 +1270,9 @@ function peg$parse(input, options) {
|
|||
peg$silentFails--;
|
||||
if (s0 === peg$FAILED) {
|
||||
s1 = peg$FAILED;
|
||||
if (peg$silentFails === 0) { peg$fail(peg$e19); }
|
||||
if (peg$silentFails === 0) {
|
||||
peg$fail(peg$e19);
|
||||
}
|
||||
}
|
||||
|
||||
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
|
||||
|
@ -1179,5 +1301,5 @@ function peg$parse(input, options) {
|
|||
|
||||
module.exports = {
|
||||
SyntaxError: peg$SyntaxError,
|
||||
parse: peg$parse
|
||||
parse: peg$parse,
|
||||
};
|
||||
|
|
|
@ -28,3 +28,4 @@
|
|||
// environment: environment,
|
||||
// }
|
||||
// }
|
||||
|
||||
|
|
|
@ -81,8 +81,10 @@ let setRawParse = (r: t, rawParse: T.rawParseArgumentType): t =>
|
|||
let setExpression = (r: t, expression: T.expressionArgumentType): t =>
|
||||
{...r, expression: Some(expression)}->touchExpression
|
||||
|
||||
let setContinuation = (r: t, continuation: T.continuationArgumentType): t =>
|
||||
{...r, continuation: continuation}
|
||||
let setContinuation = (r: t, continuation: T.continuationArgumentType): t => {
|
||||
...r,
|
||||
continuation: continuation,
|
||||
}
|
||||
|
||||
let setResult = (r: t, result: T.resultArgumentType): t => {
|
||||
...r,
|
||||
|
@ -115,10 +117,10 @@ let setIncludes = (this: t, includes: T.includesType): t => {
|
|||
includes: includes,
|
||||
}
|
||||
|
||||
let setImportAsVariables = (
|
||||
this: t,
|
||||
includeAsVariables: T.importAsVariablesType,
|
||||
): t => {...this, includeAsVariables: includeAsVariables}
|
||||
let setImportAsVariables = (this: t, includeAsVariables: T.importAsVariablesType): t => {
|
||||
...this,
|
||||
includeAsVariables: includeAsVariables,
|
||||
}
|
||||
|
||||
let setDirectImports = (this: t, directIncludes: array<string>): t => {
|
||||
...this,
|
||||
|
@ -161,37 +163,25 @@ let buildExpression = (this: t): t => {
|
|||
switch this->getExpression {
|
||||
| Some(_) => this // cached
|
||||
| None =>
|
||||
this
|
||||
->doBuildExpression
|
||||
->Belt.Option.map(setExpression(this, _))
|
||||
->E.O2.defaultFn(() => this)
|
||||
this->doBuildExpression->Belt.Option.map(setExpression(this, _))->E.O2.defaultFn(() => this)
|
||||
}
|
||||
}
|
||||
|
||||
let failRun = (
|
||||
this: t,
|
||||
e: Reducer_ErrorValue.errorValue
|
||||
): t => this->setResult(e->Error)->setContinuation(Reducer_Bindings.makeEmptyBindings())
|
||||
let failRun = (this: t, e: Reducer_ErrorValue.errorValue): t =>
|
||||
this->setResult(e->Error)->setContinuation(Reducer_Bindings.makeEmptyBindings())
|
||||
|
||||
let doRun = (
|
||||
this: t,
|
||||
context: Reducer_T.context
|
||||
): t =>
|
||||
let doRun = (this: t, context: Reducer_T.context): t =>
|
||||
switch this->getExpression {
|
||||
| Some(expressionResult) => {
|
||||
switch expressionResult {
|
||||
| Ok(expression) => {
|
||||
try {
|
||||
| Some(expressionResult) => switch expressionResult {
|
||||
| Ok(expression) => try {
|
||||
let result = Reducer_Expression.evaluate(expression, context)
|
||||
this->setResult(result->Ok)->setContinuation(context.bindings)
|
||||
} catch {
|
||||
| Reducer_ErrorValue.ErrorException(e) => this->failRun(e)
|
||||
| _ => this->failRun(RETodo("unhandled rescript exception"))
|
||||
}
|
||||
}
|
||||
| Error(e) => this->failRun(e)
|
||||
}
|
||||
}
|
||||
| None => this->failRun(RETodo("attempt to run without expression"))
|
||||
}
|
||||
|
||||
|
|
|
@ -31,10 +31,10 @@ let rec topologicalSortUtil = (
|
|||
}
|
||||
|
||||
let getTopologicalSort = (this: t): array<string> => {
|
||||
let (_visited, stack) = this->getSourceIds->Belt.Array.reduce((Belt.Map.String.empty, list{}), (
|
||||
(currVisited, currStack),
|
||||
currId,
|
||||
) =>
|
||||
let (_visited, stack) =
|
||||
this
|
||||
->getSourceIds
|
||||
->Belt.Array.reduce((Belt.Map.String.empty, list{}), ((currVisited, currStack), currId) =>
|
||||
if !Belt.Map.String.getWithDefault(currVisited, currId, false) {
|
||||
topologicalSortUtil(this, currId, (currVisited, currStack))
|
||||
} else {
|
||||
|
|
|
@ -14,9 +14,7 @@ let availableNumbers: array<(string, float)> = [
|
|||
]
|
||||
|
||||
let mathBindings: Bindings.t =
|
||||
availableNumbers
|
||||
->E.A2.fmap(((name, v)) => (name, Reducer_T.IEvNumber(v)))
|
||||
->Bindings.fromArray
|
||||
availableNumbers->E.A2.fmap(((name, v)) => (name, Reducer_T.IEvNumber(v)))->Bindings.fromArray
|
||||
|
||||
let makeBindings = (previousBindings: Bindings.t): Bindings.t =>
|
||||
previousBindings->Bindings.mergeFrom(mathBindings)
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
module Bindings = Reducer_Bindings
|
||||
|
||||
let bindings: Reducer_T.nameSpace =
|
||||
[
|
||||
("System.version", Reducer_T.IEvString("0.4.0-dev")),
|
||||
]->Bindings.fromArray
|
||||
[("System.version", Reducer_T.IEvString("0.4.0-dev"))]->Bindings.fromArray
|
||||
|
||||
let makeBindings = (previousBindings: Reducer_T.nameSpace): Reducer_T.nameSpace =>
|
||||
previousBindings->Bindings.mergeFrom(bindings)
|
||||
|
|
|
@ -7,3 +7,4 @@
|
|||
// | exception _ => Error("MathJS Parse Error")
|
||||
// | j => Ok(j)
|
||||
// }
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user