This commit is contained in:
Vyacheslav Matyukhin 2022-09-12 13:33:20 +04:00
parent 681a1b42c6
commit 757d458ecf
No known key found for this signature in database
GPG Key ID: 3D2A774C5489F96C
48 changed files with 1067 additions and 911 deletions

View File

@ -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

View File

@ -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
} }
} }
@ -267,17 +268,20 @@ module Registry = {
let _buildFnNameDict = (r: array<function>): fnNameDict => { let _buildFnNameDict = (r: array<function>): fnNameDict => {
// Sorry for the imperative style of this. But it's much easier/less buggy than the previous version. // Sorry for the imperative style of this. But it's much easier/less buggy than the previous version.
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
} }
} }
} }

View File

@ -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))
}, },
(), (),
) )

View File

@ -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),
]

View File

@ -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)
}
},
()
),
],
(),
),
] ]

View File

@ -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
}, },
(), (),
), ),

View File

@ -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),
(), (),
), ),
], ],

View File

@ -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),
(), (),
) )
} }

View File

@ -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)
}, },
(), (),
), ),

View File

@ -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
}
})

View File

@ -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)
}, },
(), (),

View File

@ -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),
(), (),
) )
} }

View File

@ -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),
(), (),
), ),
], ],

View File

@ -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(

View File

@ -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)
} }
}, },

View File

@ -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),
]

View File

@ -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

View File

@ -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,
) )

View File

@ -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

View File

@ -21,3 +21,4 @@
// } // }
// dispatchChainPiece // dispatchChainPiece
// } // }

View File

@ -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>

View File

@ -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
} }
} }
} }

View File

@ -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

View File

@ -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: ["..."],
} }

View File

@ -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)

View File

@ -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

View File

@ -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"])

View File

@ -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>)

View File

@ -39,3 +39,4 @@
// | Ok(value) => value // | Ok(value) => value
// | _ => `Cannot compile ${typeExpressionSourceCode}`->Reducer_Exception.ImpossibleException->raise // | _ => `Cannot compile ${typeExpressionSourceCode}`->Reducer_Exception.ImpossibleException->raise
// } // }

View File

@ -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"))
// } // }

View File

@ -78,3 +78,4 @@
// ]) // ])
// newRecord->IEvType->Ok // newRecord->IEvType->Ok
// } // }

View File

@ -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
// } // }
// } // }

View File

@ -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)]) =>

View File

@ -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

View File

@ -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),

View File

@ -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)

View File

@ -1,4 +0,0 @@
let dispatch: (
ReducerInterface_InternalExpressionValue.functionCall,
ReducerInterface_InternalExpressionValue.environment,
) => option<result<ReducerInterface_InternalExpressionValue.t, Reducer_ErrorValue.errorValue>>

View File

@ -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}'`
@ -75,10 +76,10 @@ and toStringNameSpace = nameSpace => {
->Belt.MutableMap.String.toArray ->Belt.MutableMap.String.toArray
->Js.Array2.map(((eachKey, eachValue)) => `${eachKey}: ${toString(eachValue)}`) ->Js.Array2.map(((eachKey, eachValue)) => `${eachKey}: ${toString(eachValue)}`)
->Js.Array2.toString ->Js.Array2.toString
switch parent { switch parent {
| Some(p) => `{${pairs}} / ${toStringNameSpace(p)}` | Some(p) => `{${pairs}} / ${toStringNameSpace(p)}`
| None => `{${pairs}}` | None => `{${pairs}}`
} }
} }

View File

@ -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
}
}

View File

@ -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
} }

View File

@ -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")
) )
} }

View File

@ -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,
}; };

View File

@ -28,3 +28,4 @@
// environment: environment, // environment: environment,
// } // }
// } // }

View File

@ -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 => {

View File

@ -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
} }

View File

@ -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)

View File

@ -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)

View File

@ -7,3 +7,4 @@
// | exception _ => Error("MathJS Parse Error") // | exception _ => Error("MathJS Parse Error")
// | j => Ok(j) // | j => Ok(j)
// } // }