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.
|
Answer all the source ids of all the sources in the project.
|
||||||
*/
|
*/
|
||||||
@genType
|
@genType
|
||||||
let getSourceIds = (project: reducerProject): array<string> =>
|
let getSourceIds = (project: reducerProject): array<string> => project->Private.getSourceIds
|
||||||
project->Private.getSourceIds
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Sets the source for a given source Id.
|
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
|
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
|
@genType
|
||||||
let clean = (project: reducerProject, sourceId: string): unit =>
|
let clean = (project: reducerProject, sourceId: string): unit => project->Private.clean(sourceId)
|
||||||
project->Private.clean(sourceId)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Cleans all the compilation artifacts in all of the project
|
Cleans all the compilation artifacts in all of the project
|
||||||
*/
|
*/
|
||||||
@genType
|
@genType
|
||||||
let cleanAll = (project: reducerProject): unit =>
|
let cleanAll = (project: reducerProject): unit => project->Private.cleanAll
|
||||||
project->Private.cleanAll
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Cleans results. Compilation stays untouched to be able to re-run the source.
|
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.
|
Cleans all results. Compilations remains untouched to rerun the source.
|
||||||
*/
|
*/
|
||||||
@genType
|
@genType
|
||||||
let cleanAllResults = (project: reducerProject): unit =>
|
let cleanAllResults = (project: reducerProject): unit => project->Private.cleanAllResults
|
||||||
project->Private.cleanAllResults
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
To set the includes one first has to call "parseIncludes". The parsed includes or the parser error is returned.
|
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.
|
Get the run order for the sources in the project.
|
||||||
*/
|
*/
|
||||||
@genType
|
@genType
|
||||||
let getRunOrder = (project: reducerProject): array<string> =>
|
let getRunOrder = (project: reducerProject): array<string> => project->Private.getRunOrder
|
||||||
project->Private.getRunOrder
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get the run order to get the results of this specific source
|
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.
|
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
|
@genType
|
||||||
let run = (project: reducerProject, sourceId: string): unit =>
|
let run = (project: reducerProject, sourceId: string): unit => project->Private.run(sourceId)
|
||||||
project->Private.run(sourceId)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Runs all of the sources in a project. Their results and bindings will be available
|
Runs all of the sources in a project. Their results and bindings will be available
|
||||||
*/
|
*/
|
||||||
@genType
|
@genType
|
||||||
let runAll = (project: reducerProject): unit =>
|
let runAll = (project: reducerProject): unit => project->Private.runAll
|
||||||
project->Private.runAll
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get the bindings after running this source fil. The bindings are local to the source
|
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 internalExpressionValue = Reducer_T.value
|
||||||
type internalExpressionValueType = ReducerInterface_InternalExpressionValue.internalExpressionValueType
|
type internalExpressionValueType = ReducerInterface_InternalExpressionValue.internalExpressionValueType
|
||||||
|
type errorValue = Reducer_ErrorValue.errorValue
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function Registry "Type". A type, without any other information.
|
Function Registry "Type". A type, without any other information.
|
||||||
|
@ -48,7 +49,7 @@ type fnDefinition = {
|
||||||
array<frValue>,
|
array<frValue>,
|
||||||
Reducer_T.environment,
|
Reducer_T.environment,
|
||||||
Reducer_T.reducerFn,
|
Reducer_T.reducerFn,
|
||||||
) => result<internalExpressionValue, string>,
|
) => result<internalExpressionValue, errorValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type function = {
|
type function = {
|
||||||
|
@ -206,7 +207,7 @@ module FnDefinition = {
|
||||||
let argValues = FRType.matchWithExpressionValueArray(t.inputs, args)
|
let argValues = FRType.matchWithExpressionValueArray(t.inputs, args)
|
||||||
switch argValues {
|
switch argValues {
|
||||||
| Some(values) => t.run(args, values, env, reducer)
|
| Some(values) => t.run(args, values, env, reducer)
|
||||||
| None => Error("Incorrect Types")
|
| None => REOther("Incorrect Types")->Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,15 +270,18 @@ module Registry = {
|
||||||
let res: fnNameDict = Js.Dict.empty()
|
let res: fnNameDict = Js.Dict.empty()
|
||||||
r->Js.Array2.forEach(fn =>
|
r->Js.Array2.forEach(fn =>
|
||||||
fn.definitions->Js.Array2.forEach(def => {
|
fn.definitions->Js.Array2.forEach(def => {
|
||||||
let nameWithNamespace = `${fn.nameSpace}.${def.name}`
|
let names =
|
||||||
let nameWithoutNamespace = def.name
|
[
|
||||||
let names = fn.requiresNamespace ? [nameWithNamespace] : [nameWithNamespace, nameWithoutNamespace]
|
fn.nameSpace == "" ? [] : [`${fn.nameSpace}.${def.name}`],
|
||||||
|
fn.requiresNamespace ? [] : [def.name],
|
||||||
|
]->E.A.concatMany
|
||||||
|
|
||||||
names->Js.Array2.forEach(name => {
|
names->Js.Array2.forEach(name => {
|
||||||
switch res->Js.Dict.get(name) {
|
switch res->Js.Dict.get(name) {
|
||||||
| Some(fns) => {
|
| Some(fns) => {
|
||||||
let _ = fns->Js.Array2.push(def)
|
let _ = fns->Js.Array2.push(def)
|
||||||
}
|
}
|
||||||
| None => res->Js.Dict.set(name, [def])
|
| None => res->Js.Dict.set(name, [def])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -296,9 +300,9 @@ module Registry = {
|
||||||
args: array<internalExpressionValue>,
|
args: array<internalExpressionValue>,
|
||||||
env: Reducer_T.environment,
|
env: Reducer_T.environment,
|
||||||
reducer: Reducer_T.reducerFn,
|
reducer: Reducer_T.reducerFn,
|
||||||
): result<internalExpressionValue, Reducer_ErrorValue.errorValue> => {
|
): result<internalExpressionValue, errorValue> => {
|
||||||
switch Js.Dict.get(registry.fnNameDict, fnName) {
|
switch Js.Dict.get(registry.fnNameDict, fnName) {
|
||||||
| Some(definitions) => {
|
| Some(definitions) => {
|
||||||
let showNameMatchDefinitions = () => {
|
let showNameMatchDefinitions = () => {
|
||||||
let defsString =
|
let defsString =
|
||||||
definitions
|
definitions
|
||||||
|
@ -310,13 +314,12 @@ module Registry = {
|
||||||
|
|
||||||
let match = definitions->Js.Array2.find(def => def->FnDefinition.isMatch(args))
|
let match = definitions->Js.Array2.find(def => def->FnDefinition.isMatch(args))
|
||||||
switch match {
|
switch match {
|
||||||
| Some(def) => def->FnDefinition.run(args, env, reducer)->E.R2.errMap(e => Reducer_ErrorValue.REOther(e))
|
| Some(def) =>
|
||||||
| None => {
|
def->FnDefinition.run(args, env, reducer)
|
||||||
Reducer_ErrorValue.REOther(showNameMatchDefinitions())->Error
|
| None => REOther(showNameMatchDefinitions())->Error
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| None => Reducer_ErrorValue.RESymbolNotFound(fnName)->Error
|
| None => RESymbolNotFound(fnName)->Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
open FunctionRegistry_Core
|
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 = {
|
module Wrappers = {
|
||||||
let symbolic = r => DistributionTypes.Symbolic(r)
|
let symbolic = r => DistributionTypes.Symbolic(r)
|
||||||
|
@ -15,7 +17,7 @@ module Wrappers = {
|
||||||
let evArrayOfEvNumber = xs => xs->Belt.Array.map(evNumber)->evArray
|
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 = {
|
module Prepare = {
|
||||||
type t = frValue
|
type t = frValue
|
||||||
|
@ -27,19 +29,19 @@ module Prepare = {
|
||||||
let twoArgs = (inputs: ts): result<ts, err> =>
|
let twoArgs = (inputs: ts): result<ts, err> =>
|
||||||
switch inputs {
|
switch inputs {
|
||||||
| [FRValueRecord([(_, n1), (_, n2)])] => Ok([n1, n2])
|
| [FRValueRecord([(_, n1), (_, n2)])] => Ok([n1, n2])
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleErrorString)
|
||||||
}
|
}
|
||||||
|
|
||||||
let threeArgs = (inputs: ts): result<ts, err> =>
|
let threeArgs = (inputs: ts): result<ts, err> =>
|
||||||
switch inputs {
|
switch inputs {
|
||||||
| [FRValueRecord([(_, n1), (_, n2), (_, n3)])] => Ok([n1, n2, n3])
|
| [FRValueRecord([(_, n1), (_, n2), (_, n3)])] => Ok([n1, n2, n3])
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleErrorString)
|
||||||
}
|
}
|
||||||
|
|
||||||
let toArgs = (inputs: ts): result<ts, err> =>
|
let toArgs = (inputs: ts): result<ts, err> =>
|
||||||
switch inputs {
|
switch inputs {
|
||||||
| [FRValueRecord(args)] => args->E.A2.fmap(((_, b)) => b)->Ok
|
| [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> =>
|
let openA = (inputs: t): result<ts, err> =>
|
||||||
switch inputs {
|
switch inputs {
|
||||||
| FRValueArray(n) => Ok(n)
|
| FRValueArray(n) => Ok(n)
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleErrorString)
|
||||||
}
|
}
|
||||||
|
|
||||||
let arrayOfArrays = (inputs: t): result<array<ts>, err> =>
|
let arrayOfArrays = (inputs: t): result<array<ts>, err> =>
|
||||||
switch inputs {
|
switch inputs {
|
||||||
| FRValueArray(n) => n->E.A2.fmap(openA)->E.A.R.firstErrorOrOpen
|
| 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> => {
|
let twoDistOrNumber = (values: ts): result<(frValueDistOrNumber, frValueDistOrNumber), err> => {
|
||||||
switch values {
|
switch values {
|
||||||
| [FRValueDistOrNumber(a1), FRValueDistOrNumber(a2)] => Ok(a1, a2)
|
| [FRValueDistOrNumber(a1), FRValueDistOrNumber(a2)] => Ok(a1, a2)
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleErrorString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,28 +74,28 @@ module Prepare = {
|
||||||
> => {
|
> => {
|
||||||
switch values {
|
switch values {
|
||||||
| [FRValueDist(a1), FRValueDist(a2)] => Ok(a1, a2)
|
| [FRValueDist(a1), FRValueDist(a2)] => Ok(a1, a2)
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleErrorString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let twoNumbers = (values: ts): result<(float, float), err> => {
|
let twoNumbers = (values: ts): result<(float, float), err> => {
|
||||||
switch values {
|
switch values {
|
||||||
| [FRValueNumber(a1), FRValueNumber(a2)] => Ok(a1, a2)
|
| [FRValueNumber(a1), FRValueNumber(a2)] => Ok(a1, a2)
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleErrorString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let threeNumbers = (values: ts): result<(float, float, float), err> => {
|
let threeNumbers = (values: ts): result<(float, float, float), err> => {
|
||||||
switch values {
|
switch values {
|
||||||
| [FRValueNumber(a1), FRValueNumber(a2), FRValueNumber(a3)] => Ok(a1, a2, a3)
|
| [FRValueNumber(a1), FRValueNumber(a2), FRValueNumber(a3)] => Ok(a1, a2, a3)
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleErrorString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let oneDistOrNumber = (values: ts): result<frValueDistOrNumber, err> => {
|
let oneDistOrNumber = (values: ts): result<frValueDistOrNumber, err> => {
|
||||||
switch values {
|
switch values {
|
||||||
| [FRValueDistOrNumber(a1)] => Ok(a1)
|
| [FRValueDistOrNumber(a1)] => Ok(a1)
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleErrorString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,14 +126,14 @@ module Prepare = {
|
||||||
let oneNumber = (values: t): result<float, err> => {
|
let oneNumber = (values: t): result<float, err> => {
|
||||||
switch values {
|
switch values {
|
||||||
| FRValueNumber(a1) => Ok(a1)
|
| FRValueNumber(a1) => Ok(a1)
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleErrorString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let oneDict = (values: t): result<Js.Dict.t<frValue>, err> => {
|
let oneDict = (values: t): result<Js.Dict.t<frValue>, err> => {
|
||||||
switch values {
|
switch values {
|
||||||
| FRValueDict(a1) => Ok(a1)
|
| FRValueDict(a1) => Ok(a1)
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleErrorString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,6 +231,7 @@ module DefineFn = {
|
||||||
->E.R.bind(Prepare.oneNumber)
|
->E.R.bind(Prepare.oneNumber)
|
||||||
->E.R2.fmap(fn)
|
->E.R2.fmap(fn)
|
||||||
->E.R2.fmap(Wrappers.evNumber)
|
->E.R2.fmap(Wrappers.evNumber)
|
||||||
|
->E.R2.errMap(e => Reducer_ErrorValue.REOther(e))
|
||||||
},
|
},
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
|
@ -237,7 +240,11 @@ module DefineFn = {
|
||||||
~name,
|
~name,
|
||||||
~inputs=[FRTypeNumber, FRTypeNumber],
|
~inputs=[FRTypeNumber, FRTypeNumber],
|
||||||
~run=(_, inputs, _, _) => {
|
~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,
|
~name,
|
||||||
~inputs=[FRTypeNumber, FRTypeNumber, FRTypeNumber],
|
~inputs=[FRTypeNumber, FRTypeNumber, FRTypeNumber],
|
||||||
~run=(_, inputs, _, _) => {
|
~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_Number.library,
|
||||||
FR_Pointset.library,
|
FR_Pointset.library,
|
||||||
FR_Scoring.library,
|
FR_Scoring.library,
|
||||||
|
FR_GenericDist.library,
|
||||||
|
FR_Units.library,
|
||||||
])
|
])
|
||||||
|
|
||||||
let registry = FunctionRegistry_Core.Registry.make(fnList)
|
let registry = FunctionRegistry_Core.Registry.make(fnList)
|
||||||
let call = FunctionRegistry_Core.Registry.call(registry)
|
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_Core
|
||||||
open FunctionRegistry_Helpers
|
open FunctionRegistry_Helpers
|
||||||
|
|
||||||
let nameSpace = "Builtin"
|
let nameSpace = "" // no namespaced versions
|
||||||
|
|
||||||
type simpleDefinition = {
|
type simpleDefinition = {
|
||||||
inputs: array<frType>,
|
inputs: array<frType>,
|
||||||
fn: (array<internalExpressionValue>) => result<internalExpressionValue, string>,
|
fn: array<internalExpressionValue> => result<internalExpressionValue, errorValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
let makeFnMany = (name: string, definitions: array<simpleDefinition>) =>
|
let makeFnMany = (name: string, definitions: array<simpleDefinition>) =>
|
||||||
Function.make(
|
Function.make(
|
||||||
~name=name,
|
~name,
|
||||||
~nameSpace,
|
~nameSpace,
|
||||||
~requiresNamespace=false,
|
~requiresNamespace=false,
|
||||||
~definitions=definitions->Js.Array2.map(
|
~definitions=definitions->Js.Array2.map(({inputs, fn}) =>
|
||||||
({ inputs, fn }) => FnDefinition.make(
|
FnDefinition.make(~name, ~inputs, ~run=(inputs, _, _, _) => fn(inputs), ())
|
||||||
~name=name,
|
|
||||||
~inputs=inputs,
|
|
||||||
~run=(inputs, _, _, _) => fn(inputs),
|
|
||||||
()
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
|
|
||||||
let makeFn = (name: string, inputs: array<frType>, fn: (array<internalExpressionValue>) => result<internalExpressionValue, string>) =>
|
let makeFn = (
|
||||||
makeFnMany(name, [{ inputs, fn }])
|
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 = [
|
let library = [
|
||||||
// TODO - other MathJS
|
// TODO - other MathJS
|
||||||
Function.make(
|
makeBinaryFn("add", (x, y) => x +. y),
|
||||||
~name="add",
|
makeBinaryFn("subtract", (x, y) => x -. y),
|
||||||
~nameSpace,
|
makeBinaryFn("multiply", (x, y) => x *. y),
|
||||||
~requiresNamespace=false,
|
makeBinaryFn("divide", (x, y) => x /. y),
|
||||||
~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)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
()
|
|
||||||
),
|
|
||||||
],
|
|
||||||
(),
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -71,13 +71,14 @@ module Integration = {
|
||||||
aLambda,
|
aLambda,
|
||||||
[pointAsInternalExpression],
|
[pointAsInternalExpression],
|
||||||
environment,
|
environment,
|
||||||
reducer
|
reducer,
|
||||||
)
|
)
|
||||||
let result = switch resultAsInternalExpression {
|
let result = switch resultAsInternalExpression {
|
||||||
| Reducer_T.IEvNumber(x) => Ok(x)
|
| Reducer_T.IEvNumber(x) => Ok(x)
|
||||||
| _ =>
|
| _ =>
|
||||||
Error(
|
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
|
result
|
||||||
|
@ -141,11 +142,11 @@ module Integration = {
|
||||||
resultWithOuterPoints
|
resultWithOuterPoints
|
||||||
}
|
}
|
||||||
| Error(b) =>
|
| 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." ++
|
"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: " ++
|
"Original error: " ++
|
||||||
b,
|
b->Reducer_ErrorValue.errorToString
|
||||||
)
|
)->Reducer_ErrorValue.REOther->Error
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -168,7 +169,7 @@ module Integration = {
|
||||||
~run=(inputs, _, env, reducer) => {
|
~run=(inputs, _, env, reducer) => {
|
||||||
let result = switch inputs {
|
let result = switch inputs {
|
||||||
| [_, _, _, IEvNumber(0.0)] =>
|
| [_, _, _, 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),
|
IEvLambda(aLambda),
|
||||||
IEvNumber(min),
|
IEvNumber(min),
|
||||||
|
@ -185,7 +186,7 @@ module Integration = {
|
||||||
)
|
)
|
||||||
| _ =>
|
| _ =>
|
||||||
Error(
|
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
|
result
|
||||||
|
@ -208,7 +209,9 @@ module Integration = {
|
||||||
~run=(inputs, _, env, reducer) => {
|
~run=(inputs, _, env, reducer) => {
|
||||||
let result = switch inputs {
|
let result = switch inputs {
|
||||||
| [_, _, _, IEvNumber(0.0)] =>
|
| [_, _, _, 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)] =>
|
| [IEvLambda(aLambda), IEvNumber(min), IEvNumber(max), IEvNumber(epsilon)] =>
|
||||||
Helpers.integrateFunctionBetweenWithNumIntegrationPoints(
|
Helpers.integrateFunctionBetweenWithNumIntegrationPoints(
|
||||||
aLambda,
|
aLambda,
|
||||||
|
@ -218,12 +221,13 @@ module Integration = {
|
||||||
env,
|
env,
|
||||||
reducer,
|
reducer,
|
||||||
)->E.R2.errMap(b =>
|
)->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
|
result
|
||||||
},
|
},
|
||||||
|
@ -239,7 +243,7 @@ module DiminishingReturns = {
|
||||||
module Helpers = {
|
module Helpers = {
|
||||||
type diminishingReturnsAccumulatorInner = {
|
type diminishingReturnsAccumulatorInner = {
|
||||||
optimalAllocations: array<float>,
|
optimalAllocations: array<float>,
|
||||||
currentMarginalReturns: result<array<float>, string>,
|
currentMarginalReturns: result<array<float>, errorValue>,
|
||||||
}
|
}
|
||||||
let findBiggestElementIndex = xs =>
|
let findBiggestElementIndex = xs =>
|
||||||
E.A.reducei(xs, 0, (acc, newElement, index) => {
|
E.A.reducei(xs, 0, (acc, newElement, index) => {
|
||||||
|
@ -248,7 +252,7 @@ module DiminishingReturns = {
|
||||||
| false => acc
|
| 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.
|
// 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
|
The key idea for this function is that
|
||||||
|
@ -273,7 +277,7 @@ module DiminishingReturns = {
|
||||||
funds,
|
funds,
|
||||||
approximateIncrement,
|
approximateIncrement,
|
||||||
environment,
|
environment,
|
||||||
reducer
|
reducer,
|
||||||
) => {
|
) => {
|
||||||
switch (
|
switch (
|
||||||
E.A.length(lambdas) > 1,
|
E.A.length(lambdas) > 1,
|
||||||
|
@ -283,19 +287,23 @@ module DiminishingReturns = {
|
||||||
) {
|
) {
|
||||||
| (false, _, _, _) =>
|
| (false, _, _, _) =>
|
||||||
Error(
|
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, _, _) =>
|
| (_, false, _, _) =>
|
||||||
Error(
|
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, _) =>
|
| (_, _, false, _) =>
|
||||||
Error(
|
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) =>
|
| (_, _, _, false) =>
|
||||||
Error(
|
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) => {
|
| (true, true, true, true) => {
|
||||||
let applyFunctionAtPoint = (lambda, point: float) => {
|
let applyFunctionAtPoint = (lambda, point: float) => {
|
||||||
|
@ -305,13 +313,14 @@ module DiminishingReturns = {
|
||||||
lambda,
|
lambda,
|
||||||
[pointAsInternalExpression],
|
[pointAsInternalExpression],
|
||||||
environment,
|
environment,
|
||||||
reducer
|
reducer,
|
||||||
)
|
)
|
||||||
switch resultAsInternalExpression {
|
switch resultAsInternalExpression {
|
||||||
| Reducer_T.IEvNumber(x) => Ok(x)
|
| Reducer_T.IEvNumber(x) => Ok(x)
|
||||||
| _ =>
|
| _ =>
|
||||||
Error(
|
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 {
|
switch innerLambda {
|
||||||
| Reducer_T.IEvLambda(lambda) => Ok(lambda)
|
| 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)
|
}, innerlambdas)
|
||||||
let wrappedLambdas = E.A.R.firstErrorOrOpen(individuallyWrappedLambdas)
|
let wrappedLambdas = E.A.R.firstErrorOrOpen(individuallyWrappedLambdas)
|
||||||
|
@ -424,7 +433,7 @@ module DiminishingReturns = {
|
||||||
}
|
}
|
||||||
result
|
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]))
|
->E.A2.fmap(((key, value)) => Wrappers.evArray([IEvString(key), value]))
|
||||||
->Wrappers.evArray
|
->Wrappers.evArray
|
||||||
|
|
||||||
let fromList = (items: array<internalExpressionValue>): result<internalExpressionValue, string> =>
|
let fromList = (items: array<internalExpressionValue>): result<internalExpressionValue, errorValue> =>
|
||||||
items
|
items
|
||||||
->E.A2.fmap(item => {
|
->E.A2.fmap(item => {
|
||||||
switch (item: internalExpressionValue) {
|
switch (item: internalExpressionValue) {
|
||||||
|
@ -80,7 +80,8 @@ let library = [
|
||||||
->E.R2.fmap(E.Dict.concatMany)
|
->E.R2.fmap(E.Dict.concatMany)
|
||||||
->E.R2.fmap(Js.Dict.map((. r) => FunctionRegistry_Core.FRType.matchReverse(r)))
|
->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(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
|
r
|
||||||
->E.R.bind(Process.DistOrNumberToDist.twoValuesUsingSymbolicDist(~fn, ~values=_, ~env))
|
->E.R.bind(Process.DistOrNumberToDist.twoValuesUsingSymbolicDist(~fn, ~values=_, ~env))
|
||||||
->E.R2.fmap(Wrappers.evDistribution)
|
->E.R2.fmap(Wrappers.evDistribution)
|
||||||
|
->E.R2.errMap(e => Reducer_ErrorValue.REOther(e))
|
||||||
|
|
||||||
let make = (name, fn) => {
|
let make = (name, fn) => {
|
||||||
FnDefinition.make(
|
FnDefinition.make(
|
||||||
~name,
|
~name,
|
||||||
~inputs=[FRTypeDistOrNumber, FRTypeDistOrNumber],
|
~inputs=[FRTypeDistOrNumber, FRTypeDistOrNumber],
|
||||||
~run=(_, inputs, env, _) =>
|
~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,
|
~name,
|
||||||
~inputs=[FRTypeRecord([("p5", FRTypeDistOrNumber), ("p95", FRTypeDistOrNumber)])],
|
~inputs=[FRTypeRecord([("p5", FRTypeDistOrNumber), ("p95", FRTypeDistOrNumber)])],
|
||||||
~run=(_, inputs, env, _) =>
|
~run=(_, inputs, env, _) =>
|
||||||
inputs
|
inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env),
|
||||||
->Prepare.ToValueTuple.Record.twoDistOrNumber
|
|
||||||
->process(~fn, ~env=env),
|
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -44,9 +43,7 @@ module DistributionCreation = {
|
||||||
~name,
|
~name,
|
||||||
~inputs=[FRTypeRecord([("mean", FRTypeDistOrNumber), ("stdev", FRTypeDistOrNumber)])],
|
~inputs=[FRTypeRecord([("mean", FRTypeDistOrNumber), ("stdev", FRTypeDistOrNumber)])],
|
||||||
~run=(_, inputs, env, _) =>
|
~run=(_, inputs, env, _) =>
|
||||||
inputs
|
inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env),
|
||||||
->Prepare.ToValueTuple.Record.twoDistOrNumber
|
|
||||||
->process(~fn, ~env=env),
|
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -57,13 +54,14 @@ module DistributionCreation = {
|
||||||
r
|
r
|
||||||
->E.R.bind(Process.DistOrNumberToDist.oneValueUsingSymbolicDist(~fn, ~value=_, ~env))
|
->E.R.bind(Process.DistOrNumberToDist.oneValueUsingSymbolicDist(~fn, ~value=_, ~env))
|
||||||
->E.R2.fmap(Wrappers.evDistribution)
|
->E.R2.fmap(Wrappers.evDistribution)
|
||||||
|
->E.R2.errMap(e => Reducer_ErrorValue.REOther(e))
|
||||||
|
|
||||||
let make = (name, fn) =>
|
let make = (name, fn) =>
|
||||||
FnDefinition.make(
|
FnDefinition.make(
|
||||||
~name,
|
~name,
|
||||||
~inputs=[FRTypeDistOrNumber],
|
~inputs=[FRTypeDistOrNumber],
|
||||||
~run=(_, inputs, env, _) =>
|
~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
|
inputs
|
||||||
->E.A2.fmap(getMinMax)
|
->E.A2.fmap(getMinMax)
|
||||||
->E.A.R.firstErrorOrOpen
|
->E.A.R.firstErrorOrOpen
|
||||||
->E.R2.fmap(args => Reducer_T.IEvDeclaration(
|
->E.R2.fmap(args => Reducer_T.IEvDeclaration(Declaration.make(lambda, args)))
|
||||||
Declaration.make(lambda, args),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
| Error(r) => Error(r)
|
| Error(r) => Error(r)
|
||||||
| Ok(_) => Error(FunctionRegistry_Helpers.impossibleError)
|
| Ok(_) => Error(impossibleErrorString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +50,7 @@ let library = [
|
||||||
~name="declare",
|
~name="declare",
|
||||||
~inputs=[Declaration.frType],
|
~inputs=[Declaration.frType],
|
||||||
~run=(_, inputs, _, _) => {
|
~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>,
|
array: array<internalExpressionValue>,
|
||||||
eLambdaValue,
|
eLambdaValue,
|
||||||
env: Reducer_T.environment,
|
env: Reducer_T.environment,
|
||||||
reducer: Reducer_T.reducerFn
|
reducer: Reducer_T.reducerFn,
|
||||||
): internalExpressionValue => {
|
): internalExpressionValue => {
|
||||||
let mappedList = array->E.A.reduceReverse(list{}, (acc, elem) => {
|
let mappedList = array->E.A.reduceReverse(list{}, (acc, elem) => {
|
||||||
let newElem = Reducer_Expression_Lambda.doLambdaCall(
|
let newElem = Reducer_Expression_Lambda.doLambdaCall(eLambdaValue, [elem], env, reducer)
|
||||||
eLambdaValue,
|
|
||||||
[elem],
|
|
||||||
env,
|
|
||||||
reducer
|
|
||||||
)
|
|
||||||
list{newElem, ...acc}
|
list{newElem, ...acc}
|
||||||
})
|
})
|
||||||
mappedList->Belt.List.toArray->Wrappers.evArray
|
mappedList->Belt.List.toArray->Wrappers.evArray
|
||||||
|
@ -47,7 +42,7 @@ module Internals = {
|
||||||
initialValue,
|
initialValue,
|
||||||
aLambdaValue,
|
aLambdaValue,
|
||||||
env: Reducer_T.environment,
|
env: Reducer_T.environment,
|
||||||
reducer: Reducer_T.reducerFn
|
reducer: Reducer_T.reducerFn,
|
||||||
) => {
|
) => {
|
||||||
aValueArray->E.A.reduce(initialValue, (acc, elem) =>
|
aValueArray->E.A.reduce(initialValue, (acc, elem) =>
|
||||||
Reducer_Expression_Lambda.doLambdaCall(aLambdaValue, [acc, elem], env, reducer)
|
Reducer_Expression_Lambda.doLambdaCall(aLambdaValue, [acc, elem], env, reducer)
|
||||||
|
@ -59,7 +54,7 @@ module Internals = {
|
||||||
initialValue,
|
initialValue,
|
||||||
aLambdaValue,
|
aLambdaValue,
|
||||||
env: Reducer_T.environment,
|
env: Reducer_T.environment,
|
||||||
reducer: Reducer_T.reducerFn
|
reducer: Reducer_T.reducerFn,
|
||||||
) => {
|
) => {
|
||||||
aValueArray->Belt.Array.reduceReverse(initialValue, (acc, elem) =>
|
aValueArray->Belt.Array.reduceReverse(initialValue, (acc, elem) =>
|
||||||
Reducer_Expression_Lambda.doLambdaCall(aLambdaValue, [acc, elem], env, reducer)
|
Reducer_Expression_Lambda.doLambdaCall(aLambdaValue, [acc, elem], env, reducer)
|
||||||
|
@ -70,15 +65,10 @@ module Internals = {
|
||||||
aValueArray,
|
aValueArray,
|
||||||
aLambdaValue,
|
aLambdaValue,
|
||||||
env: Reducer_T.environment,
|
env: Reducer_T.environment,
|
||||||
reducer: Reducer_T.reducerFn
|
reducer: Reducer_T.reducerFn,
|
||||||
) => {
|
) => {
|
||||||
let mappedList = aValueArray->Belt.Array.reduceReverse(list{}, (acc, elem) => {
|
let mappedList = aValueArray->Belt.Array.reduceReverse(list{}, (acc, elem) => {
|
||||||
let newElem = Reducer_Expression_Lambda.doLambdaCall(
|
let newElem = Reducer_Expression_Lambda.doLambdaCall(aLambdaValue, [elem], env, reducer)
|
||||||
aLambdaValue,
|
|
||||||
[elem],
|
|
||||||
env,
|
|
||||||
reducer
|
|
||||||
)
|
|
||||||
switch newElem {
|
switch newElem {
|
||||||
| IEvBool(true) => list{elem, ...acc}
|
| IEvBool(true) => list{elem, ...acc}
|
||||||
| _ => acc
|
| _ => acc
|
||||||
|
@ -124,7 +114,8 @@ let library = [
|
||||||
~run=(_, inputs, _, _) =>
|
~run=(_, inputs, _, _) =>
|
||||||
inputs
|
inputs
|
||||||
->Prepare.ToValueTuple.twoNumbers
|
->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)],
|
~inputs=[FRTypeArray(FRTypeAny)],
|
||||||
~run=(inputs, _, _, _) =>
|
~run=(inputs, _, _, _) =>
|
||||||
switch inputs {
|
switch inputs {
|
||||||
| [IEvArray(array)] => Internals.first(array)
|
| [IEvArray(array)] => Internals.first(array)->E.R2.errMap(wrapError)
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleError)
|
||||||
},
|
},
|
||||||
(),
|
(),
|
||||||
|
@ -160,7 +151,7 @@ let library = [
|
||||||
~inputs=[FRTypeArray(FRTypeAny)],
|
~inputs=[FRTypeArray(FRTypeAny)],
|
||||||
~run=(inputs, _, _, _) =>
|
~run=(inputs, _, _, _) =>
|
||||||
switch inputs {
|
switch inputs {
|
||||||
| [IEvArray(array)] => Internals.last(array)
|
| [IEvArray(array)] => Internals.last(array)->E.R2.errMap(wrapError)
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleError)
|
||||||
},
|
},
|
||||||
(),
|
(),
|
||||||
|
@ -200,8 +191,7 @@ let library = [
|
||||||
~inputs=[FRTypeArray(FRTypeAny), FRTypeLambda],
|
~inputs=[FRTypeArray(FRTypeAny), FRTypeLambda],
|
||||||
~run=(inputs, _, env, reducer) =>
|
~run=(inputs, _, env, reducer) =>
|
||||||
switch inputs {
|
switch inputs {
|
||||||
| [IEvArray(array), IEvLambda(lambda)] =>
|
| [IEvArray(array), IEvLambda(lambda)] => Ok(Internals.map(array, lambda, env, reducer))
|
||||||
Ok(Internals.map(array, lambda, env, reducer))
|
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleError)
|
||||||
},
|
},
|
||||||
(),
|
(),
|
||||||
|
|
|
@ -12,7 +12,8 @@ module ArrayNumberDist = {
|
||||||
~run=(_, inputs, _, _) =>
|
~run=(_, inputs, _, _) =>
|
||||||
Prepare.ToTypedArray.numbers(inputs)
|
Prepare.ToTypedArray.numbers(inputs)
|
||||||
->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r))
|
->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, _, _) =>
|
~run=(_, inputs, _, _) =>
|
||||||
Prepare.ToTypedArray.numbers(inputs)
|
Prepare.ToTypedArray.numbers(inputs)
|
||||||
->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r))
|
->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 =
|
let expressionValue =
|
||||||
xyCoords
|
xyCoords
|
||||||
->E.R.bind(r => r->XYShape.T.makeFromZipped->E.R2.errMap(XYShape.Error.toString))
|
->E.R.bind(r => r->XYShape.T.makeFromZipped->E.R2.errMap(XYShape.Error.toString))
|
||||||
->E.R2.fmap(r => Reducer_T.IEvDistribution(
|
->E.R2.fmap(r => Reducer_T.IEvDistribution(PointSet(makeDist(r))))
|
||||||
PointSet(makeDist(r)),
|
|
||||||
))
|
|
||||||
expressionValue
|
expressionValue
|
||||||
}
|
}
|
||||||
|
|
||||||
module Internal = {
|
module Internal = {
|
||||||
type t = PointSetDist.t
|
type t = PointSetDist.t
|
||||||
|
|
||||||
let toType = (r): result<
|
let toType = (r): result<Reducer_T.value, Reducer_ErrorValue.errorValue> =>
|
||||||
Reducer_T.value,
|
|
||||||
Reducer_ErrorValue.errorValue,
|
|
||||||
> =>
|
|
||||||
switch r {
|
switch r {
|
||||||
| Ok(r) => Ok(Wrappers.evDistribution(PointSet(r)))
|
| Ok(r) => Ok(Wrappers.evDistribution(PointSet(r)))
|
||||||
| Error(err) => Error(REOperationError(err))
|
| Error(err) => Error(REOperationError(err))
|
||||||
|
@ -69,7 +64,7 @@ let library = [
|
||||||
)
|
)
|
||||||
->E.R2.fmap(Wrappers.pointSet)
|
->E.R2.fmap(Wrappers.pointSet)
|
||||||
->E.R2.fmap(Wrappers.evDistribution)
|
->E.R2.fmap(Wrappers.evDistribution)
|
||||||
->E.R2.errMap(_ => "")
|
->E.R2.errMap(e => Reducer_ErrorValue.REDistributionError(e))
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleError)
|
||||||
},
|
},
|
||||||
(),
|
(),
|
||||||
|
@ -90,7 +85,7 @@ let library = [
|
||||||
~run=(inputs, _, env, reducer) =>
|
~run=(inputs, _, env, reducer) =>
|
||||||
switch inputs {
|
switch inputs {
|
||||||
| [IEvDistribution(PointSet(dist)), IEvLambda(lambda)] =>
|
| [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)
|
| _ => Error(impossibleError)
|
||||||
},
|
},
|
||||||
(),
|
(),
|
||||||
|
@ -115,7 +110,9 @@ let library = [
|
||||||
FnDefinition.make(
|
FnDefinition.make(
|
||||||
~name="makeContinuous",
|
~name="makeContinuous",
|
||||||
~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))],
|
~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(
|
FnDefinition.make(
|
||||||
~name="makeDiscrete",
|
~name="makeDiscrete",
|
||||||
~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))],
|
~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)
|
| _ => Error(Operation.SampleMapNeedsNtoNFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
let toType = (r): result<
|
let toType = (r): result<Reducer_T.value, Reducer_ErrorValue.errorValue> =>
|
||||||
Reducer_T.value,
|
|
||||||
Reducer_ErrorValue.errorValue,
|
|
||||||
> =>
|
|
||||||
switch r {
|
switch r {
|
||||||
| Ok(r) => Ok(Wrappers.evDistribution(SampleSet(r)))
|
| Ok(r) => Ok(Wrappers.evDistribution(SampleSet(r)))
|
||||||
| Error(r) => Error(REDistributionError(SampleSetError(r)))
|
| Error(r) => Error(REDistributionError(SampleSetError(r)))
|
||||||
|
@ -100,7 +97,7 @@ let libaryBase = [
|
||||||
GenericDist.toSampleSetDist(dist, environment.sampleCount)
|
GenericDist.toSampleSetDist(dist, environment.sampleCount)
|
||||||
->E.R2.fmap(Wrappers.sampleSet)
|
->E.R2.fmap(Wrappers.sampleSet)
|
||||||
->E.R2.fmap(Wrappers.evDistribution)
|
->E.R2.fmap(Wrappers.evDistribution)
|
||||||
->E.R2.errMap(DistributionTypes.Error.toString)
|
->E.R2.errMap(e => Reducer_ErrorValue.REDistributionError(e))
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleError)
|
||||||
},
|
},
|
||||||
(),
|
(),
|
||||||
|
@ -123,7 +120,9 @@ let libaryBase = [
|
||||||
Prepare.ToTypedArray.numbers(inputs) |> E.R2.bind(r =>
|
Prepare.ToTypedArray.numbers(inputs) |> E.R2.bind(r =>
|
||||||
SampleSetDist.make(r)->E.R2.errMap(_ => "AM I HERE? WHYERE AMI??")
|
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)] =>
|
| [IEvLambda(lambda)] =>
|
||||||
switch Internal.fromFn(lambda, environment, reducer) {
|
switch Internal.fromFn(lambda, environment, reducer) {
|
||||||
| Ok(r) => Ok(r->Wrappers.sampleSet->Wrappers.evDistribution)
|
| Ok(r) => Ok(r->Wrappers.sampleSet->Wrappers.evDistribution)
|
||||||
| Error(e) => Error(Operation.Error.toString(e))
|
| Error(e) => e->Reducer_ErrorValue.REOperationError->Error
|
||||||
}
|
}
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleError)
|
||||||
},
|
},
|
||||||
|
@ -188,7 +187,7 @@ let libaryBase = [
|
||||||
~run=(inputs, _, environment, reducer) =>
|
~run=(inputs, _, environment, reducer) =>
|
||||||
switch inputs {
|
switch inputs {
|
||||||
| [IEvDistribution(SampleSet(dist)), IEvLambda(lambda)] =>
|
| [IEvDistribution(SampleSet(dist)), IEvLambda(lambda)] =>
|
||||||
Internal.map1(dist, lambda, environment, reducer)->E.R2.errMap(_ => "")
|
Internal.map1(dist, lambda, environment, reducer)
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleError)
|
||||||
},
|
},
|
||||||
(),
|
(),
|
||||||
|
@ -215,7 +214,7 @@ let libaryBase = [
|
||||||
IEvDistribution(SampleSet(dist2)),
|
IEvDistribution(SampleSet(dist2)),
|
||||||
IEvLambda(lambda),
|
IEvLambda(lambda),
|
||||||
] =>
|
] =>
|
||||||
Internal.map2(dist1, dist2, lambda, environment, reducer)->E.R2.errMap(_ => "")
|
Internal.map2(dist1, dist2, lambda, environment, reducer)
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleError)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -244,7 +243,7 @@ let libaryBase = [
|
||||||
IEvDistribution(SampleSet(dist3)),
|
IEvDistribution(SampleSet(dist3)),
|
||||||
IEvLambda(lambda),
|
IEvLambda(lambda),
|
||||||
] =>
|
] =>
|
||||||
Internal.map3(dist1, dist2, dist3, lambda, environment, reducer)->E.R2.errMap(_ => "")
|
Internal.map3(dist1, dist2, dist3, lambda, environment, reducer)
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleError)
|
||||||
},
|
},
|
||||||
(),
|
(),
|
||||||
|
@ -267,9 +266,7 @@ let libaryBase = [
|
||||||
~run=(inputs, _, environment, reducer) =>
|
~run=(inputs, _, environment, reducer) =>
|
||||||
switch inputs {
|
switch inputs {
|
||||||
| [IEvArray(dists), IEvLambda(lambda)] =>
|
| [IEvArray(dists), IEvLambda(lambda)] =>
|
||||||
Internal.mapN(dists, lambda, environment, reducer)->E.R2.errMap(_e => {
|
Internal.mapN(dists, lambda, environment, reducer)
|
||||||
"AHHH doesn't work"
|
|
||||||
})
|
|
||||||
| _ => Error(impossibleError)
|
| _ => Error(impossibleError)
|
||||||
},
|
},
|
||||||
(),
|
(),
|
||||||
|
@ -294,7 +291,7 @@ module Comparison = {
|
||||||
let wrapper = r =>
|
let wrapper = r =>
|
||||||
r
|
r
|
||||||
->E.R2.fmap(r => r->Wrappers.sampleSet->Wrappers.evDistribution)
|
->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) =>
|
let mkBig = (name, withDist, withFloat) =>
|
||||||
Function.make(
|
Function.make(
|
||||||
|
|
|
@ -6,7 +6,7 @@ let requiresNamespace = true
|
||||||
let runScoring = (estimate, answer, prior, env) => {
|
let runScoring = (estimate, answer, prior, env) => {
|
||||||
GenericDist.Score.logScore(~estimate, ~answer, ~prior, ~env)
|
GenericDist.Score.logScore(~estimate, ~answer, ~prior, ~env)
|
||||||
->E.R2.fmap(FunctionRegistry_Helpers.Wrappers.evNumber)
|
->E.R2.fmap(FunctionRegistry_Helpers.Wrappers.evNumber)
|
||||||
->E.R2.errMap(DistributionTypes.Error.toString)
|
->E.R2.errMap(e => Reducer_ErrorValue.REDistributionError(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
let library = [
|
let library = [
|
||||||
|
@ -40,7 +40,7 @@ let library = [
|
||||||
FRValueDist(prior),
|
FRValueDist(prior),
|
||||||
]) =>
|
]) =>
|
||||||
runScoring(estimate, Score_Scalar(d), Some(prior), environment)
|
runScoring(estimate, Score_Scalar(d), Some(prior), environment)
|
||||||
| Error(e) => Error(e)
|
| Error(e) => Error(e->FunctionRegistry_Helpers.wrapError)
|
||||||
| _ => Error(FunctionRegistry_Helpers.impossibleError)
|
| _ => Error(FunctionRegistry_Helpers.impossibleError)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -55,7 +55,7 @@ let library = [
|
||||||
runScoring(estimate, Score_Dist(d), None, environment)
|
runScoring(estimate, Score_Dist(d), None, environment)
|
||||||
| Ok([FRValueDist(estimate), FRValueDistOrNumber(FRValueNumber(d))]) =>
|
| Ok([FRValueDist(estimate), FRValueDistOrNumber(FRValueNumber(d))]) =>
|
||||||
runScoring(estimate, Score_Scalar(d), None, environment)
|
runScoring(estimate, Score_Scalar(d), None, environment)
|
||||||
| Error(e) => Error(e)
|
| Error(e) => Error(e->FunctionRegistry_Helpers.wrapError)
|
||||||
| _ => Error(FunctionRegistry_Helpers.impossibleError)
|
| _ => 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),
|
||||||
|
]
|
|
@ -11,10 +11,11 @@ let rec get = (nameSpace: t, id: string) => {
|
||||||
let T.NameSpace(container, parent) = nameSpace
|
let T.NameSpace(container, parent) = nameSpace
|
||||||
|
|
||||||
switch container->Belt.MutableMap.String.get(id) {
|
switch container->Belt.MutableMap.String.get(id) {
|
||||||
| Some(v) => Some(v)
|
| Some(v) => Some(v)
|
||||||
| None => switch parent {
|
| None =>
|
||||||
| Some(p) => get(p, id)
|
switch parent {
|
||||||
| None => None
|
| Some(p) => get(p, id)
|
||||||
|
| None => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,16 +36,12 @@ let set = (nameSpace: t, id: string, value): t => {
|
||||||
nameSpace
|
nameSpace
|
||||||
}
|
}
|
||||||
|
|
||||||
let extend = (nameSpace: t) => T.NameSpace(
|
let extend = (nameSpace: t) => T.NameSpace(makeEmptyMap(), nameSpace->Some)
|
||||||
makeEmptyMap(),
|
|
||||||
nameSpace->Some
|
|
||||||
)
|
|
||||||
|
|
||||||
let toKeyValuePairs = (T.NameSpace(container, _): t): array<(string, internalExpressionValue)> => {
|
let toKeyValuePairs = (T.NameSpace(container, _): t): array<(string, internalExpressionValue)> => {
|
||||||
container->Belt.MutableMap.String.toArray
|
container->Belt.MutableMap.String.toArray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let makeEmptyBindings = (): t => T.NameSpace(makeEmptyMap(), None)
|
let makeEmptyBindings = (): t => T.NameSpace(makeEmptyMap(), None)
|
||||||
|
|
||||||
let toExpressionValue = (nameSpace: t): internalExpressionValue => T.IEvBindings(nameSpace)
|
let toExpressionValue = (nameSpace: t): internalExpressionValue => T.IEvBindings(nameSpace)
|
||||||
|
@ -64,7 +61,7 @@ let mergeFrom = (T.NameSpace(container, _): t, T.NameSpace(newContainer, parent)
|
||||||
}
|
}
|
||||||
container
|
container
|
||||||
}),
|
}),
|
||||||
parent
|
parent,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +77,8 @@ let removeResult = (nameSpace: t): t => {
|
||||||
nameSpace
|
nameSpace
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let locals = (T.NameSpace(container, _): t) => T.NameSpace(container, None)
|
||||||
|
|
||||||
// let typeAliasesKey = "_typeAliases_"
|
// let typeAliasesKey = "_typeAliases_"
|
||||||
// let typeReferencesKey = "_typeReferences_"
|
// 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) =>
|
// let functionNotFoundError = (call: functionCall) =>
|
||||||
// REFunctionNotFound(call->functionCallToCallSignature->functionCallSignatureToString)->Error
|
// 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 => {
|
let createContext = (stdLib: Reducer_T.nameSpace, environment: Reducer_T.environment): t => {
|
||||||
{
|
{
|
||||||
bindings: stdLib->Reducer_Bindings.extend,
|
bindings: stdLib->Reducer_Bindings.extend,
|
||||||
environment,
|
environment: environment,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let createDefaultContext = (): t =>
|
let createDefaultContext = (): t =>
|
||||||
createContext(
|
createContext(
|
||||||
ReducerInterface_StdLib.internalStdLib,
|
ReducerInterface_StdLib.internalStdLib,
|
||||||
ReducerInterface_InternalExpressionValue.defaultEnvironment
|
ReducerInterface_InternalExpressionValue.defaultEnvironment,
|
||||||
)
|
)
|
||||||
|
|
|
@ -33,17 +33,17 @@ let callInternal = (
|
||||||
| call => call->IEV.toStringFunctionCall->MathJs.Eval.eval
|
| call => call->IEV.toStringFunctionCall->MathJs.Eval.eval
|
||||||
}
|
}
|
||||||
|
|
||||||
let constructRecord = arrayOfPairs => {
|
// let constructRecord = arrayOfPairs => {
|
||||||
Belt.Array.map(arrayOfPairs, pairValue =>
|
// Belt.Array.map(arrayOfPairs, pairValue =>
|
||||||
switch pairValue {
|
// switch pairValue {
|
||||||
| Reducer_T.IEvArray([IEvString(key), valueValue]) => (key, valueValue)
|
// | Reducer_T.IEvArray([IEvString(key), valueValue]) => (key, valueValue)
|
||||||
| _ => ("wrong key type", pairValue->IEV.toStringWithType->IEvString)
|
// | _ => ("wrong key type", pairValue->IEV.toStringWithType->IEvString)
|
||||||
}
|
// }
|
||||||
)
|
// )
|
||||||
->Belt.Map.String.fromArray
|
// ->Belt.Map.String.fromArray
|
||||||
->Reducer_T.IEvRecord
|
// ->Reducer_T.IEvRecord
|
||||||
->Ok
|
// ->Ok
|
||||||
}
|
// }
|
||||||
|
|
||||||
// let arrayAtIndex = (aValueArray: array<Reducer_T.value>, fIndex: float) =>
|
// let arrayAtIndex = (aValueArray: array<Reducer_T.value>, fIndex: float) =>
|
||||||
// switch Belt.Array.get(aValueArray, Belt.Int.fromFloat(fIndex)) {
|
// switch Belt.Array.get(aValueArray, Belt.Int.fromFloat(fIndex)) {
|
||||||
|
@ -111,7 +111,7 @@ let callInternal = (
|
||||||
| ("$_atIndex_$", [IEvBindings(dict), IEvString(sIndex)]) => moduleAtIndex(dict, sIndex)
|
| ("$_atIndex_$", [IEvBindings(dict), IEvString(sIndex)]) => moduleAtIndex(dict, sIndex)
|
||||||
// | ("$_atIndex_$", [IEvRecord(dict), IEvString(sIndex)]) => recordAtIndex(dict, sIndex)
|
// | ("$_atIndex_$", [IEvRecord(dict), IEvString(sIndex)]) => recordAtIndex(dict, sIndex)
|
||||||
// | ("$_constructArray_$", args) => IEvArray(args)->Ok
|
// | ("$_constructArray_$", args) => IEvArray(args)->Ok
|
||||||
| ("$_constructRecord_$", [IEvArray(arrayOfPairs)]) => constructRecord(arrayOfPairs)
|
// | ("$_constructRecord_$", [IEvArray(arrayOfPairs)]) => constructRecord(arrayOfPairs)
|
||||||
// | ("$_exportBindings_$", [IEvBindings(nameSpace)]) => doExportBindings(nameSpace)
|
// | ("$_exportBindings_$", [IEvBindings(nameSpace)]) => doExportBindings(nameSpace)
|
||||||
// | ("$_exportBindings_$", [evValue]) => doIdentity(evValue)
|
// | ("$_exportBindings_$", [evValue]) => doIdentity(evValue)
|
||||||
// | ("$_setBindings_$", [IEvBindings(nameSpace), IEvSymbol(symbol), value]) =>
|
// | ("$_setBindings_$", [IEvBindings(nameSpace), IEvSymbol(symbol), value]) =>
|
||||||
|
@ -154,7 +154,9 @@ let callInternal = (
|
||||||
| (_, [IEvString(_), IEvString(_)]) =>
|
| (_, [IEvString(_), IEvString(_)]) =>
|
||||||
callMathJs(call)
|
callMathJs(call)
|
||||||
| 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 = (
|
let dispatch = (
|
||||||
call: IEV.functionCall,
|
call: IEV.functionCall,
|
||||||
env: Reducer_T.environment,
|
env: Reducer_T.environment,
|
||||||
reducer: Reducer_T.reducerFn
|
reducer: Reducer_T.reducerFn,
|
||||||
): Reducer_T.value =>
|
): Reducer_T.value =>
|
||||||
try {
|
try {
|
||||||
let (fn, args) = call
|
let (fn, args) = call
|
||||||
|
|
|
@ -21,3 +21,4 @@
|
||||||
// }
|
// }
|
||||||
// dispatchChainPiece
|
// dispatchChainPiece
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
|
@ -19,3 +19,4 @@
|
||||||
// array<Reducer_T.value>,
|
// array<Reducer_T.value>,
|
||||||
// ProjectAccessorsT.t,
|
// ProjectAccessorsT.t,
|
||||||
// ) => result<Reducer_T.value, Reducer_ErrorValue.errorValue>
|
// ) => result<Reducer_T.value, Reducer_ErrorValue.errorValue>
|
||||||
|
|
||||||
|
|
|
@ -10,78 +10,70 @@ exception ErrorException = Reducer_ErrorValue.ErrorException
|
||||||
/*
|
/*
|
||||||
Recursively evaluate the expression
|
Recursively evaluate the expression
|
||||||
*/
|
*/
|
||||||
let rec evaluate: T.reducerFn = (
|
let rec evaluate: T.reducerFn = (expression, context) => {
|
||||||
expression,
|
|
||||||
context
|
|
||||||
) => {
|
|
||||||
// Js.log(`reduce: ${expression->Reducer_Expression_T.toString}`)
|
// Js.log(`reduce: ${expression->Reducer_Expression_T.toString}`)
|
||||||
switch expression {
|
switch expression {
|
||||||
| T.EBlock(statements) => {
|
| T.EBlock(statements) => {
|
||||||
let innerContext = {...context, bindings: context.bindings->Bindings.extend}
|
let innerContext = {...context, bindings: context.bindings->Bindings.extend}
|
||||||
statements->Js.Array2.reduce(
|
statements->Js.Array2.reduce((_, statement) => statement->evaluate(innerContext), T.IEvVoid)
|
||||||
(_, statement) => statement->evaluate(innerContext),
|
|
||||||
T.IEvVoid
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
| T.EProgram(statements) => {
|
| T.EProgram(statements) => {
|
||||||
// Js.log(`bindings: ${context.bindings->Reducer_Bindings.toString}`)
|
// Js.log(`bindings: ${context.bindings->Reducer_Bindings.toString}`)
|
||||||
let res = statements->Js.Array2.reduce(
|
let res =
|
||||||
(_, statement) => statement->evaluate(context),
|
statements->Js.Array2.reduce((_, statement) => statement->evaluate(context), T.IEvVoid)
|
||||||
T.IEvVoid
|
|
||||||
)
|
|
||||||
// Js.log(`bindings after: ${context.bindings->Reducer_Bindings.toString}`)
|
// Js.log(`bindings after: ${context.bindings->Reducer_Bindings.toString}`)
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
| T.EArray(elements) =>
|
| T.EArray(elements) => elements->Js.Array2.map(element => evaluate(element, context))->T.IEvArray
|
||||||
elements->Js.Array2.map(element => evaluate(element, context))->T.IEvArray
|
|
||||||
|
|
||||||
| T.ERecord(pairs) =>
|
| T.ERecord(pairs) =>
|
||||||
pairs->Js.Array2.map(((eKey, eValue)) => {
|
pairs
|
||||||
let key = eKey->evaluate(context)
|
->Js.Array2.map(((eKey, eValue)) => {
|
||||||
let keyString = switch key {
|
let key = eKey->evaluate(context)
|
||||||
| IEvString(s) => s
|
let keyString = switch key {
|
||||||
| _ => REOther("Record keys must be strings")->ErrorException->raise
|
| IEvString(s) => s
|
||||||
}
|
| _ => REOther("Record keys must be strings")->ErrorException->raise
|
||||||
let value = eValue->evaluate(context)
|
}
|
||||||
(keyString, value)
|
let value = eValue->evaluate(context)
|
||||||
})->Belt.Map.String.fromArray->IEvRecord
|
(keyString, value)
|
||||||
|
})
|
||||||
|
->Belt.Map.String.fromArray
|
||||||
|
->IEvRecord
|
||||||
|
|
||||||
| T.EAssign(left, right) => {
|
| T.EAssign(left, right) => {
|
||||||
let result = right->evaluate(context)
|
let result = right->evaluate(context)
|
||||||
let _ = context.bindings->Bindings.set(left, result)
|
let _ = context.bindings->Bindings.set(left, result)
|
||||||
T.IEvVoid
|
T.IEvVoid
|
||||||
}
|
}
|
||||||
|
|
||||||
| T.ESymbol(name) =>
|
| T.ESymbol(name) =>
|
||||||
switch context.bindings->Bindings.get(name) {
|
switch context.bindings->Bindings.get(name) {
|
||||||
| Some(v) => v
|
| Some(v) => v
|
||||||
| None => Reducer_ErrorValue.RESymbolNotFound(name)->ErrorException->raise
|
| None => Reducer_ErrorValue.RESymbolNotFound(name)->ErrorException->raise
|
||||||
}
|
}
|
||||||
|
|
||||||
| T.EValue(value) =>
|
| T.EValue(value) => value
|
||||||
value
|
|
||||||
|
|
||||||
| T.ETernary(predicate, trueCase, falseCase) => {
|
| T.ETernary(predicate, trueCase, falseCase) => {
|
||||||
let predicateResult = predicate->evaluate(context)
|
let predicateResult = predicate->evaluate(context)
|
||||||
switch predicateResult {
|
switch predicateResult {
|
||||||
| T.IEvBool(value) =>
|
| T.IEvBool(value) => (value ? trueCase : falseCase)->evaluate(context)
|
||||||
(value ? trueCase : falseCase)->evaluate(context)
|
|
||||||
| _ => REExpectedType("Boolean", "")->ErrorException->raise
|
| _ => REExpectedType("Boolean", "")->ErrorException->raise
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
| T.ELambda(parameters, body) =>
|
| T.ELambda(parameters, body) =>
|
||||||
Lambda.makeLambda(parameters, context.bindings, body)->T.IEvLambda
|
Lambda.makeLambda(parameters, context.bindings, body)->T.IEvLambda
|
||||||
|
|
||||||
| T.ECall(fn, args) => {
|
| T.ECall(fn, args) => {
|
||||||
let lambda = fn->evaluate(context)
|
let lambda = fn->evaluate(context)
|
||||||
let argValues = Js.Array2.map(args, arg => arg->evaluate(context))
|
let argValues = Js.Array2.map(args, arg => arg->evaluate(context))
|
||||||
switch lambda {
|
switch lambda {
|
||||||
| T.IEvLambda(lambda) =>
|
| T.IEvLambda(lambda) => Lambda.doLambdaCall(lambda, argValues, context.environment, evaluate)
|
||||||
Lambda.doLambdaCall(lambda, argValues, context.environment, evaluate)
|
| _ => REExpectedType("Lambda", "")->ErrorException->raise
|
||||||
| _ => REExpectedType("Lambda", "")->ErrorException->raise
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
module BBindingsReplacer = Reducer_Expression_BindingsReplacer
|
|
||||||
module BErrorValue = Reducer_ErrorValue
|
module BErrorValue = Reducer_ErrorValue
|
||||||
module T = Reducer_T
|
module T = Reducer_T
|
||||||
|
|
||||||
|
@ -14,13 +13,9 @@ let eBindings = (anArray: array<(string, T.value)>) =>
|
||||||
|
|
||||||
let eBool = aBool => aBool->T.IEvBool->T.EValue
|
let eBool = aBool => aBool->T.IEvBool->T.EValue
|
||||||
|
|
||||||
let eCall = (fn: expression, args: array<expression>): expression =>
|
let eCall = (fn: expression, args: array<expression>): expression => T.ECall(fn, args)
|
||||||
T.ECall(fn, args)
|
|
||||||
|
|
||||||
let eLambda = (
|
let eLambda = (parameters: array<string>, expr: expression) => T.ELambda(parameters, expr)
|
||||||
parameters: array<string>,
|
|
||||||
expr: expression,
|
|
||||||
) => T.ELambda(parameters, expr)
|
|
||||||
|
|
||||||
let eNumber = aNumber => aNumber->T.IEvNumber->T.EValue
|
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 eString = aString => aString->T.IEvString->T.EValue
|
||||||
|
|
||||||
let eSymbol = (name: string): expression =>
|
let eSymbol = (name: string): expression => T.ESymbol(name)
|
||||||
T.ESymbol(name)
|
|
||||||
|
|
||||||
let eBlock = (exprs: array<expression>): expression =>
|
let eBlock = (exprs: array<expression>): expression => T.EBlock(exprs)
|
||||||
T.EBlock(exprs)
|
|
||||||
|
|
||||||
let eProgram = (exprs: array<expression>): expression =>
|
let eProgram = (exprs: array<expression>): expression => T.EProgram(exprs)
|
||||||
T.EProgram(exprs)
|
|
||||||
|
|
||||||
let eModule = (nameSpace: T.nameSpace): expression =>
|
let eModule = (nameSpace: T.nameSpace): expression => nameSpace->T.IEvBindings->T.EValue
|
||||||
nameSpace->T.IEvBindings->T.EValue
|
|
||||||
|
|
||||||
let eLetStatement = (symbol: string, valueExpression: expression): expression =>
|
let eLetStatement = (symbol: string, valueExpression: expression): expression => T.EAssign(
|
||||||
T.EAssign(symbol, valueExpression)
|
symbol,
|
||||||
|
valueExpression,
|
||||||
|
)
|
||||||
|
|
||||||
let eTernary = (predicate: expression, trueCase: expression, falseCase: expression): expression =>
|
let eTernary = (
|
||||||
T.ETernary(predicate, trueCase, falseCase)
|
predicate: expression,
|
||||||
|
trueCase: expression,
|
||||||
|
falseCase: expression,
|
||||||
|
): expression => T.ETernary(predicate, trueCase, falseCase)
|
||||||
|
|
||||||
let eIdentifier = (name: string): expression =>
|
let eIdentifier = (name: string): expression => name->T.ESymbol
|
||||||
name->T.ESymbol
|
|
||||||
|
|
||||||
// let eTypeIdentifier = (name: string): expression =>
|
// let eTypeIdentifier = (name: string): expression =>
|
||||||
// name->T.IEvTypeIdentifier->T.EValue
|
// name->T.IEvTypeIdentifier->T.EValue
|
||||||
|
|
|
@ -7,7 +7,7 @@ let doLambdaCall = (
|
||||||
lambdaValue: Reducer_T.lambdaValue,
|
lambdaValue: Reducer_T.lambdaValue,
|
||||||
args,
|
args,
|
||||||
environment: Reducer_T.environment,
|
environment: Reducer_T.environment,
|
||||||
reducer: Reducer_T.reducerFn
|
reducer: Reducer_T.reducerFn,
|
||||||
): Reducer_T.value => {
|
): Reducer_T.value => {
|
||||||
lambdaValue.body(args, environment, reducer)
|
lambdaValue.body(args, environment, reducer)
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ let makeLambda = (
|
||||||
let lambda = (
|
let lambda = (
|
||||||
arguments: array<Reducer_T.value>,
|
arguments: array<Reducer_T.value>,
|
||||||
environment: Reducer_T.environment,
|
environment: Reducer_T.environment,
|
||||||
reducer: Reducer_T.reducerFn
|
reducer: Reducer_T.reducerFn,
|
||||||
) => {
|
) => {
|
||||||
let argsLength = arguments->Js.Array2.length
|
let argsLength = arguments->Js.Array2.length
|
||||||
let parametersLength = parameters->Js.Array2.length
|
let parametersLength = parameters->Js.Array2.length
|
||||||
|
@ -34,23 +34,21 @@ let makeLambda = (
|
||||||
}
|
}
|
||||||
|
|
||||||
let localBindings = bindings->Reducer_Bindings.extend
|
let localBindings = bindings->Reducer_Bindings.extend
|
||||||
parameters->Js.Array2.forEachi(
|
parameters->Js.Array2.forEachi((parameter, index) => {
|
||||||
(parameter, index) => {
|
let _ = localBindings->Reducer_Bindings.set(parameter, arguments[index])
|
||||||
let _ = localBindings->Reducer_Bindings.set(parameter, arguments[index])
|
})
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
reducer(body, { bindings: localBindings, environment })
|
reducer(body, {bindings: localBindings, environment: environment})
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// context: bindings,
|
// context: bindings,
|
||||||
body: lambda,
|
body: lambda,
|
||||||
parameters,
|
parameters: parameters,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let makeFFILambda = (body: Reducer_T.lambdaBody): Reducer_T.lambdaValue => {
|
let makeFFILambda = (body: Reducer_T.lambdaBody): Reducer_T.lambdaValue => {
|
||||||
body,
|
body: body,
|
||||||
parameters: ["..."]
|
parameters: ["..."],
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,15 +27,13 @@ let commaJoin = values => values->Reducer_Extra_Array.intersperse(", ")->Js.Stri
|
||||||
*/
|
*/
|
||||||
let rec toString = (expression: expression) =>
|
let rec toString = (expression: expression) =>
|
||||||
switch expression {
|
switch expression {
|
||||||
| EBlock(statements) =>
|
| EBlock(statements) => `{${Js.Array2.map(statements, aValue => toString(aValue))->commaJoin}}`
|
||||||
`{${Js.Array2.map(statements, aValue => toString(aValue))->commaJoin}}`
|
| EProgram(statements) => `<${Js.Array2.map(statements, aValue => toString(aValue))->commaJoin}>`
|
||||||
| EProgram(statements) =>
|
| EArray(aList) => `[${Js.Array2.map(aList, aValue => toString(aValue))->commaJoin}]`
|
||||||
`<${Js.Array2.map(statements, aValue => toString(aValue))->commaJoin}>`
|
|
||||||
| EArray(aList) =>
|
|
||||||
`[${Js.Array2.map(aList, aValue => toString(aValue))->commaJoin}]`
|
|
||||||
| ERecord(map) => "TODO"
|
| ERecord(map) => "TODO"
|
||||||
| ESymbol(name) => name
|
| 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}`
|
| EAssign(name, value) => `${name} = ${value->toString}`
|
||||||
| ECall(fn, args) => `(${fn->toString})(${args->Js.Array2.map(toString)->commaJoin})`
|
| ECall(fn, args) => `(${fn->toString})(${args->Js.Array2.map(toString)->commaJoin})`
|
||||||
| ELambda(parameters, body) => `{|${parameters->commaJoin}| ${body->toString}}`
|
| ELambda(parameters, body) => `{|${parameters->commaJoin}| ${body->toString}}`
|
||||||
|
@ -77,7 +75,3 @@ type optionFfiFnReturningResult = (
|
||||||
array<internalExpressionValue>,
|
array<internalExpressionValue>,
|
||||||
environment,
|
environment,
|
||||||
) => option<result<internalExpressionValue, Reducer_ErrorValue.errorValue>>
|
) => option<result<internalExpressionValue, Reducer_ErrorValue.errorValue>>
|
||||||
|
|
||||||
type expressionOrFFI =
|
|
||||||
| NotFFI(expression)
|
|
||||||
| FFI(ffiFn)
|
|
||||||
|
|
|
@ -109,14 +109,17 @@ let rec pgToString = (peggyNode: peggyNode): string => {
|
||||||
|
|
||||||
switch peggyNode {
|
switch peggyNode {
|
||||||
| PgNodeBlock(node)
|
| PgNodeBlock(node)
|
||||||
| PgNodeProgram(node)
|
| PgNodeProgram(node) =>
|
||||||
=> "{" ++ node["statements"]->nodesToStringUsingSeparator("; ") ++ "}"
|
"{" ++ node["statements"]->nodesToStringUsingSeparator("; ") ++ "}"
|
||||||
| PgNodeArray(node)
|
| PgNodeArray(node) => "[" ++ node["elements"]->nodesToStringUsingSeparator("; ") ++ "]"
|
||||||
=> "[" ++ node["elements"]->nodesToStringUsingSeparator("; ") ++ "]"
|
| PgNodeRecord(node) =>
|
||||||
| PgNodeRecord(node)
|
"{" ++
|
||||||
=> "{" ++ node["elements"]->Js.Array2.map(element => PgNodeKeyValue(element))->pgNodesToStringUsingSeparator(", ") ++ "}"
|
node["elements"]
|
||||||
|
->Js.Array2.map(element => PgNodeKeyValue(element))
|
||||||
|
->pgNodesToStringUsingSeparator(", ") ++ "}"
|
||||||
| PgNodeBoolean(node) => node["value"]->Js.String.make
|
| 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
|
| PgNodeFloat(node) => node["value"]->Js.String.make
|
||||||
| PgNodeIdentifier(node) => `:${node["value"]}`
|
| PgNodeIdentifier(node) => `:${node["value"]}`
|
||||||
| PgNodeInteger(node) => node["value"]->Js.String.make
|
| 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 caseLambda = (nodeLambda: Parse.nodeLambda): expression => {
|
||||||
let args =
|
let args =
|
||||||
nodeLambda["args"]
|
nodeLambda["args"]->Js.Array2.map((argNode: Parse.nodeIdentifier) => argNode["value"])
|
||||||
->Js.Array2.map((argNode: Parse.nodeIdentifier) => argNode["value"])
|
|
||||||
let body = nodeLambda["body"]->fromNode
|
let body = nodeLambda["body"]->fromNode
|
||||||
|
|
||||||
ExpressionBuilder.eLambda(args, body)
|
ExpressionBuilder.eLambda(args, body)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let caseRecord = (nodeRecord): expression => {
|
let caseRecord = (nodeRecord): expression => {
|
||||||
nodeRecord["elements"]
|
nodeRecord["elements"]
|
||||||
->Js.Array2.map(
|
->Js.Array2.map(keyValueNode => (
|
||||||
keyValueNode => (keyValueNode["key"]->fromNode, keyValueNode["value"]->fromNode)
|
keyValueNode["key"]->fromNode,
|
||||||
)
|
keyValueNode["value"]->fromNode,
|
||||||
|
))
|
||||||
->ExpressionBuilder.eRecord
|
->ExpressionBuilder.eRecord
|
||||||
}
|
}
|
||||||
|
|
||||||
switch Parse.castNodeType(node) {
|
switch Parse.castNodeType(node) {
|
||||||
| PgNodeBlock(nodeBlock) => caseBlock(nodeBlock)
|
| PgNodeBlock(nodeBlock) => caseBlock(nodeBlock)
|
||||||
| PgNodeProgram(nodeProgram) => caseProgram(nodeProgram)
|
| 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)
|
| PgNodeRecord(nodeRecord) => caseRecord(nodeRecord)
|
||||||
| PgNodeBoolean(nodeBoolean) => ExpressionBuilder.eBool(nodeBoolean["value"])
|
| 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"])
|
| PgNodeFloat(nodeFloat) => ExpressionBuilder.eNumber(nodeFloat["value"])
|
||||||
| PgNodeIdentifier(nodeIdentifier) => ExpressionBuilder.eSymbol(nodeIdentifier["value"])
|
| PgNodeIdentifier(nodeIdentifier) => ExpressionBuilder.eSymbol(nodeIdentifier["value"])
|
||||||
| PgNodeInteger(nodeInteger) => ExpressionBuilder.eNumber(Belt.Int.toFloat(nodeInteger["value"]))
|
| PgNodeInteger(nodeInteger) => ExpressionBuilder.eNumber(Belt.Int.toFloat(nodeInteger["value"]))
|
||||||
|
@ -54,7 +55,7 @@ let rec fromNode = (node: Parse.node): expression => {
|
||||||
ExpressionBuilder.eTernary(
|
ExpressionBuilder.eTernary(
|
||||||
fromNode(nodeTernary["condition"]),
|
fromNode(nodeTernary["condition"]),
|
||||||
fromNode(nodeTernary["trueExpression"]),
|
fromNode(nodeTernary["trueExpression"]),
|
||||||
fromNode(nodeTernary["falseExpression"])
|
fromNode(nodeTernary["falseExpression"]),
|
||||||
)
|
)
|
||||||
// | PgNodeTypeIdentifier(nodeTypeIdentifier) =>
|
// | PgNodeTypeIdentifier(nodeTypeIdentifier) =>
|
||||||
// ExpressionBuilder.eTypeIdentifier(nodeTypeIdentifier["value"])
|
// ExpressionBuilder.eTypeIdentifier(nodeTypeIdentifier["value"])
|
||||||
|
|
|
@ -25,10 +25,10 @@ type rec value =
|
||||||
and lambdaBody = (array<value>, environment, reducerFn) => value
|
and lambdaBody = (array<value>, environment, reducerFn) => value
|
||||||
@genType.opaque
|
@genType.opaque
|
||||||
and lambdaValue = {
|
and lambdaValue = {
|
||||||
parameters: array<string>,
|
parameters: array<string>,
|
||||||
// context: nameSpace,
|
// context: nameSpace,
|
||||||
body: (array<value>, environment, reducerFn) => value,
|
body: (array<value>, environment, reducerFn) => value,
|
||||||
}
|
}
|
||||||
@genType.opaque and lambdaDeclaration = Declaration.declaration<lambdaValue>
|
@genType.opaque and lambdaDeclaration = Declaration.declaration<lambdaValue>
|
||||||
and expression =
|
and expression =
|
||||||
| EBlock(array<expression>)
|
| EBlock(array<expression>)
|
||||||
|
|
|
@ -39,3 +39,4 @@
|
||||||
// | Ok(value) => value
|
// | Ok(value) => value
|
||||||
// | _ => `Cannot compile ${typeExpressionSourceCode}`->Reducer_Exception.ImpossibleException->raise
|
// | _ => `Cannot compile ${typeExpressionSourceCode}`->Reducer_Exception.ImpossibleException->raise
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
|
@ -117,3 +117,4 @@
|
||||||
// | IEvRecord(record) => record->Belt.Map.String.map(fromIEvValue)
|
// | IEvRecord(record) => record->Belt.Map.String.map(fromIEvValue)
|
||||||
// | _ => raise(Reducer_Exception.ImpossibleException("Reducer_Type_T-ievRecord"))
|
// | _ => raise(Reducer_Exception.ImpossibleException("Reducer_Type_T-ievRecord"))
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
|
@ -78,3 +78,4 @@
|
||||||
// ])
|
// ])
|
||||||
// newRecord->IEvType->Ok
|
// newRecord->IEvType->Ok
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
|
@ -179,3 +179,4 @@
|
||||||
// | Error(error) => Error(error) // Directly propagating - err => err - causes type mismatch
|
// | Error(error) => Error(error) // Directly propagating - err => err - causes type mismatch
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
module T = Reducer_T
|
module T = Reducer_T
|
||||||
|
|
||||||
let dispatch = (call: ReducerInterface_InternalExpressionValue.functionCall, _: GenericDist.env): option<
|
let dispatch = (
|
||||||
result<T.value, Reducer_ErrorValue.errorValue>,
|
call: ReducerInterface_InternalExpressionValue.functionCall,
|
||||||
> => {
|
_: GenericDist.env,
|
||||||
|
): option<result<T.value, Reducer_ErrorValue.errorValue>> => {
|
||||||
switch call {
|
switch call {
|
||||||
| ("toString", [IEvDate(t)]) => T.IEvString(DateTime.Date.toString(t))->Ok->Some
|
| ("toString", [IEvDate(t)]) => T.IEvString(DateTime.Date.toString(t))->Ok->Some
|
||||||
| ("makeDateFromYear", [IEvNumber(year)]) =>
|
| ("makeDateFromYear", [IEvNumber(year)]) =>
|
||||||
|
|
|
@ -3,7 +3,7 @@ module T = Reducer_T
|
||||||
type internalExpressionValue = IEV.t
|
type internalExpressionValue = IEV.t
|
||||||
|
|
||||||
let dispatch = (call: IEV.functionCall, _: T.environment): option<
|
let dispatch = (call: IEV.functionCall, _: T.environment): option<
|
||||||
result<Reducer_T.value, Reducer_ErrorValue.errorValue>
|
result<Reducer_T.value, Reducer_ErrorValue.errorValue>,
|
||||||
> => {
|
> => {
|
||||||
switch call {
|
switch call {
|
||||||
| ("toString", [IEvTimeDuration(t)]) => T.IEvString(DateTime.Duration.toString(t))->Ok->Some
|
| ("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)]) =>
|
| ("fromUnit_hours", [IEvNumber(f)]) =>
|
||||||
T.IEvTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some
|
T.IEvTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some
|
||||||
| ("days", [IEvNumber(f)]) => T.IEvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
|
| ("days", [IEvNumber(f)]) => T.IEvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
|
||||||
| ("fromUnit_days", [IEvNumber(f)]) =>
|
| ("fromUnit_days", [IEvNumber(f)]) => T.IEvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
|
||||||
T.IEvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
|
|
||||||
| ("years", [IEvNumber(f)]) => T.IEvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
|
| ("years", [IEvNumber(f)]) => T.IEvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
|
||||||
| ("fromUnit_years", [IEvNumber(f)]) =>
|
| ("fromUnit_years", [IEvNumber(f)]) =>
|
||||||
T.IEvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
|
T.IEvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
|
||||||
|
|
|
@ -10,7 +10,7 @@ let dispatch = (
|
||||||
chain,
|
chain,
|
||||||
): result<Reducer_T.value, 'e> => {
|
): result<Reducer_T.value, 'e> => {
|
||||||
E.A.O.firstSomeFn([
|
E.A.O.firstSomeFn([
|
||||||
() => ReducerInterface_GenericDistribution.dispatch(call, environment),
|
// () => ReducerInterface_GenericDistribution.dispatch(call, environment),
|
||||||
() => ReducerInterface_Date.dispatch(call, environment),
|
() => ReducerInterface_Date.dispatch(call, environment),
|
||||||
() => ReducerInterface_Duration.dispatch(call, environment),
|
() => ReducerInterface_Duration.dispatch(call, environment),
|
||||||
() => ReducerInterface_Number.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 toStringDistribution = dist => GenericDist.toString(dist)
|
||||||
and toStringLambda = (lambdaValue: T.lambdaValue) =>
|
and toStringLambda = (lambdaValue: T.lambdaValue) =>
|
||||||
`lambda(${Js.Array2.toString(lambdaValue.parameters)}=>internal code)`
|
`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 toStringNumber = aNumber => Js.String.make(aNumber)
|
||||||
and toStringRecord = aMap => aMap->toStringMap
|
and toStringRecord = aMap => aMap->toStringMap
|
||||||
and toStringString = aString => `'${aString}'`
|
and toStringString = aString => `'${aString}'`
|
||||||
|
@ -77,8 +78,8 @@ and toStringNameSpace = nameSpace => {
|
||||||
->Js.Array2.toString
|
->Js.Array2.toString
|
||||||
|
|
||||||
switch parent {
|
switch parent {
|
||||||
| Some(p) => `{${pairs}} / ${toStringNameSpace(p)}`
|
| Some(p) => `{${pairs}} / ${toStringNameSpace(p)}`
|
||||||
| None => `{${pairs}}`
|
| None => `{${pairs}}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,76 +1,77 @@
|
||||||
exception ErrorException = Reducer_ErrorValue.ErrorException
|
exception ErrorException = Reducer_ErrorValue.ErrorException
|
||||||
|
|
||||||
let internalStdLib: Reducer_Bindings.t = {
|
let internalStdLib: Reducer_Bindings.t = {
|
||||||
let res = Reducer_Bindings.makeEmptyBindings()
|
let res =
|
||||||
->SquiggleLibrary_Math.makeBindings
|
Reducer_Bindings.makeEmptyBindings()
|
||||||
->SquiggleLibrary_Versions.makeBindings
|
->SquiggleLibrary_Math.makeBindings
|
||||||
|
->SquiggleLibrary_Versions.makeBindings
|
||||||
|
|
||||||
let _ = res->Reducer_Bindings.set("multiply", Reducer_Expression_Lambda.makeFFILambda(
|
let _ = res->Reducer_Bindings.set(
|
||||||
(arguments, _, _) => {
|
"$_atIndex_$",
|
||||||
switch arguments {
|
Reducer_Expression_Lambda.makeFFILambda((inputs, _, _) => {
|
||||||
| [IEvNumber(x), IEvNumber(y)] => IEvNumber(x *. y)
|
|
||||||
| _ => raise(Not_found)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)->Reducer_T.IEvLambda)
|
|
||||||
|
|
||||||
let _ = res->Reducer_Bindings.set("$_atIndex_$", Reducer_Expression_Lambda.makeFFILambda(
|
|
||||||
(inputs, _, _) => {
|
|
||||||
switch inputs {
|
switch inputs {
|
||||||
| [IEvArray(aValueArray), IEvNumber(fIndex)] => {
|
| [IEvArray(aValueArray), IEvNumber(fIndex)] => switch Belt.Array.get(
|
||||||
switch Belt.Array.get(aValueArray, Belt.Int.fromFloat(fIndex)) {
|
aValueArray,
|
||||||
|
Belt.Int.fromFloat(fIndex),
|
||||||
|
) {
|
||||||
| Some(value) => value
|
| 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
|
| Some(value) => value
|
||||||
| None => RERecordPropertyNotFound("Record index not found", sIndex)->ErrorException->raise
|
| None => RERecordPropertyNotFound("Record index not found", sIndex)->ErrorException->raise
|
||||||
}
|
}
|
||||||
}
|
|
||||||
| _ => REOther("Trying to access key on wrong value")->ErrorException->raise
|
| _ => REOther("Trying to access key on wrong value")->ErrorException->raise
|
||||||
}
|
}
|
||||||
}
|
})->Reducer_T.IEvLambda,
|
||||||
)->Reducer_T.IEvLambda)
|
)
|
||||||
|
|
||||||
// TODO:
|
FunctionRegistry_Library.nonRegistryLambdas->Js.Array2.forEach(
|
||||||
// () => ReducerInterface_GenericDistribution.dispatch(call, environment),
|
((name, lambda)) => {
|
||||||
// () => ReducerInterface_Date.dispatch(call, environment),
|
let _ = res->Reducer_Bindings.set(name, lambda->Reducer_T.IEvLambda)
|
||||||
// () => ReducerInterface_Duration.dispatch(call, environment),
|
|
||||||
// () => ReducerInterface_Number.dispatch(call, environment),
|
|
||||||
|
|
||||||
// Reducer_Dispatch_BuiltIn:
|
|
||||||
|
|
||||||
// [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)
|
|
||||||
// [ ] | ("concat", [IEvArray(aValueArray), IEvArray(bValueArray)]) => doAddArray(aValueArray, bValueArray)
|
|
||||||
// [ ] | ("concat", [IEvString(aValueString), IEvString(bValueString)]) => doAddString(aValueString, bValueString)
|
|
||||||
// [ ] | ("inspect", [value, IEvString(label)]) => inspectLabel(value, label)
|
|
||||||
// [ ] | ("inspect", [value]) => inspect(value)
|
|
||||||
// [ ] | (_, [IEvBool(_)])
|
|
||||||
// [ ] | (_, [IEvNumber(_)])
|
|
||||||
// [ ] | (_, [IEvString(_)])
|
|
||||||
// [ ] | (_, [IEvBool(_), IEvBool(_)])
|
|
||||||
// [ ] | (_, [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) => {
|
|
||||||
switch FunctionRegistry_Library.call(name, arguments, environment, reducer) {
|
|
||||||
| Ok(value) => value
|
|
||||||
| Error(error) => error->Reducer_ErrorValue.ErrorException->raise
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)->Reducer_T.IEvLambda)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// () => ReducerInterface_GenericDistribution.dispatch(call, environment),
|
||||||
|
// () => ReducerInterface_Date.dispatch(call, environment),
|
||||||
|
// () => ReducerInterface_Duration.dispatch(call, environment),
|
||||||
|
// () => ReducerInterface_Number.dispatch(call, environment),
|
||||||
|
|
||||||
|
// Reducer_Dispatch_BuiltIn:
|
||||||
|
|
||||||
|
// [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)
|
||||||
|
// [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)
|
||||||
|
// [ ] | ("inspect", [value]) => inspect(value)
|
||||||
|
// [ ] | (_, [IEvBool(_)])
|
||||||
|
// [ ] | (_, [IEvNumber(_)])
|
||||||
|
// [ ] | (_, [IEvString(_)])
|
||||||
|
// [ ] | (_, [IEvBool(_), IEvBool(_)])
|
||||||
|
// [ ] | (_, [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) => {
|
||||||
|
switch FunctionRegistry_Library.call(name, arguments, environment, reducer) {
|
||||||
|
| Ok(value) => value
|
||||||
|
| Error(error) => error->Reducer_ErrorValue.ErrorException->raise
|
||||||
|
}
|
||||||
|
})->Reducer_T.IEvLambda,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,10 +85,7 @@ let getIncludes = (project: t, sourceId: string): ProjectItem.T.includesType =>
|
||||||
let getPastChain = (project: t, sourceId: string): array<string> =>
|
let getPastChain = (project: t, sourceId: string): array<string> =>
|
||||||
project->getItem(sourceId)->ProjectItem.getPastChain
|
project->getItem(sourceId)->ProjectItem.getPastChain
|
||||||
|
|
||||||
let getIncludesAsVariables = (
|
let getIncludesAsVariables = (project: t, sourceId: string): ProjectItem.T.importAsVariablesType =>
|
||||||
project: t,
|
|
||||||
sourceId: string,
|
|
||||||
): ProjectItem.T.importAsVariablesType =>
|
|
||||||
project->getItem(sourceId)->ProjectItem.getIncludesAsVariables
|
project->getItem(sourceId)->ProjectItem.getIncludesAsVariables
|
||||||
|
|
||||||
let getDirectIncludes = (project: t, sourceId: string): array<string> =>
|
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 => {
|
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<
|
let getContinuationsBefore = (project: t, sourceId: string): array<ProjectItem.T.continuation> => {
|
||||||
ProjectItem.T.continuation,
|
|
||||||
> => {
|
|
||||||
let pastNameSpaces = project->getPastChain(sourceId)->Js.Array2.map(getBindings(project, _))
|
let pastNameSpaces = project->getPastChain(sourceId)->Js.Array2.map(getBindings(project, _))
|
||||||
let theLength = pastNameSpaces->Js.Array2.length
|
let theLength = pastNameSpaces->Js.Array2.length
|
||||||
if theLength == 0 {
|
if theLength == 0 {
|
||||||
|
@ -177,7 +172,8 @@ let getContinuationsBefore = (project: t, sourceId: string): array<
|
||||||
|
|
||||||
let linkDependencies = (project: t, sourceId: string): ProjectItem.T.continuation => {
|
let linkDependencies = (project: t, sourceId: string): ProjectItem.T.continuation => {
|
||||||
let continuationsBefore = project->getContinuationsBefore(sourceId)
|
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)
|
let includesAsVariables = project->getIncludesAsVariables(sourceId)
|
||||||
Belt.Array.reduce(includesAsVariables, nameSpace, (currentNameSpace, (variable, includeFile)) =>
|
Belt.Array.reduce(includesAsVariables, nameSpace, (currentNameSpace, (variable, includeFile)) =>
|
||||||
Bindings.set(
|
Bindings.set(
|
||||||
|
@ -242,9 +238,7 @@ let evaluate = (sourceCode: string) => {
|
||||||
runAll(project)
|
runAll(project)
|
||||||
|
|
||||||
(
|
(
|
||||||
getResultOption(project, "main")->Belt.Option.getWithDefault(
|
getResultOption(project, "main")->Belt.Option.getWithDefault(Reducer_T.IEvVoid->Ok),
|
||||||
Reducer_T.IEvVoid->Ok,
|
project->getBindings("main"),
|
||||||
),
|
|
||||||
project->getBindings("main")
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,9 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
function peg$subclass(child, parent) {
|
function peg$subclass(child, parent) {
|
||||||
function C() { this.constructor = child; }
|
function C() {
|
||||||
|
this.constructor = child;
|
||||||
|
}
|
||||||
C.prototype = parent.prototype;
|
C.prototype = parent.prototype;
|
||||||
child.prototype = new C();
|
child.prototype = new C();
|
||||||
}
|
}
|
||||||
|
@ -27,13 +29,15 @@ peg$subclass(peg$SyntaxError, Error);
|
||||||
|
|
||||||
function peg$padEnd(str, targetLength, padString) {
|
function peg$padEnd(str, targetLength, padString) {
|
||||||
padString = padString || " ";
|
padString = padString || " ";
|
||||||
if (str.length > targetLength) { return str; }
|
if (str.length > targetLength) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
targetLength -= str.length;
|
targetLength -= str.length;
|
||||||
padString += padString.repeat(targetLength);
|
padString += padString.repeat(targetLength);
|
||||||
return str + padString.slice(0, targetLength);
|
return str + padString.slice(0, targetLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
peg$SyntaxError.prototype.format = function(sources) {
|
peg$SyntaxError.prototype.format = function (sources) {
|
||||||
var str = "Error: " + this.message;
|
var str = "Error: " + this.message;
|
||||||
if (this.location) {
|
if (this.location) {
|
||||||
var src = null;
|
var src = null;
|
||||||
|
@ -48,15 +52,24 @@ peg$SyntaxError.prototype.format = function(sources) {
|
||||||
var loc = this.location.source + ":" + s.line + ":" + s.column;
|
var loc = this.location.source + ":" + s.line + ":" + s.column;
|
||||||
if (src) {
|
if (src) {
|
||||||
var e = this.location.end;
|
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 line = src[s.line - 1];
|
||||||
var last = s.line === e.line ? e.column : line.length + 1;
|
var last = s.line === e.line ? e.column : line.length + 1;
|
||||||
var hatLen = (last - s.column) || 1;
|
var hatLen = last - s.column || 1;
|
||||||
str += "\n --> " + loc + "\n"
|
str +=
|
||||||
+ filler + " |\n"
|
"\n --> " +
|
||||||
+ s.line + " | " + line + "\n"
|
loc +
|
||||||
+ filler + " | " + peg$padEnd("", s.column - 1, ' ')
|
"\n" +
|
||||||
+ peg$padEnd("", hatLen, "^");
|
filler +
|
||||||
|
" |\n" +
|
||||||
|
s.line +
|
||||||
|
" | " +
|
||||||
|
line +
|
||||||
|
"\n" +
|
||||||
|
filler +
|
||||||
|
" | " +
|
||||||
|
peg$padEnd("", s.column - 1, " ") +
|
||||||
|
peg$padEnd("", hatLen, "^");
|
||||||
} else {
|
} else {
|
||||||
str += "\n at " + loc;
|
str += "\n at " + loc;
|
||||||
}
|
}
|
||||||
|
@ -64,33 +77,35 @@ peg$SyntaxError.prototype.format = function(sources) {
|
||||||
return str;
|
return str;
|
||||||
};
|
};
|
||||||
|
|
||||||
peg$SyntaxError.buildMessage = function(expected, found) {
|
peg$SyntaxError.buildMessage = function (expected, found) {
|
||||||
var DESCRIBE_EXPECTATION_FNS = {
|
var DESCRIBE_EXPECTATION_FNS = {
|
||||||
literal: function(expectation) {
|
literal: function (expectation) {
|
||||||
return "\"" + literalEscape(expectation.text) + "\"";
|
return '"' + literalEscape(expectation.text) + '"';
|
||||||
},
|
},
|
||||||
|
|
||||||
class: function(expectation) {
|
class: function (expectation) {
|
||||||
var escapedParts = expectation.parts.map(function(part) {
|
var escapedParts = expectation.parts.map(function (part) {
|
||||||
return Array.isArray(part)
|
return Array.isArray(part)
|
||||||
? classEscape(part[0]) + "-" + classEscape(part[1])
|
? classEscape(part[0]) + "-" + classEscape(part[1])
|
||||||
: classEscape(part);
|
: classEscape(part);
|
||||||
});
|
});
|
||||||
|
|
||||||
return "[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]";
|
return (
|
||||||
|
"[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]"
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
any: function() {
|
any: function () {
|
||||||
return "any character";
|
return "any character";
|
||||||
},
|
},
|
||||||
|
|
||||||
end: function() {
|
end: function () {
|
||||||
return "end of input";
|
return "end of input";
|
||||||
},
|
},
|
||||||
|
|
||||||
other: function(expectation) {
|
other: function (expectation) {
|
||||||
return expectation.description;
|
return expectation.description;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function hex(ch) {
|
function hex(ch) {
|
||||||
|
@ -100,13 +115,17 @@ peg$SyntaxError.buildMessage = function(expected, found) {
|
||||||
function literalEscape(s) {
|
function literalEscape(s) {
|
||||||
return s
|
return s
|
||||||
.replace(/\\/g, "\\\\")
|
.replace(/\\/g, "\\\\")
|
||||||
.replace(/"/g, "\\\"")
|
.replace(/"/g, '\\"')
|
||||||
.replace(/\0/g, "\\0")
|
.replace(/\0/g, "\\0")
|
||||||
.replace(/\t/g, "\\t")
|
.replace(/\t/g, "\\t")
|
||||||
.replace(/\n/g, "\\n")
|
.replace(/\n/g, "\\n")
|
||||||
.replace(/\r/g, "\\r")
|
.replace(/\r/g, "\\r")
|
||||||
.replace(/[\x00-\x0F]/g, function(ch) { return "\\x0" + hex(ch); })
|
.replace(/[\x00-\x0F]/g, function (ch) {
|
||||||
.replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return "\\x" + hex(ch); });
|
return "\\x0" + hex(ch);
|
||||||
|
})
|
||||||
|
.replace(/[\x10-\x1F\x7F-\x9F]/g, function (ch) {
|
||||||
|
return "\\x" + hex(ch);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function classEscape(s) {
|
function classEscape(s) {
|
||||||
|
@ -114,13 +133,17 @@ peg$SyntaxError.buildMessage = function(expected, found) {
|
||||||
.replace(/\\/g, "\\\\")
|
.replace(/\\/g, "\\\\")
|
||||||
.replace(/\]/g, "\\]")
|
.replace(/\]/g, "\\]")
|
||||||
.replace(/\^/g, "\\^")
|
.replace(/\^/g, "\\^")
|
||||||
.replace(/-/g, "\\-")
|
.replace(/-/g, "\\-")
|
||||||
.replace(/\0/g, "\\0")
|
.replace(/\0/g, "\\0")
|
||||||
.replace(/\t/g, "\\t")
|
.replace(/\t/g, "\\t")
|
||||||
.replace(/\n/g, "\\n")
|
.replace(/\n/g, "\\n")
|
||||||
.replace(/\r/g, "\\r")
|
.replace(/\r/g, "\\r")
|
||||||
.replace(/[\x00-\x0F]/g, function(ch) { return "\\x0" + hex(ch); })
|
.replace(/[\x00-\x0F]/g, function (ch) {
|
||||||
.replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return "\\x" + hex(ch); });
|
return "\\x0" + hex(ch);
|
||||||
|
})
|
||||||
|
.replace(/[\x10-\x1F\x7F-\x9F]/g, function (ch) {
|
||||||
|
return "\\x" + hex(ch);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function describeExpectation(expectation) {
|
function describeExpectation(expectation) {
|
||||||
|
@ -151,17 +174,25 @@ peg$SyntaxError.buildMessage = function(expected, found) {
|
||||||
return descriptions[0] + " or " + descriptions[1];
|
return descriptions[0] + " or " + descriptions[1];
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return descriptions.slice(0, -1).join(", ")
|
return (
|
||||||
+ ", or "
|
descriptions.slice(0, -1).join(", ") +
|
||||||
+ descriptions[descriptions.length - 1];
|
", or " +
|
||||||
|
descriptions[descriptions.length - 1]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function describeFound(found) {
|
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) {
|
function peg$parse(input, options) {
|
||||||
|
@ -177,7 +208,7 @@ function peg$parse(input, options) {
|
||||||
var peg$c1 = "#include";
|
var peg$c1 = "#include";
|
||||||
var peg$c2 = "as";
|
var peg$c2 = "as";
|
||||||
var peg$c3 = "'";
|
var peg$c3 = "'";
|
||||||
var peg$c4 = "\"";
|
var peg$c4 = '"';
|
||||||
var peg$c5 = "//";
|
var peg$c5 = "//";
|
||||||
var peg$c6 = "/*";
|
var peg$c6 = "/*";
|
||||||
var peg$c7 = "*/";
|
var peg$c7 = "*/";
|
||||||
|
@ -197,8 +228,8 @@ function peg$parse(input, options) {
|
||||||
var peg$e3 = peg$otherExpectation("string");
|
var peg$e3 = peg$otherExpectation("string");
|
||||||
var peg$e4 = peg$literalExpectation("'", false);
|
var peg$e4 = peg$literalExpectation("'", false);
|
||||||
var peg$e5 = peg$classExpectation(["'"], true, false);
|
var peg$e5 = peg$classExpectation(["'"], true, false);
|
||||||
var peg$e6 = peg$literalExpectation("\"", false);
|
var peg$e6 = peg$literalExpectation('"', false);
|
||||||
var peg$e7 = peg$classExpectation(["\""], true, false);
|
var peg$e7 = peg$classExpectation(['"'], true, false);
|
||||||
var peg$e8 = peg$otherExpectation("comment");
|
var peg$e8 = peg$otherExpectation("comment");
|
||||||
var peg$e9 = peg$literalExpectation("//", false);
|
var peg$e9 = peg$literalExpectation("//", false);
|
||||||
var peg$e10 = 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$e18 = peg$classExpectation(["\r", "\n"], true, false);
|
||||||
var peg$e19 = peg$otherExpectation("identifier");
|
var peg$e19 = peg$otherExpectation("identifier");
|
||||||
var peg$e20 = peg$classExpectation(["_", ["a", "z"]], false, false);
|
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$f0 = function (head, tail) {
|
||||||
var peg$f1 = function() {return [];};
|
return [head, ...tail].filter((e) => e != "");
|
||||||
var peg$f2 = function(file, variable) {return [!variable ? '' : variable, file]};
|
};
|
||||||
var peg$f3 = function(characters) {return characters.join('');};
|
var peg$f1 = function () {
|
||||||
var peg$f4 = function(characters) {return characters.join('');};
|
return [];
|
||||||
var peg$f5 = function() { return '';};
|
};
|
||||||
var peg$f6 = function() { return '';};
|
var peg$f2 = function (file, variable) {
|
||||||
var peg$f7 = function() {return text();};
|
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$currPos = 0;
|
||||||
var peg$savedPos = 0;
|
var peg$savedPos = 0;
|
||||||
var peg$posDetailsCache = [{ line: 1, column: 1 }];
|
var peg$posDetailsCache = [{ line: 1, column: 1 }];
|
||||||
|
@ -235,7 +286,9 @@ function peg$parse(input, options) {
|
||||||
|
|
||||||
if ("startRule" in options) {
|
if ("startRule" in options) {
|
||||||
if (!(options.startRule in peg$startRuleFunctions)) {
|
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];
|
peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
|
||||||
|
@ -253,7 +306,7 @@ function peg$parse(input, options) {
|
||||||
return {
|
return {
|
||||||
source: peg$source,
|
source: peg$source,
|
||||||
start: peg$savedPos,
|
start: peg$savedPos,
|
||||||
end: peg$currPos
|
end: peg$currPos,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,9 +315,10 @@ function peg$parse(input, options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function expected(description, location) {
|
function expected(description, location) {
|
||||||
location = location !== undefined
|
location =
|
||||||
? location
|
location !== undefined
|
||||||
: peg$computeLocation(peg$savedPos, peg$currPos);
|
? location
|
||||||
|
: peg$computeLocation(peg$savedPos, peg$currPos);
|
||||||
|
|
||||||
throw peg$buildStructuredError(
|
throw peg$buildStructuredError(
|
||||||
[peg$otherExpectation(description)],
|
[peg$otherExpectation(description)],
|
||||||
|
@ -274,9 +328,10 @@ function peg$parse(input, options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function error(message, location) {
|
function error(message, location) {
|
||||||
location = location !== undefined
|
location =
|
||||||
? location
|
location !== undefined
|
||||||
: peg$computeLocation(peg$savedPos, peg$currPos);
|
? location
|
||||||
|
: peg$computeLocation(peg$savedPos, peg$currPos);
|
||||||
|
|
||||||
throw peg$buildSimpleError(message, location);
|
throw peg$buildSimpleError(message, location);
|
||||||
}
|
}
|
||||||
|
@ -286,7 +341,12 @@ function peg$parse(input, options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function peg$classExpectation(parts, inverted, ignoreCase) {
|
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() {
|
function peg$anyExpectation() {
|
||||||
|
@ -316,7 +376,7 @@ function peg$parse(input, options) {
|
||||||
details = peg$posDetailsCache[p];
|
details = peg$posDetailsCache[p];
|
||||||
details = {
|
details = {
|
||||||
line: details.line,
|
line: details.line,
|
||||||
column: details.column
|
column: details.column,
|
||||||
};
|
};
|
||||||
|
|
||||||
while (p < pos) {
|
while (p < pos) {
|
||||||
|
@ -345,18 +405,20 @@ function peg$parse(input, options) {
|
||||||
start: {
|
start: {
|
||||||
offset: startPos,
|
offset: startPos,
|
||||||
line: startPosDetails.line,
|
line: startPosDetails.line,
|
||||||
column: startPosDetails.column
|
column: startPosDetails.column,
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
offset: endPos,
|
offset: endPos,
|
||||||
line: endPosDetails.line,
|
line: endPosDetails.line,
|
||||||
column: endPosDetails.column
|
column: endPosDetails.column,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function peg$fail(expected) {
|
function peg$fail(expected) {
|
||||||
if (peg$currPos < peg$maxFailPos) { return; }
|
if (peg$currPos < peg$maxFailPos) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (peg$currPos > peg$maxFailPos) {
|
if (peg$currPos > peg$maxFailPos) {
|
||||||
peg$maxFailPos = peg$currPos;
|
peg$maxFailPos = peg$currPos;
|
||||||
|
@ -516,7 +578,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s2 = peg$FAILED;
|
s2 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e0); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
peg$silentFails--;
|
peg$silentFails--;
|
||||||
if (s2 === peg$FAILED) {
|
if (s2 === peg$FAILED) {
|
||||||
|
@ -586,7 +650,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos += 8;
|
peg$currPos += 8;
|
||||||
} else {
|
} else {
|
||||||
s2 = peg$FAILED;
|
s2 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e1); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (s2 !== peg$FAILED) {
|
if (s2 !== peg$FAILED) {
|
||||||
s3 = [];
|
s3 = [];
|
||||||
|
@ -619,7 +685,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos += 2;
|
peg$currPos += 2;
|
||||||
} else {
|
} else {
|
||||||
s7 = peg$FAILED;
|
s7 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e2); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (s7 !== peg$FAILED) {
|
if (s7 !== peg$FAILED) {
|
||||||
s8 = [];
|
s8 = [];
|
||||||
|
@ -716,7 +784,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s2 = peg$FAILED;
|
s2 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e4); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (s2 !== peg$FAILED) {
|
if (s2 !== peg$FAILED) {
|
||||||
s3 = [];
|
s3 = [];
|
||||||
|
@ -725,7 +795,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s4 = peg$FAILED;
|
s4 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e5); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while (s4 !== peg$FAILED) {
|
while (s4 !== peg$FAILED) {
|
||||||
s3.push(s4);
|
s3.push(s4);
|
||||||
|
@ -734,7 +806,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s4 = peg$FAILED;
|
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) {
|
if (input.charCodeAt(peg$currPos) === 39) {
|
||||||
|
@ -742,7 +816,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s4 = peg$FAILED;
|
s4 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e4); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (s4 !== peg$FAILED) {
|
if (s4 !== peg$FAILED) {
|
||||||
s1 = s3;
|
s1 = s3;
|
||||||
|
@ -767,7 +843,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s2 = peg$FAILED;
|
s2 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e6); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e6);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (s2 !== peg$FAILED) {
|
if (s2 !== peg$FAILED) {
|
||||||
s3 = [];
|
s3 = [];
|
||||||
|
@ -776,7 +854,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s4 = peg$FAILED;
|
s4 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e7); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e7);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while (s4 !== peg$FAILED) {
|
while (s4 !== peg$FAILED) {
|
||||||
s3.push(s4);
|
s3.push(s4);
|
||||||
|
@ -785,7 +865,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s4 = peg$FAILED;
|
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) {
|
if (input.charCodeAt(peg$currPos) === 34) {
|
||||||
|
@ -793,7 +875,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s4 = peg$FAILED;
|
s4 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e6); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e6);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (s4 !== peg$FAILED) {
|
if (s4 !== peg$FAILED) {
|
||||||
s1 = s3;
|
s1 = s3;
|
||||||
|
@ -814,7 +898,9 @@ function peg$parse(input, options) {
|
||||||
peg$silentFails--;
|
peg$silentFails--;
|
||||||
if (s0 === peg$FAILED) {
|
if (s0 === peg$FAILED) {
|
||||||
s1 = 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 };
|
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
|
||||||
|
@ -877,7 +963,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos += 2;
|
peg$currPos += 2;
|
||||||
} else {
|
} else {
|
||||||
s1 = peg$FAILED;
|
s1 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e9); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e9);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
s2 = [];
|
s2 = [];
|
||||||
|
@ -910,7 +998,9 @@ function peg$parse(input, options) {
|
||||||
peg$silentFails--;
|
peg$silentFails--;
|
||||||
if (s0 === peg$FAILED) {
|
if (s0 === peg$FAILED) {
|
||||||
s1 = 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 };
|
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
|
||||||
|
@ -937,7 +1027,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos += 2;
|
peg$currPos += 2;
|
||||||
} else {
|
} else {
|
||||||
s1 = peg$FAILED;
|
s1 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e10); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e10);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (s1 !== peg$FAILED) {
|
if (s1 !== peg$FAILED) {
|
||||||
s2 = [];
|
s2 = [];
|
||||||
|
@ -946,7 +1038,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s3 = peg$FAILED;
|
s3 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e11); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e11);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while (s3 !== peg$FAILED) {
|
while (s3 !== peg$FAILED) {
|
||||||
s2.push(s3);
|
s2.push(s3);
|
||||||
|
@ -955,7 +1049,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s3 = peg$FAILED;
|
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) {
|
if (input.substr(peg$currPos, 2) === peg$c7) {
|
||||||
|
@ -963,7 +1059,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos += 2;
|
peg$currPos += 2;
|
||||||
} else {
|
} else {
|
||||||
s3 = peg$FAILED;
|
s3 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e12); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e12);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
peg$savedPos = s0;
|
peg$savedPos = s0;
|
||||||
|
@ -979,7 +1077,9 @@ function peg$parse(input, options) {
|
||||||
peg$silentFails--;
|
peg$silentFails--;
|
||||||
if (s0 === peg$FAILED) {
|
if (s0 === peg$FAILED) {
|
||||||
s1 = 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 };
|
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
|
||||||
|
@ -1005,12 +1105,16 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e14); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e14);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
peg$silentFails--;
|
peg$silentFails--;
|
||||||
if (s0 === peg$FAILED) {
|
if (s0 === peg$FAILED) {
|
||||||
s1 = 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 };
|
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
|
||||||
|
@ -1036,12 +1140,16 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e16); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e16);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
peg$silentFails--;
|
peg$silentFails--;
|
||||||
if (s0 === peg$FAILED) {
|
if (s0 === peg$FAILED) {
|
||||||
s1 = 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 };
|
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
|
||||||
|
@ -1067,12 +1175,16 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s0 = peg$FAILED;
|
s0 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e18); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e18);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
peg$silentFails--;
|
peg$silentFails--;
|
||||||
if (s0 === peg$FAILED) {
|
if (s0 === peg$FAILED) {
|
||||||
s1 = 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 };
|
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
|
||||||
|
@ -1101,7 +1213,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s3 = peg$FAILED;
|
s3 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e20); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e20);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (s3 !== peg$FAILED) {
|
if (s3 !== peg$FAILED) {
|
||||||
while (s3 !== peg$FAILED) {
|
while (s3 !== peg$FAILED) {
|
||||||
|
@ -1111,7 +1225,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s3 = peg$FAILED;
|
s3 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e20); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e20);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1124,7 +1240,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s4 = peg$FAILED;
|
s4 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e21); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e21);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while (s4 !== peg$FAILED) {
|
while (s4 !== peg$FAILED) {
|
||||||
s3.push(s4);
|
s3.push(s4);
|
||||||
|
@ -1133,7 +1251,9 @@ function peg$parse(input, options) {
|
||||||
peg$currPos++;
|
peg$currPos++;
|
||||||
} else {
|
} else {
|
||||||
s4 = peg$FAILED;
|
s4 = peg$FAILED;
|
||||||
if (peg$silentFails === 0) { peg$fail(peg$e21); }
|
if (peg$silentFails === 0) {
|
||||||
|
peg$fail(peg$e21);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s2 = [s2, s3];
|
s2 = [s2, s3];
|
||||||
|
@ -1150,7 +1270,9 @@ function peg$parse(input, options) {
|
||||||
peg$silentFails--;
|
peg$silentFails--;
|
||||||
if (s0 === peg$FAILED) {
|
if (s0 === peg$FAILED) {
|
||||||
s1 = 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 };
|
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
|
||||||
|
@ -1179,5 +1301,5 @@ function peg$parse(input, options) {
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
SyntaxError: peg$SyntaxError,
|
SyntaxError: peg$SyntaxError,
|
||||||
parse: peg$parse
|
parse: peg$parse,
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,3 +28,4 @@
|
||||||
// environment: environment,
|
// environment: environment,
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
|
@ -81,8 +81,10 @@ let setRawParse = (r: t, rawParse: T.rawParseArgumentType): t =>
|
||||||
let setExpression = (r: t, expression: T.expressionArgumentType): t =>
|
let setExpression = (r: t, expression: T.expressionArgumentType): t =>
|
||||||
{...r, expression: Some(expression)}->touchExpression
|
{...r, expression: Some(expression)}->touchExpression
|
||||||
|
|
||||||
let setContinuation = (r: t, continuation: T.continuationArgumentType): t =>
|
let setContinuation = (r: t, continuation: T.continuationArgumentType): t => {
|
||||||
{...r, continuation: continuation}
|
...r,
|
||||||
|
continuation: continuation,
|
||||||
|
}
|
||||||
|
|
||||||
let setResult = (r: t, result: T.resultArgumentType): t => {
|
let setResult = (r: t, result: T.resultArgumentType): t => {
|
||||||
...r,
|
...r,
|
||||||
|
@ -115,10 +117,10 @@ let setIncludes = (this: t, includes: T.includesType): t => {
|
||||||
includes: includes,
|
includes: includes,
|
||||||
}
|
}
|
||||||
|
|
||||||
let setImportAsVariables = (
|
let setImportAsVariables = (this: t, includeAsVariables: T.importAsVariablesType): t => {
|
||||||
this: t,
|
...this,
|
||||||
includeAsVariables: T.importAsVariablesType,
|
includeAsVariables: includeAsVariables,
|
||||||
): t => {...this, includeAsVariables: includeAsVariables}
|
}
|
||||||
|
|
||||||
let setDirectImports = (this: t, directIncludes: array<string>): t => {
|
let setDirectImports = (this: t, directIncludes: array<string>): t => {
|
||||||
...this,
|
...this,
|
||||||
|
@ -161,38 +163,26 @@ let buildExpression = (this: t): t => {
|
||||||
switch this->getExpression {
|
switch this->getExpression {
|
||||||
| Some(_) => this // cached
|
| Some(_) => this // cached
|
||||||
| None =>
|
| None =>
|
||||||
this
|
this->doBuildExpression->Belt.Option.map(setExpression(this, _))->E.O2.defaultFn(() => this)
|
||||||
->doBuildExpression
|
|
||||||
->Belt.Option.map(setExpression(this, _))
|
|
||||||
->E.O2.defaultFn(() => this)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let failRun = (
|
let failRun = (this: t, e: Reducer_ErrorValue.errorValue): t =>
|
||||||
this: t,
|
this->setResult(e->Error)->setContinuation(Reducer_Bindings.makeEmptyBindings())
|
||||||
e: Reducer_ErrorValue.errorValue
|
|
||||||
): t => this->setResult(e->Error)->setContinuation(Reducer_Bindings.makeEmptyBindings())
|
|
||||||
|
|
||||||
let doRun = (
|
let doRun = (this: t, context: Reducer_T.context): t =>
|
||||||
this: t,
|
|
||||||
context: Reducer_T.context
|
|
||||||
): t =>
|
|
||||||
switch this->getExpression {
|
switch this->getExpression {
|
||||||
| Some(expressionResult) => {
|
| Some(expressionResult) => switch expressionResult {
|
||||||
switch expressionResult {
|
| Ok(expression) => try {
|
||||||
| Ok(expression) => {
|
let result = Reducer_Expression.evaluate(expression, context)
|
||||||
try {
|
this->setResult(result->Ok)->setContinuation(context.bindings)
|
||||||
let result = Reducer_Expression.evaluate(expression, context)
|
} catch {
|
||||||
this->setResult(result->Ok)->setContinuation(context.bindings)
|
| Reducer_ErrorValue.ErrorException(e) => this->failRun(e)
|
||||||
} catch {
|
| _ => this->failRun(RETodo("unhandled rescript exception"))
|
||||||
| Reducer_ErrorValue.ErrorException(e) => this->failRun(e)
|
|
||||||
| _ => this->failRun(RETodo("unhandled rescript exception"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
| Error(e) => this->failRun(e)
|
|
||||||
}
|
}
|
||||||
|
| Error(e) => this->failRun(e)
|
||||||
}
|
}
|
||||||
| None => this->failRun(RETodo("attempt to run without expression"))
|
| None => this->failRun(RETodo("attempt to run without expression"))
|
||||||
}
|
}
|
||||||
|
|
||||||
let run = (this: t, context: Reducer_T.context): t => {
|
let run = (this: t, context: Reducer_T.context): t => {
|
||||||
|
|
|
@ -31,16 +31,16 @@ let rec topologicalSortUtil = (
|
||||||
}
|
}
|
||||||
|
|
||||||
let getTopologicalSort = (this: t): array<string> => {
|
let getTopologicalSort = (this: t): array<string> => {
|
||||||
let (_visited, stack) = this->getSourceIds->Belt.Array.reduce((Belt.Map.String.empty, list{}), (
|
let (_visited, stack) =
|
||||||
(currVisited, currStack),
|
this
|
||||||
currId,
|
->getSourceIds
|
||||||
) =>
|
->Belt.Array.reduce((Belt.Map.String.empty, list{}), ((currVisited, currStack), currId) =>
|
||||||
if !Belt.Map.String.getWithDefault(currVisited, currId, false) {
|
if !Belt.Map.String.getWithDefault(currVisited, currId, false) {
|
||||||
topologicalSortUtil(this, currId, (currVisited, currStack))
|
topologicalSortUtil(this, currId, (currVisited, currStack))
|
||||||
} else {
|
} else {
|
||||||
(currVisited, currStack)
|
(currVisited, currStack)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
Belt.List.reverse(stack)->Belt.List.toArray
|
Belt.List.reverse(stack)->Belt.List.toArray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,7 @@ let availableNumbers: array<(string, float)> = [
|
||||||
]
|
]
|
||||||
|
|
||||||
let mathBindings: Bindings.t =
|
let mathBindings: Bindings.t =
|
||||||
availableNumbers
|
availableNumbers->E.A2.fmap(((name, v)) => (name, Reducer_T.IEvNumber(v)))->Bindings.fromArray
|
||||||
->E.A2.fmap(((name, v)) => (name, Reducer_T.IEvNumber(v)))
|
|
||||||
->Bindings.fromArray
|
|
||||||
|
|
||||||
let makeBindings = (previousBindings: Bindings.t): Bindings.t =>
|
let makeBindings = (previousBindings: Bindings.t): Bindings.t =>
|
||||||
previousBindings->Bindings.mergeFrom(mathBindings)
|
previousBindings->Bindings.mergeFrom(mathBindings)
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
module Bindings = Reducer_Bindings
|
module Bindings = Reducer_Bindings
|
||||||
|
|
||||||
let bindings: Reducer_T.nameSpace =
|
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 =>
|
let makeBindings = (previousBindings: Reducer_T.nameSpace): Reducer_T.nameSpace =>
|
||||||
previousBindings->Bindings.mergeFrom(bindings)
|
previousBindings->Bindings.mergeFrom(bindings)
|
||||||
|
|
|
@ -7,3 +7,4 @@
|
||||||
// | exception _ => Error("MathJS Parse Error")
|
// | exception _ => Error("MathJS Parse Error")
|
||||||
// | j => Ok(j)
|
// | j => Ok(j)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user