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.
*/
@genType
let getSourceIds = (project: reducerProject): array<string> =>
project->Private.getSourceIds
let getSourceIds = (project: reducerProject): array<string> => project->Private.getSourceIds
/*
Sets the source for a given source Id.
@ -71,15 +70,13 @@ Cleans the compilation artifacts for a given source ID. The results stay untouch
Normally, you would never need the compilation artifacts again as the results with the same sources would never change. However, they are needed in case of any debugging reruns
*/
@genType
let clean = (project: reducerProject, sourceId: string): unit =>
project->Private.clean(sourceId)
let clean = (project: reducerProject, sourceId: string): unit => project->Private.clean(sourceId)
/*
Cleans all the compilation artifacts in all of the project
*/
@genType
let cleanAll = (project: reducerProject): unit =>
project->Private.cleanAll
let cleanAll = (project: reducerProject): unit => project->Private.cleanAll
/*
Cleans results. Compilation stays untouched to be able to re-run the source.
@ -93,8 +90,7 @@ let cleanResults = (project: reducerProject, sourceId: string): unit =>
Cleans all results. Compilations remains untouched to rerun the source.
*/
@genType
let cleanAllResults = (project: reducerProject): unit =>
project->Private.cleanAllResults
let cleanAllResults = (project: reducerProject): unit => project->Private.cleanAllResults
/*
To set the includes one first has to call "parseIncludes". The parsed includes or the parser error is returned.
@ -144,8 +140,7 @@ let getDependents = (project: reducerProject, sourceId: string): array<string> =
Get the run order for the sources in the project.
*/
@genType
let getRunOrder = (project: reducerProject): array<string> =>
project->Private.getRunOrder
let getRunOrder = (project: reducerProject): array<string> => project->Private.getRunOrder
/*
Get the run order to get the results of this specific source
@ -177,15 +172,13 @@ let rawParse = (project: reducerProject, sourceId: string): unit =>
Runs a specific source code if it is not done already. The code is parsed if it is not already done. It runs the dependencies if it is not already done.
*/
@genType
let run = (project: reducerProject, sourceId: string): unit =>
project->Private.run(sourceId)
let run = (project: reducerProject, sourceId: string): unit => project->Private.run(sourceId)
/*
Runs all of the sources in a project. Their results and bindings will be available
*/
@genType
let runAll = (project: reducerProject): unit =>
project->Private.runAll
let runAll = (project: reducerProject): unit => project->Private.runAll
/*
Get the bindings after running this source fil. The bindings are local to the source

View File

@ -1,5 +1,6 @@
type internalExpressionValue = Reducer_T.value
type internalExpressionValueType = ReducerInterface_InternalExpressionValue.internalExpressionValueType
type errorValue = Reducer_ErrorValue.errorValue
/*
Function Registry "Type". A type, without any other information.
@ -48,7 +49,7 @@ type fnDefinition = {
array<frValue>,
Reducer_T.environment,
Reducer_T.reducerFn,
) => result<internalExpressionValue, string>,
) => result<internalExpressionValue, errorValue>,
}
type function = {
@ -206,7 +207,7 @@ module FnDefinition = {
let argValues = FRType.matchWithExpressionValueArray(t.inputs, args)
switch argValues {
| Some(values) => t.run(args, values, env, reducer)
| None => Error("Incorrect Types")
| None => REOther("Incorrect Types")->Error
}
}
@ -267,17 +268,20 @@ module Registry = {
let _buildFnNameDict = (r: array<function>): fnNameDict => {
// Sorry for the imperative style of this. But it's much easier/less buggy than the previous version.
let res: fnNameDict = Js.Dict.empty()
r->Js.Array2.forEach(fn =>
r->Js.Array2.forEach(fn =>
fn.definitions->Js.Array2.forEach(def => {
let nameWithNamespace = `${fn.nameSpace}.${def.name}`
let nameWithoutNamespace = def.name
let names = fn.requiresNamespace ? [nameWithNamespace] : [nameWithNamespace, nameWithoutNamespace]
let names =
[
fn.nameSpace == "" ? [] : [`${fn.nameSpace}.${def.name}`],
fn.requiresNamespace ? [] : [def.name],
]->E.A.concatMany
names->Js.Array2.forEach(name => {
switch res->Js.Dict.get(name) {
| Some(fns) => {
| Some(fns) => {
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>,
env: Reducer_T.environment,
reducer: Reducer_T.reducerFn,
): result<internalExpressionValue, Reducer_ErrorValue.errorValue> => {
): result<internalExpressionValue, errorValue> => {
switch Js.Dict.get(registry.fnNameDict, fnName) {
| Some(definitions) => {
| Some(definitions) => {
let showNameMatchDefinitions = () => {
let defsString =
definitions
@ -310,13 +314,12 @@ module Registry = {
let match = definitions->Js.Array2.find(def => def->FnDefinition.isMatch(args))
switch match {
| Some(def) => def->FnDefinition.run(args, env, reducer)->E.R2.errMap(e => Reducer_ErrorValue.REOther(e))
| None => {
Reducer_ErrorValue.REOther(showNameMatchDefinitions())->Error
}
| Some(def) =>
def->FnDefinition.run(args, env, reducer)
| None => REOther(showNameMatchDefinitions())->Error
}
}
| None => Reducer_ErrorValue.RESymbolNotFound(fnName)->Error
| None => RESymbolNotFound(fnName)->Error
}
}
}

View File

@ -1,6 +1,8 @@
open FunctionRegistry_Core
let impossibleError = "Wrong inputs / Logically impossible"
let impossibleErrorString = "Wrong inputs / Logically impossible"
let impossibleError: errorValue = impossibleErrorString->REOther
let wrapError = e => Reducer_ErrorValue.REOther(e)
module Wrappers = {
let symbolic = r => DistributionTypes.Symbolic(r)
@ -15,7 +17,7 @@ module Wrappers = {
let evArrayOfEvNumber = xs => xs->Belt.Array.map(evNumber)->evArray
}
let getOrError = (a, g) => E.A.get(a, g) |> E.O.toResult(impossibleError)
let getOrError = (a, g) => E.A.get(a, g) |> E.O.toResult(impossibleErrorString)
module Prepare = {
type t = frValue
@ -27,19 +29,19 @@ module Prepare = {
let twoArgs = (inputs: ts): result<ts, err> =>
switch inputs {
| [FRValueRecord([(_, n1), (_, n2)])] => Ok([n1, n2])
| _ => Error(impossibleError)
| _ => Error(impossibleErrorString)
}
let threeArgs = (inputs: ts): result<ts, err> =>
switch inputs {
| [FRValueRecord([(_, n1), (_, n2), (_, n3)])] => Ok([n1, n2, n3])
| _ => Error(impossibleError)
| _ => Error(impossibleErrorString)
}
let toArgs = (inputs: ts): result<ts, err> =>
switch inputs {
| [FRValueRecord(args)] => args->E.A2.fmap(((_, b)) => b)->Ok
| _ => Error(impossibleError)
| _ => Error(impossibleErrorString)
}
}
@ -47,13 +49,13 @@ module Prepare = {
let openA = (inputs: t): result<ts, err> =>
switch inputs {
| FRValueArray(n) => Ok(n)
| _ => Error(impossibleError)
| _ => Error(impossibleErrorString)
}
let arrayOfArrays = (inputs: t): result<array<ts>, err> =>
switch inputs {
| FRValueArray(n) => n->E.A2.fmap(openA)->E.A.R.firstErrorOrOpen
| _ => Error(impossibleError)
| _ => Error(impossibleErrorString)
}
}
}
@ -62,7 +64,7 @@ module Prepare = {
let twoDistOrNumber = (values: ts): result<(frValueDistOrNumber, frValueDistOrNumber), err> => {
switch values {
| [FRValueDistOrNumber(a1), FRValueDistOrNumber(a2)] => Ok(a1, a2)
| _ => Error(impossibleError)
| _ => Error(impossibleErrorString)
}
}
@ -72,28 +74,28 @@ module Prepare = {
> => {
switch values {
| [FRValueDist(a1), FRValueDist(a2)] => Ok(a1, a2)
| _ => Error(impossibleError)
| _ => Error(impossibleErrorString)
}
}
let twoNumbers = (values: ts): result<(float, float), err> => {
switch values {
| [FRValueNumber(a1), FRValueNumber(a2)] => Ok(a1, a2)
| _ => Error(impossibleError)
| _ => Error(impossibleErrorString)
}
}
let threeNumbers = (values: ts): result<(float, float, float), err> => {
switch values {
| [FRValueNumber(a1), FRValueNumber(a2), FRValueNumber(a3)] => Ok(a1, a2, a3)
| _ => Error(impossibleError)
| _ => Error(impossibleErrorString)
}
}
let oneDistOrNumber = (values: ts): result<frValueDistOrNumber, err> => {
switch values {
| [FRValueDistOrNumber(a1)] => Ok(a1)
| _ => Error(impossibleError)
| _ => Error(impossibleErrorString)
}
}
@ -124,14 +126,14 @@ module Prepare = {
let oneNumber = (values: t): result<float, err> => {
switch values {
| FRValueNumber(a1) => Ok(a1)
| _ => Error(impossibleError)
| _ => Error(impossibleErrorString)
}
}
let oneDict = (values: t): result<Js.Dict.t<frValue>, err> => {
switch values {
| FRValueDict(a1) => Ok(a1)
| _ => Error(impossibleError)
| _ => Error(impossibleErrorString)
}
}
@ -229,6 +231,7 @@ module DefineFn = {
->E.R.bind(Prepare.oneNumber)
->E.R2.fmap(fn)
->E.R2.fmap(Wrappers.evNumber)
->E.R2.errMap(e => Reducer_ErrorValue.REOther(e))
},
(),
)
@ -237,7 +240,11 @@ module DefineFn = {
~name,
~inputs=[FRTypeNumber, FRTypeNumber],
~run=(_, inputs, _, _) => {
inputs->Prepare.ToValueTuple.twoNumbers->E.R2.fmap(fn)->E.R2.fmap(Wrappers.evNumber)
inputs
->Prepare.ToValueTuple.twoNumbers
->E.R2.fmap(fn)
->E.R2.fmap(Wrappers.evNumber)
->E.R2.errMap(e => Reducer_ErrorValue.REOther(e))
},
(),
)
@ -246,7 +253,11 @@ module DefineFn = {
~name,
~inputs=[FRTypeNumber, FRTypeNumber, FRTypeNumber],
~run=(_, inputs, _, _) => {
inputs->Prepare.ToValueTuple.threeNumbers->E.R2.fmap(fn)->E.R2.fmap(Wrappers.evNumber)
inputs
->Prepare.ToValueTuple.threeNumbers
->E.R2.fmap(fn)
->E.R2.fmap(Wrappers.evNumber)
->E.R2.errMap(e => Reducer_ErrorValue.REOther(e))
},
(),
)

View File

@ -9,7 +9,14 @@ let fnList = Belt.Array.concatMany([
FR_Number.library,
FR_Pointset.library,
FR_Scoring.library,
FR_GenericDist.library,
FR_Units.library,
])
let registry = FunctionRegistry_Core.Registry.make(fnList)
let call = FunctionRegistry_Core.Registry.call(registry)
let nonRegistryLambdas: array<(string, Reducer_T.lambdaValue)> = [
("mx", FR_GenericDist.mxLambda),
("mixture", FR_GenericDist.mxLambda),
]

View File

@ -1,73 +1,47 @@
open FunctionRegistry_Core
open FunctionRegistry_Helpers
let nameSpace = "Builtin"
let nameSpace = "" // no namespaced versions
type simpleDefinition = {
inputs: array<frType>,
fn: (array<internalExpressionValue>) => result<internalExpressionValue, string>,
fn: array<internalExpressionValue> => result<internalExpressionValue, errorValue>,
}
let makeFnMany = (name: string, definitions: array<simpleDefinition>) =>
Function.make(
~name=name,
~name,
~nameSpace,
~requiresNamespace=false,
~definitions=definitions->Js.Array2.map(
({ inputs, fn }) => FnDefinition.make(
~name=name,
~inputs=inputs,
~run=(inputs, _, _, _) => fn(inputs),
()
)
~definitions=definitions->Js.Array2.map(({inputs, fn}) =>
FnDefinition.make(~name, ~inputs, ~run=(inputs, _, _, _) => fn(inputs), ())
),
(),
)
let makeFn = (name: string, inputs: array<frType>, fn: (array<internalExpressionValue>) => result<internalExpressionValue, string>) =>
makeFnMany(name, [{ inputs, fn }])
let makeFn = (
name: string,
inputs: array<frType>,
fn: array<internalExpressionValue> => result<internalExpressionValue, errorValue>,
) => makeFnMany(name, [{ inputs, fn }])
let makeBinaryFn = (name: string, fn: (float, float) => float) => {
makeFn(
name,
[FRTypeNumber, FRTypeNumber],
inputs => {
switch inputs {
| [IEvNumber(x), IEvNumber(y)] => fn(x, y)->IEvNumber->Ok
| _ => Error(impossibleError)
}
}
)
}
let library = [
// TODO - other MathJS
Function.make(
~name="add",
~nameSpace,
~requiresNamespace=false,
~definitions=[
FnDefinition.make(
~name="add",
~inputs=[FRTypeNumber, FRTypeNumber],
~run=(inputs, _, _, _) => {
switch inputs {
| [IEvNumber(x), IEvNumber(y)] => IEvNumber(x+.y)->Ok
| _ => Error(impossibleError)
}
},
()
),
FnDefinition.make(
~name="add",
~inputs=[FRTypeNumber, FRTypeNumber],
~run=(inputs, _, _, _) => {
switch inputs {
| [IEvNumber(x), IEvNumber(y)] => IEvNumber(x+.y)->Ok
| _ => Error(impossibleError)
}
},
()
),
FnDefinition.make(
~name="add",
~inputs=[FRTypeNumber, FRTypeNumber],
~run=(inputs, _, _, _) => {
switch inputs {
| [IEvNumber(x), IEvNumber(y)] => IEvNumber(x+.y)->Ok
| _ => Error(impossibleError)
}
},
()
),
],
(),
),
// TODO - other MathJS
makeBinaryFn("add", (x, y) => x +. y),
makeBinaryFn("subtract", (x, y) => x -. y),
makeBinaryFn("multiply", (x, y) => x *. y),
makeBinaryFn("divide", (x, y) => x /. y),
]

View File

@ -71,13 +71,14 @@ module Integration = {
aLambda,
[pointAsInternalExpression],
environment,
reducer
reducer,
)
let result = switch resultAsInternalExpression {
| Reducer_T.IEvNumber(x) => Ok(x)
| _ =>
Error(
"Error 1 in Danger.integrate. It's possible that your function doesn't return a number, try definining auxiliaryFunction(x) = mean(yourFunction(x)) and integrate auxiliaryFunction instead",
"Error 1 in Danger.integrate. It's possible that your function doesn't return a number, try definining auxiliaryFunction(x) = mean(yourFunction(x)) and integrate auxiliaryFunction instead"
->Reducer_ErrorValue.REOther
)
}
result
@ -141,11 +142,11 @@ module Integration = {
resultWithOuterPoints
}
| Error(b) =>
Error(
(
"Integration error 2 in Danger.integrate. It's possible that your function doesn't return a number, try definining auxiliaryFunction(x) = mean(yourFunction(x)) and integrate auxiliaryFunction instead." ++
"Original error: " ++
b,
)
b->Reducer_ErrorValue.errorToString
)->Reducer_ErrorValue.REOther->Error
}
result
}
@ -168,7 +169,7 @@ module Integration = {
~run=(inputs, _, env, reducer) => {
let result = switch inputs {
| [_, _, _, IEvNumber(0.0)] =>
Error("Integration error 4 in Danger.integrate: Increment can't be 0.")
"Integration error 4 in Danger.integrate: Increment can't be 0."->Reducer_ErrorValue.REOther->Error
| [
IEvLambda(aLambda),
IEvNumber(min),
@ -185,7 +186,7 @@ module Integration = {
)
| _ =>
Error(
"Integration error 5 in Danger.integrate. Remember that inputs are (function, number (min), number (max), number(increment))",
Reducer_ErrorValue.REOther("Integration error 5 in Danger.integrate. Remember that inputs are (function, number (min), number (max), number(increment))")
)
}
result
@ -208,7 +209,9 @@ module Integration = {
~run=(inputs, _, env, reducer) => {
let result = switch inputs {
| [_, _, _, IEvNumber(0.0)] =>
Error("Integration error in Danger.integrate: Increment can't be 0.")
"Integration error in Danger.integrate: Increment can't be 0."
->Reducer_ErrorValue.REOther
->Error
| [IEvLambda(aLambda), IEvNumber(min), IEvNumber(max), IEvNumber(epsilon)] =>
Helpers.integrateFunctionBetweenWithNumIntegrationPoints(
aLambda,
@ -218,12 +221,13 @@ module Integration = {
env,
reducer,
)->E.R2.errMap(b =>
"Integration error 7 in Danger.integrate. Something went wrong along the way: " ++ b
("Integration error 7 in Danger.integrate. Something went wrong along the way: " ++ b->Reducer_ErrorValue.errorToString)
->Reducer_ErrorValue.REOther
)
| _ =>
Error(
"Integration error 8 in Danger.integrate. Remember that inputs are (function, number (min), number (max), number(increment))",
)
"Integration error 8 in Danger.integrate. Remember that inputs are (function, number (min), number (max), number(increment))"
->Reducer_ErrorValue.REOther
->Error
}
result
},
@ -239,7 +243,7 @@ module DiminishingReturns = {
module Helpers = {
type diminishingReturnsAccumulatorInner = {
optimalAllocations: array<float>,
currentMarginalReturns: result<array<float>, string>,
currentMarginalReturns: result<array<float>, errorValue>,
}
let findBiggestElementIndex = xs =>
E.A.reducei(xs, 0, (acc, newElement, index) => {
@ -248,7 +252,7 @@ module DiminishingReturns = {
| false => acc
}
})
type diminishingReturnsAccumulator = result<diminishingReturnsAccumulatorInner, string>
type diminishingReturnsAccumulator = result<diminishingReturnsAccumulatorInner, errorValue>
// TODO: This is so complicated, it probably should be its own file. It might also make sense to have it work in Rescript directly, taking in a function rather than a reducer; then something else can wrap that function in the reducer/lambdas/environment.
/*
The key idea for this function is that
@ -273,7 +277,7 @@ module DiminishingReturns = {
funds,
approximateIncrement,
environment,
reducer
reducer,
) => {
switch (
E.A.length(lambdas) > 1,
@ -283,19 +287,23 @@ module DiminishingReturns = {
) {
| (false, _, _, _) =>
Error(
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, number of functions should be greater than 1.",
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, number of functions should be greater than 1."
->Reducer_ErrorValue.REOther
)
| (_, false, _, _) =>
Error(
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, funds should be greater than 0.",
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, funds should be greater than 0."
->Reducer_ErrorValue.REOther
)
| (_, _, false, _) =>
Error(
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, approximateIncrement should be greater than 0.",
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, approximateIncrement should be greater than 0."
->Reducer_ErrorValue.REOther
)
| (_, _, _, false) =>
Error(
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, approximateIncrement should be smaller than funds amount.",
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions, approximateIncrement should be smaller than funds amount."
->Reducer_ErrorValue.REOther
)
| (true, true, true, true) => {
let applyFunctionAtPoint = (lambda, point: float) => {
@ -305,13 +313,14 @@ module DiminishingReturns = {
lambda,
[pointAsInternalExpression],
environment,
reducer
reducer,
)
switch resultAsInternalExpression {
| Reducer_T.IEvNumber(x) => Ok(x)
| _ =>
Error(
"Error 1 in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions. It's possible that your function doesn't return a number, try definining auxiliaryFunction(x) = mean(yourFunction(x)) and integrate auxiliaryFunction instead",
"Error 1 in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions. It's possible that your function doesn't return a number, try definining auxiliaryFunction(x) = mean(yourFunction(x)) and integrate auxiliaryFunction instead"
->Reducer_ErrorValue.REOther
)
}
}
@ -403,9 +412,9 @@ module DiminishingReturns = {
switch innerLambda {
| Reducer_T.IEvLambda(lambda) => Ok(lambda)
| _ =>
Error(
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions. A member of the array wasn't a function",
)
"Error in Danger.optimalAllocationGivenDiminishingMarginalReturnsForManyFunctions. A member of the array wasn't a function"
->Reducer_ErrorValue.REOther
->Error
}
}, innerlambdas)
let wrappedLambdas = E.A.R.firstErrorOrOpen(individuallyWrappedLambdas)
@ -424,7 +433,7 @@ module DiminishingReturns = {
}
result
}
| _ => Error("Error in Danger.diminishingMarginalReturnsForTwoFunctions")
| _ => "Error in Danger.diminishingMarginalReturnsForTwoFunctions"->Reducer_ErrorValue.REOther->Error
},
(),
),

View File

@ -17,7 +17,7 @@ module Internals = {
->E.A2.fmap(((key, value)) => Wrappers.evArray([IEvString(key), value]))
->Wrappers.evArray
let fromList = (items: array<internalExpressionValue>): result<internalExpressionValue, string> =>
let fromList = (items: array<internalExpressionValue>): result<internalExpressionValue, errorValue> =>
items
->E.A2.fmap(item => {
switch (item: internalExpressionValue) {
@ -80,7 +80,8 @@ let library = [
->E.R2.fmap(E.Dict.concatMany)
->E.R2.fmap(Js.Dict.map((. r) => FunctionRegistry_Core.FRType.matchReverse(r)))
->E.R2.fmap(r => r->Js.Dict.entries->Belt.Map.String.fromArray)
->E.R2.fmap(Wrappers.evRecord),
->E.R2.fmap(Wrappers.evRecord)
->E.R2.errMap(e => e->Reducer_ErrorValue.REOther),
(),
),
],

View File

@ -16,13 +16,14 @@ module DistributionCreation = {
r
->E.R.bind(Process.DistOrNumberToDist.twoValuesUsingSymbolicDist(~fn, ~values=_, ~env))
->E.R2.fmap(Wrappers.evDistribution)
->E.R2.errMap(e => Reducer_ErrorValue.REOther(e))
let make = (name, fn) => {
FnDefinition.make(
~name,
~inputs=[FRTypeDistOrNumber, FRTypeDistOrNumber],
~run=(_, inputs, env, _) =>
inputs->Prepare.ToValueTuple.twoDistOrNumber->process(~fn, ~env=env),
inputs->Prepare.ToValueTuple.twoDistOrNumber->process(~fn, ~env),
(),
)
}
@ -32,9 +33,7 @@ module DistributionCreation = {
~name,
~inputs=[FRTypeRecord([("p5", FRTypeDistOrNumber), ("p95", FRTypeDistOrNumber)])],
~run=(_, inputs, env, _) =>
inputs
->Prepare.ToValueTuple.Record.twoDistOrNumber
->process(~fn, ~env=env),
inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env),
(),
)
}
@ -44,9 +43,7 @@ module DistributionCreation = {
~name,
~inputs=[FRTypeRecord([("mean", FRTypeDistOrNumber), ("stdev", FRTypeDistOrNumber)])],
~run=(_, inputs, env, _) =>
inputs
->Prepare.ToValueTuple.Record.twoDistOrNumber
->process(~fn, ~env=env),
inputs->Prepare.ToValueTuple.Record.twoDistOrNumber->process(~fn, ~env),
(),
)
}
@ -57,13 +54,14 @@ module DistributionCreation = {
r
->E.R.bind(Process.DistOrNumberToDist.oneValueUsingSymbolicDist(~fn, ~value=_, ~env))
->E.R2.fmap(Wrappers.evDistribution)
->E.R2.errMap(e => Reducer_ErrorValue.REOther(e))
let make = (name, fn) =>
FnDefinition.make(
~name,
~inputs=[FRTypeDistOrNumber],
~run=(_, inputs, env, _) =>
inputs->Prepare.ToValueTuple.oneDistOrNumber->process(~fn, ~env=env),
inputs->Prepare.ToValueTuple.oneDistOrNumber->process(~fn, ~env),
(),
)
}

View File

@ -18,12 +18,10 @@ module Declaration = {
inputs
->E.A2.fmap(getMinMax)
->E.A.R.firstErrorOrOpen
->E.R2.fmap(args => Reducer_T.IEvDeclaration(
Declaration.make(lambda, args),
))
->E.R2.fmap(args => Reducer_T.IEvDeclaration(Declaration.make(lambda, args)))
}
| Error(r) => Error(r)
| Ok(_) => Error(FunctionRegistry_Helpers.impossibleError)
| Ok(_) => Error(impossibleErrorString)
}
}
}
@ -52,7 +50,7 @@ let library = [
~name="declare",
~inputs=[Declaration.frType],
~run=(_, inputs, _, _) => {
inputs->getOrError(0)->E.R.bind(Declaration.fromExpressionValue)
inputs->getOrError(0)->E.R.bind(Declaration.fromExpressionValue)->E.R2.errMap(wrapError)
},
(),
),

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>,
eLambdaValue,
env: Reducer_T.environment,
reducer: Reducer_T.reducerFn
reducer: Reducer_T.reducerFn,
): internalExpressionValue => {
let mappedList = array->E.A.reduceReverse(list{}, (acc, elem) => {
let newElem = Reducer_Expression_Lambda.doLambdaCall(
eLambdaValue,
[elem],
env,
reducer
)
let newElem = Reducer_Expression_Lambda.doLambdaCall(eLambdaValue, [elem], env, reducer)
list{newElem, ...acc}
})
mappedList->Belt.List.toArray->Wrappers.evArray
@ -47,7 +42,7 @@ module Internals = {
initialValue,
aLambdaValue,
env: Reducer_T.environment,
reducer: Reducer_T.reducerFn
reducer: Reducer_T.reducerFn,
) => {
aValueArray->E.A.reduce(initialValue, (acc, elem) =>
Reducer_Expression_Lambda.doLambdaCall(aLambdaValue, [acc, elem], env, reducer)
@ -59,7 +54,7 @@ module Internals = {
initialValue,
aLambdaValue,
env: Reducer_T.environment,
reducer: Reducer_T.reducerFn
reducer: Reducer_T.reducerFn,
) => {
aValueArray->Belt.Array.reduceReverse(initialValue, (acc, elem) =>
Reducer_Expression_Lambda.doLambdaCall(aLambdaValue, [acc, elem], env, reducer)
@ -70,15 +65,10 @@ module Internals = {
aValueArray,
aLambdaValue,
env: Reducer_T.environment,
reducer: Reducer_T.reducerFn
reducer: Reducer_T.reducerFn,
) => {
let mappedList = aValueArray->Belt.Array.reduceReverse(list{}, (acc, elem) => {
let newElem = Reducer_Expression_Lambda.doLambdaCall(
aLambdaValue,
[elem],
env,
reducer
)
let newElem = Reducer_Expression_Lambda.doLambdaCall(aLambdaValue, [elem], env, reducer)
switch newElem {
| IEvBool(true) => list{elem, ...acc}
| _ => acc
@ -124,7 +114,8 @@ let library = [
~run=(_, inputs, _, _) =>
inputs
->Prepare.ToValueTuple.twoNumbers
->E.R2.fmap(((low, high)) => Internals.upTo(low, high)),
->E.R2.fmap(((low, high)) => Internals.upTo(low, high))
->E.R2.errMap(wrapError),
(),
),
],
@ -141,7 +132,7 @@ let library = [
~inputs=[FRTypeArray(FRTypeAny)],
~run=(inputs, _, _, _) =>
switch inputs {
| [IEvArray(array)] => Internals.first(array)
| [IEvArray(array)] => Internals.first(array)->E.R2.errMap(wrapError)
| _ => Error(impossibleError)
},
(),
@ -160,7 +151,7 @@ let library = [
~inputs=[FRTypeArray(FRTypeAny)],
~run=(inputs, _, _, _) =>
switch inputs {
| [IEvArray(array)] => Internals.last(array)
| [IEvArray(array)] => Internals.last(array)->E.R2.errMap(wrapError)
| _ => Error(impossibleError)
},
(),
@ -200,8 +191,7 @@ let library = [
~inputs=[FRTypeArray(FRTypeAny), FRTypeLambda],
~run=(inputs, _, env, reducer) =>
switch inputs {
| [IEvArray(array), IEvLambda(lambda)] =>
Ok(Internals.map(array, lambda, env, reducer))
| [IEvArray(array), IEvLambda(lambda)] => Ok(Internals.map(array, lambda, env, reducer))
| _ => Error(impossibleError)
},
(),

View File

@ -12,7 +12,8 @@ module ArrayNumberDist = {
~run=(_, inputs, _, _) =>
Prepare.ToTypedArray.numbers(inputs)
->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r))
->E.R.bind(fn),
->E.R.bind(fn)
->E.R2.errMap(wrapError),
(),
)
}
@ -23,7 +24,8 @@ module ArrayNumberDist = {
~run=(_, inputs, _, _) =>
Prepare.ToTypedArray.numbers(inputs)
->E.R.bind(r => E.A.length(r) === 0 ? Error("List is empty") : Ok(r))
->E.R.bind(fn),
->E.R.bind(fn)
->E.R2.errMap(wrapError),
(),
)
}

View File

@ -17,19 +17,14 @@ let inputsTodist = (inputs: array<FunctionRegistry_Core.frValue>, makeDist) => {
let expressionValue =
xyCoords
->E.R.bind(r => r->XYShape.T.makeFromZipped->E.R2.errMap(XYShape.Error.toString))
->E.R2.fmap(r => Reducer_T.IEvDistribution(
PointSet(makeDist(r)),
))
->E.R2.fmap(r => Reducer_T.IEvDistribution(PointSet(makeDist(r))))
expressionValue
}
module Internal = {
type t = PointSetDist.t
let toType = (r): result<
Reducer_T.value,
Reducer_ErrorValue.errorValue,
> =>
let toType = (r): result<Reducer_T.value, Reducer_ErrorValue.errorValue> =>
switch r {
| Ok(r) => Ok(Wrappers.evDistribution(PointSet(r)))
| Error(err) => Error(REOperationError(err))
@ -69,7 +64,7 @@ let library = [
)
->E.R2.fmap(Wrappers.pointSet)
->E.R2.fmap(Wrappers.evDistribution)
->E.R2.errMap(_ => "")
->E.R2.errMap(e => Reducer_ErrorValue.REDistributionError(e))
| _ => Error(impossibleError)
},
(),
@ -90,7 +85,7 @@ let library = [
~run=(inputs, _, env, reducer) =>
switch inputs {
| [IEvDistribution(PointSet(dist)), IEvLambda(lambda)] =>
Internal.mapY(dist, lambda, env, reducer)->E.R2.errMap(Reducer_ErrorValue.errorToString)
Internal.mapY(dist, lambda, env, reducer)
| _ => Error(impossibleError)
},
(),
@ -115,7 +110,9 @@ let library = [
FnDefinition.make(
~name="makeContinuous",
~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))],
~run=(_, inputs, _, _) => inputsTodist(inputs, r => Continuous(Continuous.make(r))),
~run=(_, inputs, _, _) =>
inputsTodist(inputs, r => Continuous(Continuous.make(r)))
->E.R2.errMap(wrapError),
(),
),
],
@ -138,7 +135,9 @@ let library = [
FnDefinition.make(
~name="makeDiscrete",
~inputs=[FRTypeArray(FRTypeRecord([("x", FRTypeNumeric), ("y", FRTypeNumeric)]))],
~run=(_, inputs, _, _) => inputsTodist(inputs, r => Discrete(Discrete.make(r))),
~run=(_, inputs, _, _) =>
inputsTodist(inputs, r => Discrete(Discrete.make(r)))
->E.R2.errMap(wrapError),
(),
),
],

View File

@ -18,10 +18,7 @@ module Internal = {
| _ => Error(Operation.SampleMapNeedsNtoNFunction)
}
let toType = (r): result<
Reducer_T.value,
Reducer_ErrorValue.errorValue,
> =>
let toType = (r): result<Reducer_T.value, Reducer_ErrorValue.errorValue> =>
switch r {
| Ok(r) => Ok(Wrappers.evDistribution(SampleSet(r)))
| Error(r) => Error(REDistributionError(SampleSetError(r)))
@ -100,7 +97,7 @@ let libaryBase = [
GenericDist.toSampleSetDist(dist, environment.sampleCount)
->E.R2.fmap(Wrappers.sampleSet)
->E.R2.fmap(Wrappers.evDistribution)
->E.R2.errMap(DistributionTypes.Error.toString)
->E.R2.errMap(e => Reducer_ErrorValue.REDistributionError(e))
| _ => Error(impossibleError)
},
(),
@ -123,7 +120,9 @@ let libaryBase = [
Prepare.ToTypedArray.numbers(inputs) |> E.R2.bind(r =>
SampleSetDist.make(r)->E.R2.errMap(_ => "AM I HERE? WHYERE AMI??")
)
sampleSet->E.R2.fmap(Wrappers.sampleSet)->E.R2.fmap(Wrappers.evDistribution)
sampleSet->E.R2.fmap(Wrappers.sampleSet)
->E.R2.fmap(Wrappers.evDistribution)
->E.R2.errMap(wrapError)
},
(),
),
@ -166,7 +165,7 @@ let libaryBase = [
| [IEvLambda(lambda)] =>
switch Internal.fromFn(lambda, environment, reducer) {
| Ok(r) => Ok(r->Wrappers.sampleSet->Wrappers.evDistribution)
| Error(e) => Error(Operation.Error.toString(e))
| Error(e) => e->Reducer_ErrorValue.REOperationError->Error
}
| _ => Error(impossibleError)
},
@ -188,7 +187,7 @@ let libaryBase = [
~run=(inputs, _, environment, reducer) =>
switch inputs {
| [IEvDistribution(SampleSet(dist)), IEvLambda(lambda)] =>
Internal.map1(dist, lambda, environment, reducer)->E.R2.errMap(_ => "")
Internal.map1(dist, lambda, environment, reducer)
| _ => Error(impossibleError)
},
(),
@ -215,7 +214,7 @@ let libaryBase = [
IEvDistribution(SampleSet(dist2)),
IEvLambda(lambda),
] =>
Internal.map2(dist1, dist2, lambda, environment, reducer)->E.R2.errMap(_ => "")
Internal.map2(dist1, dist2, lambda, environment, reducer)
| _ => Error(impossibleError)
}
},
@ -244,7 +243,7 @@ let libaryBase = [
IEvDistribution(SampleSet(dist3)),
IEvLambda(lambda),
] =>
Internal.map3(dist1, dist2, dist3, lambda, environment, reducer)->E.R2.errMap(_ => "")
Internal.map3(dist1, dist2, dist3, lambda, environment, reducer)
| _ => Error(impossibleError)
},
(),
@ -267,9 +266,7 @@ let libaryBase = [
~run=(inputs, _, environment, reducer) =>
switch inputs {
| [IEvArray(dists), IEvLambda(lambda)] =>
Internal.mapN(dists, lambda, environment, reducer)->E.R2.errMap(_e => {
"AHHH doesn't work"
})
Internal.mapN(dists, lambda, environment, reducer)
| _ => Error(impossibleError)
},
(),
@ -294,7 +291,7 @@ module Comparison = {
let wrapper = r =>
r
->E.R2.fmap(r => r->Wrappers.sampleSet->Wrappers.evDistribution)
->E.R2.errMap(SampleSetDist.Error.toString)
->E.R2.errMap(e => e->DistributionTypes.Error.sampleErrorToDistErr->Reducer_ErrorValue.REDistributionError)
let mkBig = (name, withDist, withFloat) =>
Function.make(

View File

@ -6,7 +6,7 @@ let requiresNamespace = true
let runScoring = (estimate, answer, prior, env) => {
GenericDist.Score.logScore(~estimate, ~answer, ~prior, ~env)
->E.R2.fmap(FunctionRegistry_Helpers.Wrappers.evNumber)
->E.R2.errMap(DistributionTypes.Error.toString)
->E.R2.errMap(e => Reducer_ErrorValue.REDistributionError(e))
}
let library = [
@ -40,7 +40,7 @@ let library = [
FRValueDist(prior),
]) =>
runScoring(estimate, Score_Scalar(d), Some(prior), environment)
| Error(e) => Error(e)
| Error(e) => Error(e->FunctionRegistry_Helpers.wrapError)
| _ => Error(FunctionRegistry_Helpers.impossibleError)
}
},
@ -55,7 +55,7 @@ let library = [
runScoring(estimate, Score_Dist(d), None, environment)
| Ok([FRValueDist(estimate), FRValueDistOrNumber(FRValueNumber(d))]) =>
runScoring(estimate, Score_Scalar(d), None, environment)
| Error(e) => Error(e)
| Error(e) => Error(e->FunctionRegistry_Helpers.wrapError)
| _ => Error(FunctionRegistry_Helpers.impossibleError)
}
},

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
switch container->Belt.MutableMap.String.get(id) {
| Some(v) => Some(v)
| None => switch parent {
| Some(p) => get(p, id)
| None => None
| Some(v) => Some(v)
| None =>
switch parent {
| Some(p) => get(p, id)
| None => None
}
}
}
@ -35,16 +36,12 @@ let set = (nameSpace: t, id: string, value): t => {
nameSpace
}
let extend = (nameSpace: t) => T.NameSpace(
makeEmptyMap(),
nameSpace->Some
)
let extend = (nameSpace: t) => T.NameSpace(makeEmptyMap(), nameSpace->Some)
let toKeyValuePairs = (T.NameSpace(container, _): t): array<(string, internalExpressionValue)> => {
container->Belt.MutableMap.String.toArray
}
let makeEmptyBindings = (): t => T.NameSpace(makeEmptyMap(), None)
let toExpressionValue = (nameSpace: t): internalExpressionValue => T.IEvBindings(nameSpace)
@ -64,7 +61,7 @@ let mergeFrom = (T.NameSpace(container, _): t, T.NameSpace(newContainer, parent)
}
container
}),
parent
parent,
)
}
@ -80,6 +77,8 @@ let removeResult = (nameSpace: t): t => {
nameSpace
}
let locals = (T.NameSpace(container, _): t) => T.NameSpace(container, None)
// let typeAliasesKey = "_typeAliases_"
// let typeReferencesKey = "_typeReferences_"
@ -131,16 +130,6 @@ let removeResult = (nameSpace: t): t => {
// )
// }
// external castExpressionToInternalCode: ExpressionT.expressionOrFFI => internalCode = "%identity"
// let eLambdaFFIValue = (ffiFn: ExpressionT.ffiFn) => {
// IEvLambda({
// parameters: [],
// context: emptyModule,
// body: FFI(ffiFn)->castExpressionToInternalCode,
// })
// }
// let functionNotFoundError = (call: functionCall) =>
// REFunctionNotFound(call->functionCallToCallSignature->functionCallSignatureToString)->Error

View File

@ -3,12 +3,12 @@ type t = Reducer_T.context
let createContext = (stdLib: Reducer_T.nameSpace, environment: Reducer_T.environment): t => {
{
bindings: stdLib->Reducer_Bindings.extend,
environment,
environment: environment,
}
}
let createDefaultContext = (): t =>
createContext(
ReducerInterface_StdLib.internalStdLib,
ReducerInterface_InternalExpressionValue.defaultEnvironment
)
createContext(
ReducerInterface_StdLib.internalStdLib,
ReducerInterface_InternalExpressionValue.defaultEnvironment,
)

View File

@ -33,17 +33,17 @@ let callInternal = (
| call => call->IEV.toStringFunctionCall->MathJs.Eval.eval
}
let constructRecord = arrayOfPairs => {
Belt.Array.map(arrayOfPairs, pairValue =>
switch pairValue {
| Reducer_T.IEvArray([IEvString(key), valueValue]) => (key, valueValue)
| _ => ("wrong key type", pairValue->IEV.toStringWithType->IEvString)
}
)
->Belt.Map.String.fromArray
->Reducer_T.IEvRecord
->Ok
}
// let constructRecord = arrayOfPairs => {
// Belt.Array.map(arrayOfPairs, pairValue =>
// switch pairValue {
// | Reducer_T.IEvArray([IEvString(key), valueValue]) => (key, valueValue)
// | _ => ("wrong key type", pairValue->IEV.toStringWithType->IEvString)
// }
// )
// ->Belt.Map.String.fromArray
// ->Reducer_T.IEvRecord
// ->Ok
// }
// let arrayAtIndex = (aValueArray: array<Reducer_T.value>, fIndex: float) =>
// switch Belt.Array.get(aValueArray, Belt.Int.fromFloat(fIndex)) {
@ -111,7 +111,7 @@ let callInternal = (
| ("$_atIndex_$", [IEvBindings(dict), IEvString(sIndex)]) => moduleAtIndex(dict, sIndex)
// | ("$_atIndex_$", [IEvRecord(dict), IEvString(sIndex)]) => recordAtIndex(dict, sIndex)
// | ("$_constructArray_$", args) => IEvArray(args)->Ok
| ("$_constructRecord_$", [IEvArray(arrayOfPairs)]) => constructRecord(arrayOfPairs)
// | ("$_constructRecord_$", [IEvArray(arrayOfPairs)]) => constructRecord(arrayOfPairs)
// | ("$_exportBindings_$", [IEvBindings(nameSpace)]) => doExportBindings(nameSpace)
// | ("$_exportBindings_$", [evValue]) => doIdentity(evValue)
// | ("$_setBindings_$", [IEvBindings(nameSpace), IEvSymbol(symbol), value]) =>
@ -154,7 +154,9 @@ let callInternal = (
| (_, [IEvString(_), IEvString(_)]) =>
callMathJs(call)
| call =>
Error(REFunctionNotFound(call->IEV.functionCallToCallSignature->IEV.functionCallSignatureToString)) // Report full type signature as error
Error(
REFunctionNotFound(call->IEV.functionCallToCallSignature->IEV.functionCallSignatureToString),
) // Report full type signature as error
}
}
/*
@ -163,7 +165,7 @@ let callInternal = (
let dispatch = (
call: IEV.functionCall,
env: Reducer_T.environment,
reducer: Reducer_T.reducerFn
reducer: Reducer_T.reducerFn,
): Reducer_T.value =>
try {
let (fn, args) = call

View File

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

View File

@ -19,3 +19,4 @@
// array<Reducer_T.value>,
// ProjectAccessorsT.t,
// ) => result<Reducer_T.value, Reducer_ErrorValue.errorValue>

View File

@ -10,78 +10,70 @@ exception ErrorException = Reducer_ErrorValue.ErrorException
/*
Recursively evaluate the expression
*/
let rec evaluate: T.reducerFn = (
expression,
context
) => {
let rec evaluate: T.reducerFn = (expression, context) => {
// Js.log(`reduce: ${expression->Reducer_Expression_T.toString}`)
switch expression {
| T.EBlock(statements) => {
| T.EBlock(statements) => {
let innerContext = {...context, bindings: context.bindings->Bindings.extend}
statements->Js.Array2.reduce(
(_, statement) => statement->evaluate(innerContext),
T.IEvVoid
)
statements->Js.Array2.reduce((_, statement) => statement->evaluate(innerContext), T.IEvVoid)
}
| T.EProgram(statements) => {
| T.EProgram(statements) => {
// Js.log(`bindings: ${context.bindings->Reducer_Bindings.toString}`)
let res = statements->Js.Array2.reduce(
(_, statement) => statement->evaluate(context),
T.IEvVoid
)
let res =
statements->Js.Array2.reduce((_, statement) => statement->evaluate(context), T.IEvVoid)
// Js.log(`bindings after: ${context.bindings->Reducer_Bindings.toString}`)
res
}
| T.EArray(elements) =>
elements->Js.Array2.map(element => evaluate(element, context))->T.IEvArray
| T.EArray(elements) => elements->Js.Array2.map(element => evaluate(element, context))->T.IEvArray
| T.ERecord(pairs) =>
pairs->Js.Array2.map(((eKey, eValue)) => {
let key = eKey->evaluate(context)
let keyString = switch key {
| IEvString(s) => s
| _ => REOther("Record keys must be strings")->ErrorException->raise
}
let value = eValue->evaluate(context)
(keyString, value)
})->Belt.Map.String.fromArray->IEvRecord
| T.ERecord(pairs) =>
pairs
->Js.Array2.map(((eKey, eValue)) => {
let key = eKey->evaluate(context)
let keyString = switch key {
| IEvString(s) => s
| _ => REOther("Record keys must be strings")->ErrorException->raise
}
let value = eValue->evaluate(context)
(keyString, value)
})
->Belt.Map.String.fromArray
->IEvRecord
| T.EAssign(left, right) => {
| T.EAssign(left, right) => {
let result = right->evaluate(context)
let _ = context.bindings->Bindings.set(left, result)
T.IEvVoid
}
| T.ESymbol(name) =>
switch context.bindings->Bindings.get(name) {
| Some(v) => v
| None => Reducer_ErrorValue.RESymbolNotFound(name)->ErrorException->raise
}
| T.ESymbol(name) =>
switch context.bindings->Bindings.get(name) {
| Some(v) => v
| None => Reducer_ErrorValue.RESymbolNotFound(name)->ErrorException->raise
}
| T.EValue(value) =>
value
| T.EValue(value) => value
| T.ETernary(predicate, trueCase, falseCase) => {
| T.ETernary(predicate, trueCase, falseCase) => {
let predicateResult = predicate->evaluate(context)
switch predicateResult {
| T.IEvBool(value) =>
(value ? trueCase : falseCase)->evaluate(context)
| T.IEvBool(value) => (value ? trueCase : falseCase)->evaluate(context)
| _ => REExpectedType("Boolean", "")->ErrorException->raise
}
}
| T.ELambda(parameters, body) =>
Lambda.makeLambda(parameters, context.bindings, body)->T.IEvLambda
| T.ELambda(parameters, body) =>
Lambda.makeLambda(parameters, context.bindings, body)->T.IEvLambda
| T.ECall(fn, args) => {
| T.ECall(fn, args) => {
let lambda = fn->evaluate(context)
let argValues = Js.Array2.map(args, arg => arg->evaluate(context))
switch lambda {
| T.IEvLambda(lambda) =>
Lambda.doLambdaCall(lambda, argValues, context.environment, evaluate)
| _ => REExpectedType("Lambda", "")->ErrorException->raise
| T.IEvLambda(lambda) => Lambda.doLambdaCall(lambda, argValues, context.environment, evaluate)
| _ => REExpectedType("Lambda", "")->ErrorException->raise
}
}
}

View File

@ -1,4 +1,3 @@
module BBindingsReplacer = Reducer_Expression_BindingsReplacer
module BErrorValue = Reducer_ErrorValue
module T = Reducer_T
@ -14,13 +13,9 @@ let eBindings = (anArray: array<(string, T.value)>) =>
let eBool = aBool => aBool->T.IEvBool->T.EValue
let eCall = (fn: expression, args: array<expression>): expression =>
T.ECall(fn, args)
let eCall = (fn: expression, args: array<expression>): expression => T.ECall(fn, args)
let eLambda = (
parameters: array<string>,
expr: expression,
) => T.ELambda(parameters, expr)
let eLambda = (parameters: array<string>, expr: expression) => T.ELambda(parameters, expr)
let eNumber = aNumber => aNumber->T.IEvNumber->T.EValue
@ -28,26 +23,26 @@ let eRecord = (aMap: array<(T.expression, T.expression)>) => aMap->T.ERecord
let eString = aString => aString->T.IEvString->T.EValue
let eSymbol = (name: string): expression =>
T.ESymbol(name)
let eSymbol = (name: string): expression => T.ESymbol(name)
let eBlock = (exprs: array<expression>): expression =>
T.EBlock(exprs)
let eBlock = (exprs: array<expression>): expression => T.EBlock(exprs)
let eProgram = (exprs: array<expression>): expression =>
T.EProgram(exprs)
let eProgram = (exprs: array<expression>): expression => T.EProgram(exprs)
let eModule = (nameSpace: T.nameSpace): expression =>
nameSpace->T.IEvBindings->T.EValue
let eModule = (nameSpace: T.nameSpace): expression => nameSpace->T.IEvBindings->T.EValue
let eLetStatement = (symbol: string, valueExpression: expression): expression =>
T.EAssign(symbol, valueExpression)
let eLetStatement = (symbol: string, valueExpression: expression): expression => T.EAssign(
symbol,
valueExpression,
)
let eTernary = (predicate: expression, trueCase: expression, falseCase: expression): expression =>
T.ETernary(predicate, trueCase, falseCase)
let eTernary = (
predicate: expression,
trueCase: expression,
falseCase: expression,
): expression => T.ETernary(predicate, trueCase, falseCase)
let eIdentifier = (name: string): expression =>
name->T.ESymbol
let eIdentifier = (name: string): expression => name->T.ESymbol
// let eTypeIdentifier = (name: string): expression =>
// name->T.IEvTypeIdentifier->T.EValue

View File

@ -7,7 +7,7 @@ let doLambdaCall = (
lambdaValue: Reducer_T.lambdaValue,
args,
environment: Reducer_T.environment,
reducer: Reducer_T.reducerFn
reducer: Reducer_T.reducerFn,
): Reducer_T.value => {
lambdaValue.body(args, environment, reducer)
}
@ -25,7 +25,7 @@ let makeLambda = (
let lambda = (
arguments: array<Reducer_T.value>,
environment: Reducer_T.environment,
reducer: Reducer_T.reducerFn
reducer: Reducer_T.reducerFn,
) => {
let argsLength = arguments->Js.Array2.length
let parametersLength = parameters->Js.Array2.length
@ -34,23 +34,21 @@ let makeLambda = (
}
let localBindings = bindings->Reducer_Bindings.extend
parameters->Js.Array2.forEachi(
(parameter, index) => {
let _ = localBindings->Reducer_Bindings.set(parameter, arguments[index])
}
)
parameters->Js.Array2.forEachi((parameter, index) => {
let _ = localBindings->Reducer_Bindings.set(parameter, arguments[index])
})
reducer(body, { bindings: localBindings, environment })
reducer(body, {bindings: localBindings, environment: environment})
}
{
// context: bindings,
body: lambda,
parameters,
parameters: parameters,
}
}
let makeFFILambda = (body: Reducer_T.lambdaBody): Reducer_T.lambdaValue => {
body,
parameters: ["..."]
body: body,
parameters: ["..."],
}

View File

@ -27,15 +27,13 @@ let commaJoin = values => values->Reducer_Extra_Array.intersperse(", ")->Js.Stri
*/
let rec toString = (expression: expression) =>
switch expression {
| EBlock(statements) =>
`{${Js.Array2.map(statements, aValue => toString(aValue))->commaJoin}}`
| EProgram(statements) =>
`<${Js.Array2.map(statements, aValue => toString(aValue))->commaJoin}>`
| EArray(aList) =>
`[${Js.Array2.map(aList, aValue => toString(aValue))->commaJoin}]`
| EBlock(statements) => `{${Js.Array2.map(statements, aValue => toString(aValue))->commaJoin}}`
| EProgram(statements) => `<${Js.Array2.map(statements, aValue => toString(aValue))->commaJoin}>`
| EArray(aList) => `[${Js.Array2.map(aList, aValue => toString(aValue))->commaJoin}]`
| ERecord(map) => "TODO"
| ESymbol(name) => name
| ETernary(predicate, trueCase, falseCase) => `${predicate->toString} ? (${trueCase->toString}) : (${falseCase->toString})`
| ETernary(predicate, trueCase, falseCase) =>
`${predicate->toString} ? (${trueCase->toString}) : (${falseCase->toString})`
| EAssign(name, value) => `${name} = ${value->toString}`
| ECall(fn, args) => `(${fn->toString})(${args->Js.Array2.map(toString)->commaJoin})`
| ELambda(parameters, body) => `{|${parameters->commaJoin}| ${body->toString}}`
@ -77,7 +75,3 @@ type optionFfiFnReturningResult = (
array<internalExpressionValue>,
environment,
) => option<result<internalExpressionValue, Reducer_ErrorValue.errorValue>>
type expressionOrFFI =
| NotFFI(expression)
| FFI(ffiFn)

View File

@ -109,14 +109,17 @@ let rec pgToString = (peggyNode: peggyNode): string => {
switch peggyNode {
| PgNodeBlock(node)
| PgNodeProgram(node)
=> "{" ++ node["statements"]->nodesToStringUsingSeparator("; ") ++ "}"
| PgNodeArray(node)
=> "[" ++ node["elements"]->nodesToStringUsingSeparator("; ") ++ "]"
| PgNodeRecord(node)
=> "{" ++ node["elements"]->Js.Array2.map(element => PgNodeKeyValue(element))->pgNodesToStringUsingSeparator(", ") ++ "}"
| PgNodeProgram(node) =>
"{" ++ node["statements"]->nodesToStringUsingSeparator("; ") ++ "}"
| PgNodeArray(node) => "[" ++ node["elements"]->nodesToStringUsingSeparator("; ") ++ "]"
| PgNodeRecord(node) =>
"{" ++
node["elements"]
->Js.Array2.map(element => PgNodeKeyValue(element))
->pgNodesToStringUsingSeparator(", ") ++ "}"
| PgNodeBoolean(node) => node["value"]->Js.String.make
| PgNodeCall(node) => "(" ++ node["fn"]->toString ++ " " ++ node["args"]->nodesToStringUsingSeparator(" ") ++ ")"
| PgNodeCall(node) =>
"(" ++ node["fn"]->toString ++ " " ++ node["args"]->nodesToStringUsingSeparator(" ") ++ ")"
| PgNodeFloat(node) => node["value"]->Js.String.make
| PgNodeIdentifier(node) => `:${node["value"]}`
| PgNodeInteger(node) => node["value"]->Js.String.make

View File

@ -13,29 +13,30 @@ let rec fromNode = (node: Parse.node): expression => {
let caseLambda = (nodeLambda: Parse.nodeLambda): expression => {
let args =
nodeLambda["args"]
->Js.Array2.map((argNode: Parse.nodeIdentifier) => argNode["value"])
nodeLambda["args"]->Js.Array2.map((argNode: Parse.nodeIdentifier) => argNode["value"])
let body = nodeLambda["body"]->fromNode
ExpressionBuilder.eLambda(args, body)
}
let caseRecord = (nodeRecord): expression => {
nodeRecord["elements"]
->Js.Array2.map(
keyValueNode => (keyValueNode["key"]->fromNode, keyValueNode["value"]->fromNode)
)
->Js.Array2.map(keyValueNode => (
keyValueNode["key"]->fromNode,
keyValueNode["value"]->fromNode,
))
->ExpressionBuilder.eRecord
}
switch Parse.castNodeType(node) {
| PgNodeBlock(nodeBlock) => caseBlock(nodeBlock)
| PgNodeProgram(nodeProgram) => caseProgram(nodeProgram)
| PgNodeArray(nodeArray) => ExpressionBuilder.eArray(nodeArray["elements"]->Js.Array2.map(fromNode))
| PgNodeArray(nodeArray) =>
ExpressionBuilder.eArray(nodeArray["elements"]->Js.Array2.map(fromNode))
| PgNodeRecord(nodeRecord) => caseRecord(nodeRecord)
| PgNodeBoolean(nodeBoolean) => ExpressionBuilder.eBool(nodeBoolean["value"])
| PgNodeCall(nodeCall) => ExpressionBuilder.eCall(fromNode(nodeCall["fn"]), nodeCall["args"]->Js.Array2.map(fromNode))
| PgNodeCall(nodeCall) =>
ExpressionBuilder.eCall(fromNode(nodeCall["fn"]), nodeCall["args"]->Js.Array2.map(fromNode))
| PgNodeFloat(nodeFloat) => ExpressionBuilder.eNumber(nodeFloat["value"])
| PgNodeIdentifier(nodeIdentifier) => ExpressionBuilder.eSymbol(nodeIdentifier["value"])
| PgNodeInteger(nodeInteger) => ExpressionBuilder.eNumber(Belt.Int.toFloat(nodeInteger["value"]))
@ -54,7 +55,7 @@ let rec fromNode = (node: Parse.node): expression => {
ExpressionBuilder.eTernary(
fromNode(nodeTernary["condition"]),
fromNode(nodeTernary["trueExpression"]),
fromNode(nodeTernary["falseExpression"])
fromNode(nodeTernary["falseExpression"]),
)
// | PgNodeTypeIdentifier(nodeTypeIdentifier) =>
// ExpressionBuilder.eTypeIdentifier(nodeTypeIdentifier["value"])

View File

@ -25,10 +25,10 @@ type rec value =
and lambdaBody = (array<value>, environment, reducerFn) => value
@genType.opaque
and lambdaValue = {
parameters: array<string>,
// context: nameSpace,
body: (array<value>, environment, reducerFn) => value,
}
parameters: array<string>,
// context: nameSpace,
body: (array<value>, environment, reducerFn) => value,
}
@genType.opaque and lambdaDeclaration = Declaration.declaration<lambdaValue>
and expression =
| EBlock(array<expression>)

View File

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

View File

@ -117,3 +117,4 @@
// | IEvRecord(record) => record->Belt.Map.String.map(fromIEvValue)
// | _ => raise(Reducer_Exception.ImpossibleException("Reducer_Type_T-ievRecord"))
// }

View File

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

View File

@ -179,3 +179,4 @@
// | Error(error) => Error(error) // Directly propagating - err => err - causes type mismatch
// }
// }

View File

@ -1,8 +1,9 @@
module T = Reducer_T
let dispatch = (call: ReducerInterface_InternalExpressionValue.functionCall, _: GenericDist.env): option<
result<T.value, Reducer_ErrorValue.errorValue>,
> => {
let dispatch = (
call: ReducerInterface_InternalExpressionValue.functionCall,
_: GenericDist.env,
): option<result<T.value, Reducer_ErrorValue.errorValue>> => {
switch call {
| ("toString", [IEvDate(t)]) => T.IEvString(DateTime.Date.toString(t))->Ok->Some
| ("makeDateFromYear", [IEvNumber(year)]) =>

View File

@ -3,7 +3,7 @@ module T = Reducer_T
type internalExpressionValue = IEV.t
let dispatch = (call: IEV.functionCall, _: T.environment): option<
result<Reducer_T.value, Reducer_ErrorValue.errorValue>
result<Reducer_T.value, Reducer_ErrorValue.errorValue>,
> => {
switch call {
| ("toString", [IEvTimeDuration(t)]) => T.IEvString(DateTime.Duration.toString(t))->Ok->Some
@ -14,8 +14,7 @@ let dispatch = (call: IEV.functionCall, _: T.environment): option<
| ("fromUnit_hours", [IEvNumber(f)]) =>
T.IEvTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some
| ("days", [IEvNumber(f)]) => T.IEvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
| ("fromUnit_days", [IEvNumber(f)]) =>
T.IEvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
| ("fromUnit_days", [IEvNumber(f)]) => T.IEvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
| ("years", [IEvNumber(f)]) => T.IEvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
| ("fromUnit_years", [IEvNumber(f)]) =>
T.IEvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some

View File

@ -10,7 +10,7 @@ let dispatch = (
chain,
): result<Reducer_T.value, 'e> => {
E.A.O.firstSomeFn([
() => ReducerInterface_GenericDistribution.dispatch(call, environment),
// () => ReducerInterface_GenericDistribution.dispatch(call, environment),
() => ReducerInterface_Date.dispatch(call, environment),
() => ReducerInterface_Duration.dispatch(call, environment),
() => ReducerInterface_Number.dispatch(call, environment),

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 toStringLambda = (lambdaValue: T.lambdaValue) =>
`lambda(${Js.Array2.toString(lambdaValue.parameters)}=>internal code)`
and toStringFunction = (lambdaValue: T.lambdaValue) => `function(${Js.Array2.toString(lambdaValue.parameters)})`
and toStringFunction = (lambdaValue: T.lambdaValue) =>
`function(${Js.Array2.toString(lambdaValue.parameters)})`
and toStringNumber = aNumber => Js.String.make(aNumber)
and toStringRecord = aMap => aMap->toStringMap
and toStringString = aString => `'${aString}'`
@ -75,10 +76,10 @@ and toStringNameSpace = nameSpace => {
->Belt.MutableMap.String.toArray
->Js.Array2.map(((eachKey, eachValue)) => `${eachKey}: ${toString(eachValue)}`)
->Js.Array2.toString
switch parent {
| Some(p) => `{${pairs}} / ${toStringNameSpace(p)}`
| None => `{${pairs}}`
| Some(p) => `{${pairs}} / ${toStringNameSpace(p)}`
| 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
let internalStdLib: Reducer_Bindings.t = {
let res = Reducer_Bindings.makeEmptyBindings()
->SquiggleLibrary_Math.makeBindings
->SquiggleLibrary_Versions.makeBindings
let res =
Reducer_Bindings.makeEmptyBindings()
->SquiggleLibrary_Math.makeBindings
->SquiggleLibrary_Versions.makeBindings
let _ = res->Reducer_Bindings.set("multiply", Reducer_Expression_Lambda.makeFFILambda(
(arguments, _, _) => {
switch arguments {
| [IEvNumber(x), IEvNumber(y)] => IEvNumber(x *. y)
| _ => raise(Not_found)
}
}
)->Reducer_T.IEvLambda)
let _ = res->Reducer_Bindings.set("$_atIndex_$", Reducer_Expression_Lambda.makeFFILambda(
(inputs, _, _) => {
let _ = res->Reducer_Bindings.set(
"$_atIndex_$",
Reducer_Expression_Lambda.makeFFILambda((inputs, _, _) => {
switch inputs {
| [IEvArray(aValueArray), IEvNumber(fIndex)] => {
switch Belt.Array.get(aValueArray, Belt.Int.fromFloat(fIndex)) {
| [IEvArray(aValueArray), IEvNumber(fIndex)] => switch Belt.Array.get(
aValueArray,
Belt.Int.fromFloat(fIndex),
) {
| Some(value) => value
| None => REArrayIndexNotFound("Array index not found", Belt.Int.fromFloat(fIndex))->ErrorException->raise
| None =>
REArrayIndexNotFound("Array index not found", Belt.Int.fromFloat(fIndex))
->ErrorException
->raise
}
}
| [IEvRecord(dict), IEvString(sIndex)] => {
switch Belt.Map.String.get(dict, sIndex) {
| [IEvRecord(dict), IEvString(sIndex)] => switch Belt.Map.String.get(dict, sIndex) {
| Some(value) => value
| None => RERecordPropertyNotFound("Record index not found", sIndex)->ErrorException->raise
}
}
| _ => REOther("Trying to access key on wrong value")->ErrorException->raise
}
}
)->Reducer_T.IEvLambda)
})->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)
// [ ] | ("$_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)
FunctionRegistry_Library.nonRegistryLambdas->Js.Array2.forEach(
((name, lambda)) => {
let _ = res->Reducer_Bindings.set(name, lambda->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
}

View File

@ -85,10 +85,7 @@ let getIncludes = (project: t, sourceId: string): ProjectItem.T.includesType =>
let getPastChain = (project: t, sourceId: string): array<string> =>
project->getItem(sourceId)->ProjectItem.getPastChain
let getIncludesAsVariables = (
project: t,
sourceId: string,
): ProjectItem.T.importAsVariablesType =>
let getIncludesAsVariables = (project: t, sourceId: string): ProjectItem.T.importAsVariablesType =>
project->getItem(sourceId)->ProjectItem.getIncludesAsVariables
let getDirectIncludes = (project: t, sourceId: string): array<string> =>
@ -156,12 +153,10 @@ let setEnvironment = (project: t, value: InternalExpressionValue.environment): u
}
let getBindings = (project: t, sourceId: string): ProjectItem.T.bindingsArgumentType => {
project->getContinuation(sourceId) // TODO - locals method for cleaning parent?
project->getContinuation(sourceId)->Reducer_Bindings.locals
}
let getContinuationsBefore = (project: t, sourceId: string): array<
ProjectItem.T.continuation,
> => {
let getContinuationsBefore = (project: t, sourceId: string): array<ProjectItem.T.continuation> => {
let pastNameSpaces = project->getPastChain(sourceId)->Js.Array2.map(getBindings(project, _))
let theLength = pastNameSpaces->Js.Array2.length
if theLength == 0 {
@ -177,7 +172,8 @@ let getContinuationsBefore = (project: t, sourceId: string): array<
let linkDependencies = (project: t, sourceId: string): ProjectItem.T.continuation => {
let continuationsBefore = project->getContinuationsBefore(sourceId)
let nameSpace = Reducer_Bindings.makeEmptyBindings()->Reducer_Bindings.chainTo(continuationsBefore)
let nameSpace =
Reducer_Bindings.makeEmptyBindings()->Reducer_Bindings.chainTo(continuationsBefore)
let includesAsVariables = project->getIncludesAsVariables(sourceId)
Belt.Array.reduce(includesAsVariables, nameSpace, (currentNameSpace, (variable, includeFile)) =>
Bindings.set(
@ -242,9 +238,7 @@ let evaluate = (sourceCode: string) => {
runAll(project)
(
getResultOption(project, "main")->Belt.Option.getWithDefault(
Reducer_T.IEvVoid->Ok,
),
project->getBindings("main")
getResultOption(project, "main")->Belt.Option.getWithDefault(Reducer_T.IEvVoid->Ok),
project->getBindings("main"),
)
}

View File

@ -5,7 +5,9 @@
"use strict";
function peg$subclass(child, parent) {
function C() { this.constructor = child; }
function C() {
this.constructor = child;
}
C.prototype = parent.prototype;
child.prototype = new C();
}
@ -27,13 +29,15 @@ peg$subclass(peg$SyntaxError, Error);
function peg$padEnd(str, targetLength, padString) {
padString = padString || " ";
if (str.length > targetLength) { return str; }
if (str.length > targetLength) {
return str;
}
targetLength -= str.length;
padString += padString.repeat(targetLength);
return str + padString.slice(0, targetLength);
}
peg$SyntaxError.prototype.format = function(sources) {
peg$SyntaxError.prototype.format = function (sources) {
var str = "Error: " + this.message;
if (this.location) {
var src = null;
@ -48,15 +52,24 @@ peg$SyntaxError.prototype.format = function(sources) {
var loc = this.location.source + ":" + s.line + ":" + s.column;
if (src) {
var e = this.location.end;
var filler = peg$padEnd("", s.line.toString().length, ' ');
var filler = peg$padEnd("", s.line.toString().length, " ");
var line = src[s.line - 1];
var last = s.line === e.line ? e.column : line.length + 1;
var hatLen = (last - s.column) || 1;
str += "\n --> " + loc + "\n"
+ filler + " |\n"
+ s.line + " | " + line + "\n"
+ filler + " | " + peg$padEnd("", s.column - 1, ' ')
+ peg$padEnd("", hatLen, "^");
var hatLen = last - s.column || 1;
str +=
"\n --> " +
loc +
"\n" +
filler +
" |\n" +
s.line +
" | " +
line +
"\n" +
filler +
" | " +
peg$padEnd("", s.column - 1, " ") +
peg$padEnd("", hatLen, "^");
} else {
str += "\n at " + loc;
}
@ -64,33 +77,35 @@ peg$SyntaxError.prototype.format = function(sources) {
return str;
};
peg$SyntaxError.buildMessage = function(expected, found) {
peg$SyntaxError.buildMessage = function (expected, found) {
var DESCRIBE_EXPECTATION_FNS = {
literal: function(expectation) {
return "\"" + literalEscape(expectation.text) + "\"";
literal: function (expectation) {
return '"' + literalEscape(expectation.text) + '"';
},
class: function(expectation) {
var escapedParts = expectation.parts.map(function(part) {
class: function (expectation) {
var escapedParts = expectation.parts.map(function (part) {
return Array.isArray(part)
? classEscape(part[0]) + "-" + classEscape(part[1])
: classEscape(part);
});
return "[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]";
return (
"[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]"
);
},
any: function() {
any: function () {
return "any character";
},
end: function() {
end: function () {
return "end of input";
},
other: function(expectation) {
other: function (expectation) {
return expectation.description;
}
},
};
function hex(ch) {
@ -100,13 +115,17 @@ peg$SyntaxError.buildMessage = function(expected, found) {
function literalEscape(s) {
return s
.replace(/\\/g, "\\\\")
.replace(/"/g, "\\\"")
.replace(/"/g, '\\"')
.replace(/\0/g, "\\0")
.replace(/\t/g, "\\t")
.replace(/\n/g, "\\n")
.replace(/\r/g, "\\r")
.replace(/[\x00-\x0F]/g, function(ch) { return "\\x0" + hex(ch); })
.replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return "\\x" + hex(ch); });
.replace(/[\x00-\x0F]/g, function (ch) {
return "\\x0" + hex(ch);
})
.replace(/[\x10-\x1F\x7F-\x9F]/g, function (ch) {
return "\\x" + hex(ch);
});
}
function classEscape(s) {
@ -114,13 +133,17 @@ peg$SyntaxError.buildMessage = function(expected, found) {
.replace(/\\/g, "\\\\")
.replace(/\]/g, "\\]")
.replace(/\^/g, "\\^")
.replace(/-/g, "\\-")
.replace(/-/g, "\\-")
.replace(/\0/g, "\\0")
.replace(/\t/g, "\\t")
.replace(/\n/g, "\\n")
.replace(/\r/g, "\\r")
.replace(/[\x00-\x0F]/g, function(ch) { return "\\x0" + hex(ch); })
.replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return "\\x" + hex(ch); });
.replace(/[\x00-\x0F]/g, function (ch) {
return "\\x0" + hex(ch);
})
.replace(/[\x10-\x1F\x7F-\x9F]/g, function (ch) {
return "\\x" + hex(ch);
});
}
function describeExpectation(expectation) {
@ -151,17 +174,25 @@ peg$SyntaxError.buildMessage = function(expected, found) {
return descriptions[0] + " or " + descriptions[1];
default:
return descriptions.slice(0, -1).join(", ")
+ ", or "
+ descriptions[descriptions.length - 1];
return (
descriptions.slice(0, -1).join(", ") +
", or " +
descriptions[descriptions.length - 1]
);
}
}
function describeFound(found) {
return found ? "\"" + literalEscape(found) + "\"" : "end of input";
return found ? '"' + literalEscape(found) + '"' : "end of input";
}
return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
return (
"Expected " +
describeExpected(expected) +
" but " +
describeFound(found) +
" found."
);
};
function peg$parse(input, options) {
@ -177,7 +208,7 @@ function peg$parse(input, options) {
var peg$c1 = "#include";
var peg$c2 = "as";
var peg$c3 = "'";
var peg$c4 = "\"";
var peg$c4 = '"';
var peg$c5 = "//";
var peg$c6 = "/*";
var peg$c7 = "*/";
@ -197,8 +228,8 @@ function peg$parse(input, options) {
var peg$e3 = peg$otherExpectation("string");
var peg$e4 = peg$literalExpectation("'", false);
var peg$e5 = peg$classExpectation(["'"], true, false);
var peg$e6 = peg$literalExpectation("\"", false);
var peg$e7 = peg$classExpectation(["\""], true, false);
var peg$e6 = peg$literalExpectation('"', false);
var peg$e7 = peg$classExpectation(['"'], true, false);
var peg$e8 = peg$otherExpectation("comment");
var peg$e9 = peg$literalExpectation("//", false);
var peg$e10 = peg$literalExpectation("/*", false);
@ -212,16 +243,36 @@ function peg$parse(input, options) {
var peg$e18 = peg$classExpectation(["\r", "\n"], true, false);
var peg$e19 = peg$otherExpectation("identifier");
var peg$e20 = peg$classExpectation(["_", ["a", "z"]], false, false);
var peg$e21 = peg$classExpectation(["_", ["a", "z"], ["0", "9"]], false, true);
var peg$e21 = peg$classExpectation(
["_", ["a", "z"], ["0", "9"]],
false,
true
);
var peg$f0 = function(head, tail) {return [head, ...tail].filter( e => e != '');};
var peg$f1 = function() {return [];};
var peg$f2 = function(file, variable) {return [!variable ? '' : variable, file]};
var peg$f3 = function(characters) {return characters.join('');};
var peg$f4 = function(characters) {return characters.join('');};
var peg$f5 = function() { return '';};
var peg$f6 = function() { return '';};
var peg$f7 = function() {return text();};
var peg$f0 = function (head, tail) {
return [head, ...tail].filter((e) => e != "");
};
var peg$f1 = function () {
return [];
};
var peg$f2 = function (file, variable) {
return [!variable ? "" : variable, file];
};
var peg$f3 = function (characters) {
return characters.join("");
};
var peg$f4 = function (characters) {
return characters.join("");
};
var peg$f5 = function () {
return "";
};
var peg$f6 = function () {
return "";
};
var peg$f7 = function () {
return text();
};
var peg$currPos = 0;
var peg$savedPos = 0;
var peg$posDetailsCache = [{ line: 1, column: 1 }];
@ -235,7 +286,9 @@ function peg$parse(input, options) {
if ("startRule" in options) {
if (!(options.startRule in peg$startRuleFunctions)) {
throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
throw new Error(
"Can't start parsing from rule \"" + options.startRule + '".'
);
}
peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
@ -253,7 +306,7 @@ function peg$parse(input, options) {
return {
source: peg$source,
start: peg$savedPos,
end: peg$currPos
end: peg$currPos,
};
}
@ -262,9 +315,10 @@ function peg$parse(input, options) {
}
function expected(description, location) {
location = location !== undefined
? location
: peg$computeLocation(peg$savedPos, peg$currPos);
location =
location !== undefined
? location
: peg$computeLocation(peg$savedPos, peg$currPos);
throw peg$buildStructuredError(
[peg$otherExpectation(description)],
@ -274,9 +328,10 @@ function peg$parse(input, options) {
}
function error(message, location) {
location = location !== undefined
? location
: peg$computeLocation(peg$savedPos, peg$currPos);
location =
location !== undefined
? location
: peg$computeLocation(peg$savedPos, peg$currPos);
throw peg$buildSimpleError(message, location);
}
@ -286,7 +341,12 @@ function peg$parse(input, options) {
}
function peg$classExpectation(parts, inverted, ignoreCase) {
return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase };
return {
type: "class",
parts: parts,
inverted: inverted,
ignoreCase: ignoreCase,
};
}
function peg$anyExpectation() {
@ -316,7 +376,7 @@ function peg$parse(input, options) {
details = peg$posDetailsCache[p];
details = {
line: details.line,
column: details.column
column: details.column,
};
while (p < pos) {
@ -345,18 +405,20 @@ function peg$parse(input, options) {
start: {
offset: startPos,
line: startPosDetails.line,
column: startPosDetails.column
column: startPosDetails.column,
},
end: {
offset: endPos,
line: endPosDetails.line,
column: endPosDetails.column
}
column: endPosDetails.column,
},
};
}
function peg$fail(expected) {
if (peg$currPos < peg$maxFailPos) { return; }
if (peg$currPos < peg$maxFailPos) {
return;
}
if (peg$currPos > peg$maxFailPos) {
peg$maxFailPos = peg$currPos;
@ -516,7 +578,9 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e0); }
if (peg$silentFails === 0) {
peg$fail(peg$e0);
}
}
peg$silentFails--;
if (s2 === peg$FAILED) {
@ -586,7 +650,9 @@ function peg$parse(input, options) {
peg$currPos += 8;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e1); }
if (peg$silentFails === 0) {
peg$fail(peg$e1);
}
}
if (s2 !== peg$FAILED) {
s3 = [];
@ -619,7 +685,9 @@ function peg$parse(input, options) {
peg$currPos += 2;
} else {
s7 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e2); }
if (peg$silentFails === 0) {
peg$fail(peg$e2);
}
}
if (s7 !== peg$FAILED) {
s8 = [];
@ -716,7 +784,9 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e4); }
if (peg$silentFails === 0) {
peg$fail(peg$e4);
}
}
if (s2 !== peg$FAILED) {
s3 = [];
@ -725,7 +795,9 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e5); }
if (peg$silentFails === 0) {
peg$fail(peg$e5);
}
}
while (s4 !== peg$FAILED) {
s3.push(s4);
@ -734,7 +806,9 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e5); }
if (peg$silentFails === 0) {
peg$fail(peg$e5);
}
}
}
if (input.charCodeAt(peg$currPos) === 39) {
@ -742,7 +816,9 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e4); }
if (peg$silentFails === 0) {
peg$fail(peg$e4);
}
}
if (s4 !== peg$FAILED) {
s1 = s3;
@ -767,7 +843,9 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e6); }
if (peg$silentFails === 0) {
peg$fail(peg$e6);
}
}
if (s2 !== peg$FAILED) {
s3 = [];
@ -776,7 +854,9 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e7); }
if (peg$silentFails === 0) {
peg$fail(peg$e7);
}
}
while (s4 !== peg$FAILED) {
s3.push(s4);
@ -785,7 +865,9 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e7); }
if (peg$silentFails === 0) {
peg$fail(peg$e7);
}
}
}
if (input.charCodeAt(peg$currPos) === 34) {
@ -793,7 +875,9 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e6); }
if (peg$silentFails === 0) {
peg$fail(peg$e6);
}
}
if (s4 !== peg$FAILED) {
s1 = s3;
@ -814,7 +898,9 @@ function peg$parse(input, options) {
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e3); }
if (peg$silentFails === 0) {
peg$fail(peg$e3);
}
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -877,7 +963,9 @@ function peg$parse(input, options) {
peg$currPos += 2;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e9); }
if (peg$silentFails === 0) {
peg$fail(peg$e9);
}
}
if (s1 !== peg$FAILED) {
s2 = [];
@ -910,7 +998,9 @@ function peg$parse(input, options) {
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e8); }
if (peg$silentFails === 0) {
peg$fail(peg$e8);
}
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -937,7 +1027,9 @@ function peg$parse(input, options) {
peg$currPos += 2;
} else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e10); }
if (peg$silentFails === 0) {
peg$fail(peg$e10);
}
}
if (s1 !== peg$FAILED) {
s2 = [];
@ -946,7 +1038,9 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e11); }
if (peg$silentFails === 0) {
peg$fail(peg$e11);
}
}
while (s3 !== peg$FAILED) {
s2.push(s3);
@ -955,7 +1049,9 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e11); }
if (peg$silentFails === 0) {
peg$fail(peg$e11);
}
}
}
if (input.substr(peg$currPos, 2) === peg$c7) {
@ -963,7 +1059,9 @@ function peg$parse(input, options) {
peg$currPos += 2;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e12); }
if (peg$silentFails === 0) {
peg$fail(peg$e12);
}
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
@ -979,7 +1077,9 @@ function peg$parse(input, options) {
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e8); }
if (peg$silentFails === 0) {
peg$fail(peg$e8);
}
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -1005,12 +1105,16 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e14); }
if (peg$silentFails === 0) {
peg$fail(peg$e14);
}
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e13); }
if (peg$silentFails === 0) {
peg$fail(peg$e13);
}
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -1036,12 +1140,16 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e16); }
if (peg$silentFails === 0) {
peg$fail(peg$e16);
}
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e15); }
if (peg$silentFails === 0) {
peg$fail(peg$e15);
}
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -1067,12 +1175,16 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e18); }
if (peg$silentFails === 0) {
peg$fail(peg$e18);
}
}
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e17); }
if (peg$silentFails === 0) {
peg$fail(peg$e17);
}
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -1101,7 +1213,9 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e20); }
if (peg$silentFails === 0) {
peg$fail(peg$e20);
}
}
if (s3 !== peg$FAILED) {
while (s3 !== peg$FAILED) {
@ -1111,7 +1225,9 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s3 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e20); }
if (peg$silentFails === 0) {
peg$fail(peg$e20);
}
}
}
} else {
@ -1124,7 +1240,9 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e21); }
if (peg$silentFails === 0) {
peg$fail(peg$e21);
}
}
while (s4 !== peg$FAILED) {
s3.push(s4);
@ -1133,7 +1251,9 @@ function peg$parse(input, options) {
peg$currPos++;
} else {
s4 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e21); }
if (peg$silentFails === 0) {
peg$fail(peg$e21);
}
}
}
s2 = [s2, s3];
@ -1150,7 +1270,9 @@ function peg$parse(input, options) {
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$e19); }
if (peg$silentFails === 0) {
peg$fail(peg$e19);
}
}
peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 };
@ -1179,5 +1301,5 @@ function peg$parse(input, options) {
module.exports = {
SyntaxError: peg$SyntaxError,
parse: peg$parse
parse: peg$parse,
};

View File

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

View File

@ -81,8 +81,10 @@ let setRawParse = (r: t, rawParse: T.rawParseArgumentType): t =>
let setExpression = (r: t, expression: T.expressionArgumentType): t =>
{...r, expression: Some(expression)}->touchExpression
let setContinuation = (r: t, continuation: T.continuationArgumentType): t =>
{...r, continuation: continuation}
let setContinuation = (r: t, continuation: T.continuationArgumentType): t => {
...r,
continuation: continuation,
}
let setResult = (r: t, result: T.resultArgumentType): t => {
...r,
@ -115,10 +117,10 @@ let setIncludes = (this: t, includes: T.includesType): t => {
includes: includes,
}
let setImportAsVariables = (
this: t,
includeAsVariables: T.importAsVariablesType,
): t => {...this, includeAsVariables: includeAsVariables}
let setImportAsVariables = (this: t, includeAsVariables: T.importAsVariablesType): t => {
...this,
includeAsVariables: includeAsVariables,
}
let setDirectImports = (this: t, directIncludes: array<string>): t => {
...this,
@ -161,38 +163,26 @@ let buildExpression = (this: t): t => {
switch this->getExpression {
| Some(_) => this // cached
| None =>
this
->doBuildExpression
->Belt.Option.map(setExpression(this, _))
->E.O2.defaultFn(() => this)
this->doBuildExpression->Belt.Option.map(setExpression(this, _))->E.O2.defaultFn(() => this)
}
}
let failRun = (
this: t,
e: Reducer_ErrorValue.errorValue
): t => this->setResult(e->Error)->setContinuation(Reducer_Bindings.makeEmptyBindings())
let failRun = (this: t, e: Reducer_ErrorValue.errorValue): t =>
this->setResult(e->Error)->setContinuation(Reducer_Bindings.makeEmptyBindings())
let doRun = (
this: t,
context: Reducer_T.context
): t =>
let doRun = (this: t, context: Reducer_T.context): t =>
switch this->getExpression {
| Some(expressionResult) => {
switch expressionResult {
| Ok(expression) => {
try {
let result = Reducer_Expression.evaluate(expression, context)
this->setResult(result->Ok)->setContinuation(context.bindings)
} catch {
| Reducer_ErrorValue.ErrorException(e) => this->failRun(e)
| _ => this->failRun(RETodo("unhandled rescript exception"))
}
}
| Error(e) => this->failRun(e)
| Some(expressionResult) => switch expressionResult {
| Ok(expression) => try {
let result = Reducer_Expression.evaluate(expression, context)
this->setResult(result->Ok)->setContinuation(context.bindings)
} catch {
| Reducer_ErrorValue.ErrorException(e) => this->failRun(e)
| _ => this->failRun(RETodo("unhandled rescript exception"))
}
| Error(e) => this->failRun(e)
}
| None => this->failRun(RETodo("attempt to run without expression"))
| None => this->failRun(RETodo("attempt to run without expression"))
}
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 (_visited, stack) = this->getSourceIds->Belt.Array.reduce((Belt.Map.String.empty, list{}), (
(currVisited, currStack),
currId,
) =>
if !Belt.Map.String.getWithDefault(currVisited, currId, false) {
topologicalSortUtil(this, currId, (currVisited, currStack))
} else {
(currVisited, currStack)
}
)
let (_visited, stack) =
this
->getSourceIds
->Belt.Array.reduce((Belt.Map.String.empty, list{}), ((currVisited, currStack), currId) =>
if !Belt.Map.String.getWithDefault(currVisited, currId, false) {
topologicalSortUtil(this, currId, (currVisited, currStack))
} else {
(currVisited, currStack)
}
)
Belt.List.reverse(stack)->Belt.List.toArray
}

View File

@ -14,9 +14,7 @@ let availableNumbers: array<(string, float)> = [
]
let mathBindings: Bindings.t =
availableNumbers
->E.A2.fmap(((name, v)) => (name, Reducer_T.IEvNumber(v)))
->Bindings.fromArray
availableNumbers->E.A2.fmap(((name, v)) => (name, Reducer_T.IEvNumber(v)))->Bindings.fromArray
let makeBindings = (previousBindings: Bindings.t): Bindings.t =>
previousBindings->Bindings.mergeFrom(mathBindings)

View File

@ -1,9 +1,7 @@
module Bindings = Reducer_Bindings
let bindings: Reducer_T.nameSpace =
[
("System.version", Reducer_T.IEvString("0.4.0-dev")),
]->Bindings.fromArray
[("System.version", Reducer_T.IEvString("0.4.0-dev"))]->Bindings.fromArray
let makeBindings = (previousBindings: Reducer_T.nameSpace): Reducer_T.nameSpace =>
previousBindings->Bindings.mergeFrom(bindings)

View File

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