Reducer InternalExpressionValue created
this will allow complicated changes to execution without changing the typescript interface
This commit is contained in:
parent
27a411e848
commit
ac9a468aa6
|
@ -0,0 +1,4 @@
|
|||
open Jest
|
||||
open Expect
|
||||
|
||||
test("todo", () => expect("1")->toBe("1"))
|
|
@ -19,23 +19,23 @@ describe("bindStatement", () => {
|
|||
testMacro(
|
||||
[],
|
||||
eBindStatement(eBindings([]), exampleStatementY),
|
||||
"Ok((:$_setBindings_$ {} :y 1) context: {})",
|
||||
"Ok((:$_setBindings_$ @{} :y 1) context: @{})",
|
||||
)
|
||||
// Then it answers the bindings for the next statement when reduced
|
||||
testMacroEval([], eBindStatement(eBindings([]), exampleStatementY), "Ok({y: 1})")
|
||||
testMacroEval([], eBindStatement(eBindings([]), exampleStatementY), "Ok(@{y: 1})")
|
||||
// Now let's feed a binding to see what happens
|
||||
testMacro(
|
||||
[],
|
||||
eBindStatement(eBindings([("x", EvNumber(2.))]), exampleStatementX),
|
||||
"Ok((:$_setBindings_$ {x: 2} :y 2) context: {x: 2})",
|
||||
eBindStatement(eBindings([("x", IevNumber(2.))]), exampleStatementX),
|
||||
"Ok((:$_setBindings_$ @{x: 2} :y 2) context: @{x: 2})",
|
||||
)
|
||||
// An expression does not return a binding, thus error
|
||||
testMacro([], eBindStatement(eBindings([]), exampleExpression), "Assignment expected")
|
||||
// When bindings from previous statement are missing the context is injected. This must be the first statement of a block
|
||||
testMacro(
|
||||
[("z", EvNumber(99.))],
|
||||
[("z", IevNumber(99.))],
|
||||
eBindStatementDefault(exampleStatementY),
|
||||
"Ok((:$_setBindings_$ {z: 99} :y 1) context: {z: 99})",
|
||||
"Ok((:$_setBindings_$ @{z: 99} :y 1) context: @{z: 99})",
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -43,26 +43,26 @@ describe("bindExpression", () => {
|
|||
// x is simply bound in the expression
|
||||
testMacro(
|
||||
[],
|
||||
eBindExpression(eBindings([("x", EvNumber(2.))]), eSymbol("x")),
|
||||
"Ok(2 context: {x: 2})",
|
||||
eBindExpression(eBindings([("x", IevNumber(2.))]), eSymbol("x")),
|
||||
"Ok(2 context: @{x: 2})",
|
||||
)
|
||||
// When an let statement is the end expression then bindings are returned
|
||||
testMacro(
|
||||
[],
|
||||
eBindExpression(eBindings([("x", EvNumber(2.))]), exampleStatementY),
|
||||
"Ok((:$_exportBindings_$ (:$_setBindings_$ {x: 2} :y 1)) context: {x: 2})",
|
||||
eBindExpression(eBindings([("x", IevNumber(2.))]), exampleStatementY),
|
||||
"Ok((:$_exportBindings_$ (:$_setBindings_$ @{x: 2} :y 1)) context: @{x: 2})",
|
||||
)
|
||||
// Now let's reduce that expression
|
||||
testMacroEval(
|
||||
[],
|
||||
eBindExpression(eBindings([("x", EvNumber(2.))]), exampleStatementY),
|
||||
"Ok({x: 2,y: 1})",
|
||||
eBindExpression(eBindings([("x", IevNumber(2.))]), exampleStatementY),
|
||||
"Ok(@{x: 2,y: 1})",
|
||||
)
|
||||
// When bindings are missing the context is injected. This must be the first and last statement of a block
|
||||
testMacroEval(
|
||||
[("z", EvNumber(99.))],
|
||||
[("z", IevNumber(99.))],
|
||||
eBindExpressionDefault(exampleStatementY),
|
||||
"Ok({y: 1,z: 99})",
|
||||
"Ok(@{y: 1,z: 99})",
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -72,7 +72,7 @@ describe("block", () => {
|
|||
testMacroEval([], eBlock(list{exampleExpression}), "Ok(1)")
|
||||
// Block with a single statement
|
||||
testMacro([], eBlock(list{exampleStatementY}), "Ok((:$$_bindExpression_$$ (:$_let_$ :y 1)))")
|
||||
testMacroEval([], eBlock(list{exampleStatementY}), "Ok({y: 1})")
|
||||
testMacroEval([], eBlock(list{exampleStatementY}), "Ok(@{y: 1})")
|
||||
// Block with a statement and an expression
|
||||
testMacro(
|
||||
[],
|
||||
|
@ -86,7 +86,7 @@ describe("block", () => {
|
|||
eBlock(list{exampleStatementY, exampleStatementZ}),
|
||||
"Ok((:$$_bindExpression_$$ (:$$_bindStatement_$$ (:$_let_$ :y 1)) (:$_let_$ :z :y)))",
|
||||
)
|
||||
testMacroEval([], eBlock(list{exampleStatementY, exampleStatementZ}), "Ok({y: 1,z: 1})")
|
||||
testMacroEval([], eBlock(list{exampleStatementY, exampleStatementZ}), "Ok(@{y: 1,z: 1})")
|
||||
// Block inside a block
|
||||
testMacro([], eBlock(list{eBlock(list{exampleExpression})}), "Ok((:$$_bindExpression_$$ {1}))")
|
||||
testMacroEval([], eBlock(list{eBlock(list{exampleExpression})}), "Ok(1)")
|
||||
|
@ -99,7 +99,7 @@ describe("block", () => {
|
|||
testMacroEval(
|
||||
[],
|
||||
eBlock(list{eLetStatement("z", eBlock(list{eBlock(list{exampleExpressionY})}))}),
|
||||
"Ok({z: :y})",
|
||||
"Ok(@{z: :y})",
|
||||
)
|
||||
// Empty block
|
||||
testMacro([], eBlock(list{}), "Ok(:undefined block)") //TODO: should be an error
|
||||
|
@ -115,7 +115,7 @@ describe("block", () => {
|
|||
"Ok((:$$_bindExpression_$$ {(:$_let_$ :y (:add :x 1)); :y}))",
|
||||
)
|
||||
testMacroEval(
|
||||
[("x", EvNumber(1.))],
|
||||
[("x", IevNumber(1.))],
|
||||
eBlock(list{
|
||||
eBlock(list{
|
||||
eLetStatement("y", eFunction("add", list{eSymbol("x"), eNumber(1.)})),
|
||||
|
@ -135,12 +135,12 @@ describe("lambda", () => {
|
|||
testMacro([], callLambdaExpression, "Ok(((:$$_lambda_$$ [y] :y) 1))")
|
||||
testMacroEval([], callLambdaExpression, "Ok(1)")
|
||||
// Parameters shadow the outer scope
|
||||
testMacroEval([("y", EvNumber(666.))], callLambdaExpression, "Ok(1)")
|
||||
testMacroEval([("y", IevNumber(666.))], callLambdaExpression, "Ok(1)")
|
||||
// When not shadowed by the parameters, the outer scope variables are available
|
||||
let lambdaExpression = eFunction(
|
||||
"$$_lambda_$$",
|
||||
list{eArrayString(["z"]), eFunction("add", list{eSymbol("y"), eSymbol("z")})},
|
||||
)
|
||||
let callLambdaExpression = eList(list{lambdaExpression, eNumber(1.)})
|
||||
testMacroEval([("y", EvNumber(666.))], callLambdaExpression, "Ok(667)")
|
||||
testMacroEval([("y", IevNumber(666.))], callLambdaExpression, "Ok(667)")
|
||||
})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module ExpressionValue = ReducerInterface.ExpressionValue
|
||||
module ExpressionValue = ReducerInterface.ExternalExpressionValue
|
||||
|
||||
open Jest
|
||||
open Expect
|
||||
|
|
|
@ -1,19 +1,24 @@
|
|||
module ExpressionT = Reducer_Expression_T
|
||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
||||
// Reducer_Helpers
|
||||
module ErrorValue = Reducer_ErrorValue
|
||||
module Bindings = Reducer_Category_Bindings
|
||||
module ExternalExpressionValue = ReducerInterface.ExternalExpressionValue
|
||||
module InternalExpressionValue = ReducerInterface.InternalExpressionValue
|
||||
module Module = Reducer_Category_Module
|
||||
|
||||
let removeDefaults = (ev: ExpressionT.expressionValue): ExpressionT.expressionValue =>
|
||||
switch ev {
|
||||
| EvRecord(extbindings) => {
|
||||
let bindings: Bindings.t = Bindings.fromRecord(extbindings)
|
||||
let keys = Js.Dict.keys(Reducer.defaultExternalBindings)
|
||||
Belt.Map.String.keep(bindings, (key, _value) => {
|
||||
let removeThis = Js.Array2.includes(keys, key)
|
||||
!removeThis
|
||||
})->Bindings.toExpressionValue
|
||||
}
|
||||
let removeDefaultsInternal = (iev: InternalExpressionValue.expressionValue) => {
|
||||
switch iev {
|
||||
| InternalExpressionValue.IevModule(nameSpace) =>
|
||||
Module.removeOther(
|
||||
nameSpace,
|
||||
ReducerInterface.StdLib.internalStdLib,
|
||||
)->InternalExpressionValue.IevModule
|
||||
| value => value
|
||||
}
|
||||
}
|
||||
|
||||
let rRemoveDefaults = r => Belt.Result.map(r, ev => removeDefaults(ev))
|
||||
let removeDefaultsExternal = (
|
||||
ev: ExternalExpressionValue.expressionValue,
|
||||
): ExternalExpressionValue.expressionValue =>
|
||||
ev->InternalExpressionValue.toInternal->removeDefaultsInternal->InternalExpressionValue.toExternal
|
||||
|
||||
let rRemoveDefaultsInternal = r => Belt.Result.map(r, removeDefaultsInternal)
|
||||
let rRemoveDefaultsExternal = r => Belt.Result.map(r, removeDefaultsExternal)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
open ReducerInterface.ExpressionValue
|
||||
module MathJs = Reducer_MathJs
|
||||
module ErrorValue = Reducer.ErrorValue
|
||||
|
||||
|
@ -6,14 +5,14 @@ open Jest
|
|||
open ExpectJs
|
||||
|
||||
describe("eval", () => {
|
||||
test("Number", () => expect(MathJs.Eval.eval("1"))->toEqual(Ok(EvNumber(1.))))
|
||||
test("Number expr", () => expect(MathJs.Eval.eval("1-1"))->toEqual(Ok(EvNumber(0.))))
|
||||
test("String", () => expect(MathJs.Eval.eval("'hello'"))->toEqual(Ok(EvString("hello"))))
|
||||
test("Number", () => expect(MathJs.Eval.eval("1"))->toEqual(Ok(IevNumber(1.))))
|
||||
test("Number expr", () => expect(MathJs.Eval.eval("1-1"))->toEqual(Ok(IevNumber(0.))))
|
||||
test("String", () => expect(MathJs.Eval.eval("'hello'"))->toEqual(Ok(IevString("hello"))))
|
||||
test("String expr", () =>
|
||||
expect(MathJs.Eval.eval("concat('hello ','world')"))->toEqual(Ok(EvString("hello world")))
|
||||
expect(MathJs.Eval.eval("concat('hello ','world')"))->toEqual(Ok(IevString("hello world")))
|
||||
)
|
||||
test("Boolean", () => expect(MathJs.Eval.eval("true"))->toEqual(Ok(EvBool(true))))
|
||||
test("Boolean expr", () => expect(MathJs.Eval.eval("2>1"))->toEqual(Ok(EvBool(true))))
|
||||
test("Boolean", () => expect(MathJs.Eval.eval("true"))->toEqual(Ok(IevBool(true))))
|
||||
test("Boolean expr", () => expect(MathJs.Eval.eval("2>1"))->toEqual(Ok(IevBool(true))))
|
||||
})
|
||||
|
||||
describe("errors", () => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module Expression = Reducer_Expression
|
||||
module ExpressionT = Reducer_Expression_T
|
||||
module ExpressionValue = ReducerInterface_ExpressionValue
|
||||
module ExpressionValue = ReducerInterface.InternalExpressionValue
|
||||
module Parse = Reducer_Peggy_Parse
|
||||
module Result = Belt.Result
|
||||
module ToExpression = Reducer_Peggy_ToExpression
|
||||
|
@ -29,7 +29,7 @@ let expectToExpressionToBe = (expr, answer, ~v="_", ()) => {
|
|||
ExpressionValue.defaultEnvironment,
|
||||
)
|
||||
)
|
||||
->Reducer_Helpers.rRemoveDefaults
|
||||
->Reducer_Helpers.rRemoveDefaultsInternal
|
||||
->ExpressionValue.toStringResultOkless
|
||||
(a1, a2)->expect->toEqual((answer, v))
|
||||
}
|
||||
|
|
|
@ -22,11 +22,11 @@ describe("Peggy to Expression", () => {
|
|||
|
||||
describe("multi-line", () => {
|
||||
testToExpression("x=1; 2", "{(:$_let_$ :x {1}); 2}", ~v="2", ())
|
||||
testToExpression("x=1; y=2", "{(:$_let_$ :x {1}); (:$_let_$ :y {2})}", ~v="{x: 1,y: 2}", ())
|
||||
testToExpression("x=1; y=2", "{(:$_let_$ :x {1}); (:$_let_$ :y {2})}", ~v="@{x: 1,y: 2}", ())
|
||||
})
|
||||
|
||||
describe("variables", () => {
|
||||
testToExpression("x = 1", "{(:$_let_$ :x {1})}", ~v="{x: 1}", ())
|
||||
testToExpression("x = 1", "{(:$_let_$ :x {1})}", ~v="@{x: 1}", ())
|
||||
testToExpression("x", "{:x}", ~v=":x", ()) //TODO: value should return error
|
||||
testToExpression("x = 1; x", "{(:$_let_$ :x {1}); :x}", ~v="1", ())
|
||||
})
|
||||
|
@ -35,7 +35,7 @@ describe("Peggy to Expression", () => {
|
|||
testToExpression(
|
||||
"identity(x) = x",
|
||||
"{(:$_let_$ :identity (:$$_lambda_$$ [x] {:x}))}",
|
||||
~v="{identity: lambda(x=>internal code)}",
|
||||
~v="@{identity: lambda(x=>internal code)}",
|
||||
(),
|
||||
) // Function definitions become lambda assignments
|
||||
testToExpression("identity(x)", "{(:identity :x)}", ()) // Note value returns error properly
|
||||
|
@ -155,7 +155,7 @@ describe("Peggy to Expression", () => {
|
|||
testToExpression(
|
||||
"y=99; x={y=1; y}",
|
||||
"{(:$_let_$ :y {99}); (:$_let_$ :x {(:$_let_$ :y {1}); :y})}",
|
||||
~v="{x: 1,y: 99}",
|
||||
~v="@{x: 1,y: 99}",
|
||||
(),
|
||||
)
|
||||
})
|
||||
|
@ -165,19 +165,19 @@ describe("Peggy to Expression", () => {
|
|||
testToExpression(
|
||||
"f={|x| x}",
|
||||
"{(:$_let_$ :f {(:$$_lambda_$$ [x] {:x})})}",
|
||||
~v="{f: lambda(x=>internal code)}",
|
||||
~v="@{f: lambda(x=>internal code)}",
|
||||
(),
|
||||
)
|
||||
testToExpression(
|
||||
"f(x)=x",
|
||||
"{(:$_let_$ :f (:$$_lambda_$$ [x] {:x}))}",
|
||||
~v="{f: lambda(x=>internal code)}",
|
||||
~v="@{f: lambda(x=>internal code)}",
|
||||
(),
|
||||
) // Function definitions are lambda assignments
|
||||
testToExpression(
|
||||
"f(x)=x ? 1 : 0",
|
||||
"{(:$_let_$ :f (:$$_lambda_$$ [x] {(:$$_ternary_$$ :x 1 0)}))}",
|
||||
~v="{f: lambda(x=>internal code)}",
|
||||
~v="@{f: lambda(x=>internal code)}",
|
||||
(),
|
||||
)
|
||||
})
|
||||
|
|
|
@ -6,7 +6,7 @@ describe("Peggy Types to Expression", () => {
|
|||
testToExpression(
|
||||
"p: number",
|
||||
"{(:$_typeOf_$ :p #number)}",
|
||||
~v="{_typeReferences_: {p: #number}}",
|
||||
~v="@{_typeReferences_: {p: #number}}",
|
||||
(),
|
||||
)
|
||||
})
|
||||
|
@ -14,7 +14,7 @@ describe("Peggy Types to Expression", () => {
|
|||
testToExpression(
|
||||
"type index=number",
|
||||
"{(:$_typeAlias_$ #index #number)}",
|
||||
~v="{_typeAliases_: {index: #number}}",
|
||||
~v="@{_typeAliases_: {index: #number}}",
|
||||
(),
|
||||
)
|
||||
})
|
||||
|
@ -22,7 +22,7 @@ describe("Peggy Types to Expression", () => {
|
|||
testToExpression(
|
||||
"answer: number|string|distribution",
|
||||
"{(:$_typeOf_$ :answer (:$_typeOr_$ (:$_constructArray_$ (#number #string #distribution))))}",
|
||||
~v="{_typeReferences_: {answer: {typeTag: 'typeOr',typeOr: [#number,#string,#distribution]}}}",
|
||||
~v="@{_typeReferences_: {answer: {typeOr: [#number,#string,#distribution],typeTag: 'typeOr'}}}",
|
||||
(),
|
||||
)
|
||||
})
|
||||
|
@ -30,13 +30,13 @@ describe("Peggy Types to Expression", () => {
|
|||
testToExpression(
|
||||
"f: number=>number=>number",
|
||||
"{(:$_typeOf_$ :f (:$_typeFunction_$ (:$_constructArray_$ (#number #number #number))))}",
|
||||
~v="{_typeReferences_: {f: {typeTag: 'typeFunction',inputs: [#number,#number],output: #number}}}",
|
||||
~v="@{_typeReferences_: {f: {inputs: [#number,#number],output: #number,typeTag: 'typeFunction'}}}",
|
||||
(),
|
||||
)
|
||||
testToExpression(
|
||||
"f: number=>number",
|
||||
"{(:$_typeOf_$ :f (:$_typeFunction_$ (:$_constructArray_$ (#number #number))))}",
|
||||
~v="{_typeReferences_: {f: {typeTag: 'typeFunction',inputs: [#number],output: #number}}}",
|
||||
~v="@{_typeReferences_: {f: {inputs: [#number],output: #number,typeTag: 'typeFunction'}}}",
|
||||
(),
|
||||
)
|
||||
})
|
||||
|
@ -44,37 +44,37 @@ describe("Peggy Types to Expression", () => {
|
|||
testToExpression(
|
||||
"answer: number<-min(1)<-max(100)|string",
|
||||
"{(:$_typeOf_$ :answer (:$_typeOr_$ (:$_constructArray_$ ((:$_typeModifier_max_$ (:$_typeModifier_min_$ #number 1) 100) #string))))}",
|
||||
~v="{_typeReferences_: {answer: {typeTag: 'typeOr',typeOr: [{typeTag: 'typeIdentifier',typeIdentifier: #number,min: 1,max: 100},#string]}}}",
|
||||
~v="@{_typeReferences_: {answer: {typeOr: [{max: 100,min: 1,typeIdentifier: #number,typeTag: 'typeIdentifier'},#string],typeTag: 'typeOr'}}}",
|
||||
(),
|
||||
)
|
||||
testToExpression(
|
||||
"answer: number<-memberOf([1,3,5])",
|
||||
"{(:$_typeOf_$ :answer (:$_typeModifier_memberOf_$ #number (:$_constructArray_$ (1 3 5))))}",
|
||||
~v="{_typeReferences_: {answer: {typeTag: 'typeIdentifier',typeIdentifier: #number,memberOf: [1,3,5]}}}",
|
||||
~v="@{_typeReferences_: {answer: {memberOf: [1,3,5],typeIdentifier: #number,typeTag: 'typeIdentifier'}}}",
|
||||
(),
|
||||
)
|
||||
testToExpression(
|
||||
"answer: number<-min(1)",
|
||||
"{(:$_typeOf_$ :answer (:$_typeModifier_min_$ #number 1))}",
|
||||
~v="{_typeReferences_: {answer: {typeTag: 'typeIdentifier',typeIdentifier: #number,min: 1}}}",
|
||||
~v="@{_typeReferences_: {answer: {min: 1,typeIdentifier: #number,typeTag: 'typeIdentifier'}}}",
|
||||
(),
|
||||
)
|
||||
testToExpression(
|
||||
"answer: number<-max(10)",
|
||||
"{(:$_typeOf_$ :answer (:$_typeModifier_max_$ #number 10))}",
|
||||
~v="{_typeReferences_: {answer: {typeTag: 'typeIdentifier',typeIdentifier: #number,max: 10}}}",
|
||||
~v="@{_typeReferences_: {answer: {max: 10,typeIdentifier: #number,typeTag: 'typeIdentifier'}}}",
|
||||
(),
|
||||
)
|
||||
testToExpression(
|
||||
"answer: number<-min(1)<-max(10)",
|
||||
"{(:$_typeOf_$ :answer (:$_typeModifier_max_$ (:$_typeModifier_min_$ #number 1) 10))}",
|
||||
~v="{_typeReferences_: {answer: {typeTag: 'typeIdentifier',typeIdentifier: #number,min: 1,max: 10}}}",
|
||||
~v="@{_typeReferences_: {answer: {max: 10,min: 1,typeIdentifier: #number,typeTag: 'typeIdentifier'}}}",
|
||||
(),
|
||||
)
|
||||
testToExpression(
|
||||
"answer: number<-max(10)<-min(1)",
|
||||
"{(:$_typeOf_$ :answer (:$_typeModifier_min_$ (:$_typeModifier_max_$ #number 10) 1))}",
|
||||
~v="{_typeReferences_: {answer: {typeTag: 'typeIdentifier',typeIdentifier: #number,max: 10,min: 1}}}",
|
||||
~v="@{_typeReferences_: {answer: {max: 10,min: 1,typeIdentifier: #number,typeTag: 'typeIdentifier'}}}",
|
||||
(),
|
||||
)
|
||||
})
|
||||
|
@ -82,7 +82,7 @@ describe("Peggy Types to Expression", () => {
|
|||
testToExpression(
|
||||
"answer: number | string $ opaque",
|
||||
"{(:$_typeOf_$ :answer (:$_typeModifier_opaque_$ (:$_typeOr_$ (:$_constructArray_$ (#number #string)))))}",
|
||||
~v="{_typeReferences_: {answer: {typeTag: 'typeOr',typeOr: [#number,#string],opaque: true}}}",
|
||||
~v="@{_typeReferences_: {answer: {opaque: true,typeOr: [#number,#string],typeTag: 'typeOr'}}}",
|
||||
(),
|
||||
)
|
||||
})
|
||||
|
@ -90,7 +90,7 @@ describe("Peggy Types to Expression", () => {
|
|||
testToExpression(
|
||||
"odds1 = [1,3,5]; odds2 = [7, 9]; type odds = number<-memberOf(concat(odds1, odds2))",
|
||||
"{(:$_let_$ :odds1 {(:$_constructArray_$ (1 3 5))}); (:$_let_$ :odds2 {(:$_constructArray_$ (7 9))}); (:$_typeAlias_$ #odds (:$_typeModifier_memberOf_$ #number (:concat :odds1 :odds2)))}",
|
||||
~v="{_typeAliases_: {odds: {typeTag: 'typeIdentifier',typeIdentifier: #number,memberOf: [1,3,5,7,9]}},odds1: [1,3,5],odds2: [7,9]}",
|
||||
~v="@{_typeAliases_: {odds: {memberOf: [1,3,5,7,9],typeIdentifier: #number,typeTag: 'typeIdentifier'}},odds1: [1,3,5],odds2: [7,9]}",
|
||||
(),
|
||||
)
|
||||
})
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
module ExpressionT = Reducer_Expression_T
|
||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
||||
module ExternalExpressionValue = ReducerInterface.ExternalExpressionValue
|
||||
module ErrorValue = Reducer_ErrorValue
|
||||
module Bindings = Reducer_Category_Bindings
|
||||
|
||||
open Jest
|
||||
open Expect
|
||||
|
@ -9,7 +8,7 @@ open Expect
|
|||
let unwrapRecord = rValue =>
|
||||
rValue->Belt.Result.flatMap(value =>
|
||||
switch value {
|
||||
| ExpressionValue.EvRecord(aRecord) => Ok(aRecord)
|
||||
| ExternalExpressionValue.EvRecord(aRecord) => Ok(aRecord)
|
||||
| _ => ErrorValue.RETodo("TODO: External bindings must be returned")->Error
|
||||
}
|
||||
)
|
||||
|
@ -19,18 +18,18 @@ let expectParseToBe = (expr: string, answer: string) =>
|
|||
|
||||
let expectEvalToBe = (expr: string, answer: string) =>
|
||||
Reducer.evaluate(expr)
|
||||
->Reducer_Helpers.rRemoveDefaults
|
||||
->ExpressionValue.toStringResult
|
||||
->Reducer_Helpers.rRemoveDefaultsExternal
|
||||
->ExternalExpressionValue.toStringResult
|
||||
->expect
|
||||
->toBe(answer)
|
||||
|
||||
let expectEvalError = (expr: string) =>
|
||||
Reducer.evaluate(expr)->ExpressionValue.toStringResult->expect->toMatch("Error\(")
|
||||
Reducer.evaluate(expr)->ExternalExpressionValue.toStringResult->expect->toMatch("Error\(")
|
||||
|
||||
let expectEvalBindingsToBe = (expr: string, bindings: Reducer.externalBindings, answer: string) =>
|
||||
Reducer.evaluateUsingOptions(expr, ~externalBindings=Some(bindings), ~environment=None)
|
||||
->Reducer_Helpers.rRemoveDefaults
|
||||
->ExpressionValue.toStringResult
|
||||
->Reducer_Helpers.rRemoveDefaultsExternal
|
||||
->ExternalExpressionValue.toStringResult
|
||||
->expect
|
||||
->toBe(answer)
|
||||
|
||||
|
|
|
@ -1,25 +1,27 @@
|
|||
open Jest
|
||||
open Expect
|
||||
|
||||
module Bindings = Reducer_Expression_Bindings
|
||||
module BindingsReplacer = Reducer_Expression_BindingsReplacer
|
||||
module Expression = Reducer_Expression
|
||||
module ExpressionValue = ReducerInterface_ExpressionValue
|
||||
// module ExpressionValue = ReducerInterface.ExpressionValue
|
||||
module InternalExpressionValue = ReducerInterface.InternalExpressionValue
|
||||
module ExpressionWithContext = Reducer_ExpressionWithContext
|
||||
module Macro = Reducer_Expression_Macro
|
||||
module T = Reducer_Expression_T
|
||||
module Module = Reducer_Category_Module
|
||||
|
||||
let testMacro_ = (
|
||||
tester,
|
||||
bindArray: array<(string, ExpressionValue.expressionValue)>,
|
||||
bindArray: array<(string, InternalExpressionValue.expressionValue)>,
|
||||
expr: T.expression,
|
||||
expectedCode: string,
|
||||
) => {
|
||||
let bindings = Belt.Map.String.fromArray(bindArray)
|
||||
let bindings = Module.fromArray(bindArray)
|
||||
tester(expr->T.toString, () =>
|
||||
expr
|
||||
->Macro.expandMacroCall(
|
||||
bindings,
|
||||
ExpressionValue.defaultEnvironment,
|
||||
InternalExpressionValue.defaultEnvironment,
|
||||
Expression.reduceExpression,
|
||||
)
|
||||
->ExpressionWithContext.toStringResult
|
||||
|
@ -30,39 +32,43 @@ let testMacro_ = (
|
|||
|
||||
let testMacroEval_ = (
|
||||
tester,
|
||||
bindArray: array<(string, ExpressionValue.expressionValue)>,
|
||||
bindArray: array<(string, InternalExpressionValue.expressionValue)>,
|
||||
expr: T.expression,
|
||||
expectedValue: string,
|
||||
) => {
|
||||
let bindings = Belt.Map.String.fromArray(bindArray)
|
||||
let bindings = Module.fromArray(bindArray)
|
||||
tester(expr->T.toString, () =>
|
||||
expr
|
||||
->Macro.doMacroCall(bindings, ExpressionValue.defaultEnvironment, Expression.reduceExpression)
|
||||
->ExpressionValue.toStringResult
|
||||
->Macro.doMacroCall(
|
||||
bindings,
|
||||
InternalExpressionValue.defaultEnvironment,
|
||||
Expression.reduceExpression,
|
||||
)
|
||||
->InternalExpressionValue.toStringResult
|
||||
->expect
|
||||
->toEqual(expectedValue)
|
||||
)
|
||||
}
|
||||
|
||||
let testMacro = (
|
||||
bindArray: array<(string, ExpressionValue.expressionValue)>,
|
||||
bindArray: array<(string, InternalExpressionValue.expressionValue)>,
|
||||
expr: T.expression,
|
||||
expectedExpr: string,
|
||||
) => testMacro_(test, bindArray, expr, expectedExpr)
|
||||
let testMacroEval = (
|
||||
bindArray: array<(string, ExpressionValue.expressionValue)>,
|
||||
bindArray: array<(string, InternalExpressionValue.expressionValue)>,
|
||||
expr: T.expression,
|
||||
expectedValue: string,
|
||||
) => testMacroEval_(test, bindArray, expr, expectedValue)
|
||||
|
||||
module MySkip = {
|
||||
let testMacro = (
|
||||
bindArray: array<(string, ExpressionValue.expressionValue)>,
|
||||
bindArray: array<(string, InternalExpressionValue.expressionValue)>,
|
||||
expr: T.expression,
|
||||
expectedExpr: string,
|
||||
) => testMacro_(Skip.test, bindArray, expr, expectedExpr)
|
||||
let testMacroEval = (
|
||||
bindArray: array<(string, ExpressionValue.expressionValue)>,
|
||||
bindArray: array<(string, InternalExpressionValue.expressionValue)>,
|
||||
expr: T.expression,
|
||||
expectedValue: string,
|
||||
) => testMacroEval_(Skip.test, bindArray, expr, expectedValue)
|
||||
|
@ -70,12 +76,12 @@ module MySkip = {
|
|||
|
||||
module MyOnly = {
|
||||
let testMacro = (
|
||||
bindArray: array<(string, ExpressionValue.expressionValue)>,
|
||||
bindArray: array<(string, InternalExpressionValue.expressionValue)>,
|
||||
expr: T.expression,
|
||||
expectedExpr: string,
|
||||
) => testMacro_(Only.test, bindArray, expr, expectedExpr)
|
||||
let testMacroEval = (
|
||||
bindArray: array<(string, ExpressionValue.expressionValue)>,
|
||||
bindArray: array<(string, InternalExpressionValue.expressionValue)>,
|
||||
expr: T.expression,
|
||||
expectedValue: string,
|
||||
) => testMacroEval_(Only.test, bindArray, expr, expectedValue)
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
// TODO: Reimplement with usual parse
|
||||
open Jest
|
||||
open Reducer_TestHelpers
|
||||
|
||||
describe("Eval with Bindings", () => {
|
||||
testEvalBindingsToBe("x", list{("x", ExpressionValue.EvNumber(1.))}, "Ok(1)")
|
||||
testEvalBindingsToBe("x+1", list{("x", ExpressionValue.EvNumber(1.))}, "Ok(2)")
|
||||
testEvalBindingsToBe("x", list{("x", ExternalExpressionValue.EvNumber(1.))}, "Ok(1)")
|
||||
testEvalBindingsToBe("x+1", list{("x", ExternalExpressionValue.EvNumber(1.))}, "Ok(2)")
|
||||
testParseToBe("y = x+1; y", "Ok({(:$_let_$ :y {(:add :x 1)}); :y})")
|
||||
testEvalBindingsToBe("y = x+1; y", list{("x", ExpressionValue.EvNumber(1.))}, "Ok(2)")
|
||||
testEvalBindingsToBe("y = x+1", list{("x", ExpressionValue.EvNumber(1.))}, "Ok({x: 1,y: 2})")
|
||||
testEvalBindingsToBe("y = x+1; y", list{("x", ExternalExpressionValue.EvNumber(1.))}, "Ok(2)")
|
||||
testEvalBindingsToBe(
|
||||
"y = x+1",
|
||||
list{("x", ExternalExpressionValue.EvNumber(1.))},
|
||||
"Ok(@{x: 1,y: 2})",
|
||||
)
|
||||
})
|
||||
|
|
|
@ -39,15 +39,15 @@ describe("symbol not defined", () => {
|
|||
})
|
||||
|
||||
describe("call and bindings", () => {
|
||||
testEvalToBe("f(x)=x+1", "Ok({f: lambda(x=>internal code)})")
|
||||
testEvalToBe("f(x)=x+1", "Ok(@{f: lambda(x=>internal code)})")
|
||||
testEvalToBe("f(x)=x+1; f(1)", "Ok(2)")
|
||||
testEvalToBe("f=1;y=2", "Ok({f: 1,y: 2})")
|
||||
testEvalToBe("f(x)=x+1; y=f(1)", "Ok({f: lambda(x=>internal code),y: 2})")
|
||||
testEvalToBe("f=1;y=2", "Ok(@{f: 1,y: 2})")
|
||||
testEvalToBe("f(x)=x+1; y=f(1)", "Ok(@{f: lambda(x=>internal code),y: 2})")
|
||||
testEvalToBe("f(x)=x+1; y=f(1); f(1)", "Ok(2)")
|
||||
testEvalToBe("f(x)=x+1; y=f(1); z=f(1)", "Ok({f: lambda(x=>internal code),y: 2,z: 2})")
|
||||
testEvalToBe("f(x)=x+1; y=f(1); z=f(1)", "Ok(@{f: lambda(x=>internal code),y: 2,z: 2})")
|
||||
testEvalToBe(
|
||||
"f(x)=x+1; g(x)=f(x)+1",
|
||||
"Ok({f: lambda(x=>internal code),g: lambda(x=>internal code)})",
|
||||
"Ok(@{f: lambda(x=>internal code),g: lambda(x=>internal code)})",
|
||||
)
|
||||
testParseToBe(
|
||||
"f=99; g(x)=f; g(2)",
|
||||
|
@ -57,7 +57,7 @@ describe("call and bindings", () => {
|
|||
testEvalToBe("f(x)=x; g(x)=f(x); g(2)", "Ok(2)")
|
||||
testEvalToBe(
|
||||
"f(x)=x+1; g(x)=f(x)+1; y=g(2)",
|
||||
"Ok({f: lambda(x=>internal code),g: lambda(x=>internal code),y: 4})",
|
||||
"Ok(@{f: lambda(x=>internal code),g: lambda(x=>internal code),y: 4})",
|
||||
)
|
||||
testEvalToBe("f(x)=x+1; g(x)=f(x)+1; g(2)", "Ok(4)")
|
||||
})
|
||||
|
@ -65,7 +65,7 @@ describe("call and bindings", () => {
|
|||
describe("function tricks", () => {
|
||||
testEvalError("f(x)=f(y)=2; f(2)") //Error because chain assignment is not allowed
|
||||
testEvalToBe("y=2;g(x)=y+1;g(2)", "Ok(3)")
|
||||
testEvalToBe("y=2;g(x)=inspect(y)+1", "Ok({g: lambda(x=>internal code),y: 2})")
|
||||
testEvalToBe("y=2;g(x)=inspect(y)+1", "Ok(@{g: lambda(x=>internal code),y: 2})")
|
||||
MySkip.testEvalToBe("f(x) = x(x); f(f)", "????") // TODO: Infinite loop. Any solution? Catching proper exception or timeout?
|
||||
MySkip.testEvalToBe("f(x, x)=x+x; f(1,2)", "????") // TODO: Duplicate parameters
|
||||
testEvalToBe("myadd(x,y)=x+y; z=myadd; z", "Ok(lambda(x,y=>internal code))")
|
||||
|
@ -75,7 +75,7 @@ describe("function tricks", () => {
|
|||
describe("lambda in structures", () => {
|
||||
testEvalToBe(
|
||||
"myadd(x,y)=x+y; z=[myadd]",
|
||||
"Ok({myadd: lambda(x,y=>internal code),z: [lambda(x,y=>internal code)]})",
|
||||
"Ok(@{myadd: lambda(x,y=>internal code),z: [lambda(x,y=>internal code)]})",
|
||||
)
|
||||
testEvalToBe("myadd(x,y)=x+y; z=[myadd]; z[0]", "Ok(lambda(x,y=>internal code))")
|
||||
testEvalToBe("myadd(x,y)=x+y; z=[myadd]; z[0](3,2)", "Ok(5)")
|
||||
|
|
|
@ -39,7 +39,7 @@ describe("eval", () => {
|
|||
testEvalToBe("x=1; y=x+1; y+1", "Ok(3)")
|
||||
testEvalError("1; x=1")
|
||||
testEvalError("1; 1")
|
||||
testEvalToBe("x=1; x=1", "Ok({x: 1})")
|
||||
testEvalToBe("x=1; x=1", "Ok(@{x: 1})")
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
open ReducerInterface.ExpressionValue
|
||||
open ReducerInterface.ExternalExpressionValue
|
||||
open Jest
|
||||
open Expect
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"license": "MIT",
|
||||
"scripts": {
|
||||
"peggy": "peggy --cache",
|
||||
"rescript": "rescript",
|
||||
"build": "yarn build:peggy && yarn build:rescript && yarn build:typescript",
|
||||
"build:peggy": "find . -type f -name *.peggy -exec yarn peggy {} \\;",
|
||||
"build:rescript": "rescript build -with-deps",
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
@@warning("-27") //TODO: Remove and fix the warning
|
||||
open Distributions
|
||||
|
||||
type t = PointSetTypes.discreteShape
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@@warning("-27") //TODO: Remove and fix the warning
|
||||
@@warning("-32") //TODO: Remove and fix the warning
|
||||
open Distributions
|
||||
|
||||
type t = PointSetTypes.mixedShape
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
||||
type expressionValue = ReducerInterface_InternalExpressionValue.expressionValue
|
||||
|
||||
/*
|
||||
Function Registry "Type". A type, without any other information.
|
||||
|
@ -28,7 +28,7 @@ type rec frValue =
|
|||
| FRValueArray(array<frValue>)
|
||||
| FRValueDistOrNumber(frValueDistOrNumber)
|
||||
| FRValueRecord(frValueRecord)
|
||||
| FRValueLambda(ReducerInterface_ExpressionValue.lambdaValue)
|
||||
| FRValueLambda(ReducerInterface_InternalExpressionValue.lambdaValue)
|
||||
| FRValueString(string)
|
||||
| FRValueVariant(string)
|
||||
| FRValueAny(frValue)
|
||||
|
@ -75,14 +75,14 @@ module FRType = {
|
|||
|
||||
let rec toFrValue = (r: expressionValue): option<frValue> =>
|
||||
switch r {
|
||||
| EvNumber(f) => Some(FRValueNumber(f))
|
||||
| EvString(f) => Some(FRValueString(f))
|
||||
| EvDistribution(f) => Some(FRValueDistOrNumber(FRValueDist(f)))
|
||||
| EvLambda(f) => Some(FRValueLambda(f))
|
||||
| EvArray(elements) =>
|
||||
| IevNumber(f) => Some(FRValueNumber(f))
|
||||
| IevString(f) => Some(FRValueString(f))
|
||||
| IevDistribution(f) => Some(FRValueDistOrNumber(FRValueDist(f)))
|
||||
| IevLambda(f) => Some(FRValueLambda(f))
|
||||
| IevArray(elements) =>
|
||||
elements->E.A2.fmap(toFrValue)->E.A.O.openIfAllSome->E.O2.fmap(r => FRValueArray(r))
|
||||
| EvRecord(record) =>
|
||||
Js.Dict.entries(record)
|
||||
| IevRecord(map) =>
|
||||
Belt.Map.String.toArray(map)
|
||||
->E.A2.fmap(((key, item)) => item->toFrValue->E.O2.fmap(o => (key, o)))
|
||||
->E.A.O.openIfAllSome
|
||||
->E.O2.fmap(r => FRValueRecord(r))
|
||||
|
@ -92,28 +92,28 @@ module FRType = {
|
|||
let rec matchWithExpressionValue = (t: t, r: expressionValue): option<frValue> =>
|
||||
switch (t, r) {
|
||||
| (FRTypeAny, f) => toFrValue(f)
|
||||
| (FRTypeString, EvString(f)) => Some(FRValueString(f))
|
||||
| (FRTypeNumber, EvNumber(f)) => Some(FRValueNumber(f))
|
||||
| (FRTypeDistOrNumber, EvNumber(f)) => Some(FRValueDistOrNumber(FRValueNumber(f)))
|
||||
| (FRTypeDistOrNumber, EvDistribution(Symbolic(#Float(f)))) =>
|
||||
| (FRTypeString, IevString(f)) => Some(FRValueString(f))
|
||||
| (FRTypeNumber, IevNumber(f)) => Some(FRValueNumber(f))
|
||||
| (FRTypeDistOrNumber, IevNumber(f)) => Some(FRValueDistOrNumber(FRValueNumber(f)))
|
||||
| (FRTypeDistOrNumber, IevDistribution(Symbolic(#Float(f)))) =>
|
||||
Some(FRValueDistOrNumber(FRValueNumber(f)))
|
||||
| (FRTypeDistOrNumber, EvDistribution(f)) => Some(FRValueDistOrNumber(FRValueDist(f)))
|
||||
| (FRTypeNumeric, EvNumber(f)) => Some(FRValueNumber(f))
|
||||
| (FRTypeNumeric, EvDistribution(Symbolic(#Float(f)))) => Some(FRValueNumber(f))
|
||||
| (FRTypeLambda, EvLambda(f)) => Some(FRValueLambda(f))
|
||||
| (FRTypeArray(intendedType), EvArray(elements)) => {
|
||||
| (FRTypeDistOrNumber, IevDistribution(f)) => Some(FRValueDistOrNumber(FRValueDist(f)))
|
||||
| (FRTypeNumeric, IevNumber(f)) => Some(FRValueNumber(f))
|
||||
| (FRTypeNumeric, IevDistribution(Symbolic(#Float(f)))) => Some(FRValueNumber(f))
|
||||
| (FRTypeLambda, IevLambda(f)) => Some(FRValueLambda(f))
|
||||
| (FRTypeArray(intendedType), IevArray(elements)) => {
|
||||
let el = elements->E.A2.fmap(matchWithExpressionValue(intendedType))
|
||||
E.A.O.openIfAllSome(el)->E.O2.fmap(r => FRValueArray(r))
|
||||
}
|
||||
| (FRTypeDict(r), EvRecord(record)) =>
|
||||
record
|
||||
->Js.Dict.entries
|
||||
| (FRTypeDict(r), IevRecord(map)) =>
|
||||
map
|
||||
->Belt.Map.String.toArray
|
||||
->E.A2.fmap(((key, item)) => matchWithExpressionValue(r, item)->E.O2.fmap(o => (key, o)))
|
||||
->E.A.O.openIfAllSome
|
||||
->E.O2.fmap(r => FRValueDict(Js.Dict.fromArray(r)))
|
||||
| (FRTypeRecord(recordParams), EvRecord(record)) => {
|
||||
| (FRTypeRecord(recordParams), IevRecord(map)) => {
|
||||
let getAndMatch = (name, input) =>
|
||||
E.Dict.get(record, name)->E.O.bind(matchWithExpressionValue(input))
|
||||
Belt.Map.String.get(map, name)->E.O.bind(matchWithExpressionValue(input))
|
||||
//All names in the type must be present. If any are missing, the corresponding
|
||||
//value will be None, and this function would return None.
|
||||
let namesAndValues: array<option<(Js.Dict.key, frValue)>> =
|
||||
|
@ -127,27 +127,29 @@ module FRType = {
|
|||
|
||||
let rec matchReverse = (e: frValue): expressionValue =>
|
||||
switch e {
|
||||
| FRValueNumber(f) => EvNumber(f)
|
||||
| FRValueDistOrNumber(FRValueNumber(n)) => EvNumber(n)
|
||||
| FRValueDistOrNumber(FRValueDist(n)) => EvDistribution(n)
|
||||
| FRValueDist(dist) => EvDistribution(dist)
|
||||
| FRValueArray(elements) => EvArray(elements->E.A2.fmap(matchReverse))
|
||||
| FRValueNumber(f) => IevNumber(f)
|
||||
| FRValueDistOrNumber(FRValueNumber(n)) => IevNumber(n)
|
||||
| FRValueDistOrNumber(FRValueDist(n)) => IevDistribution(n)
|
||||
| FRValueDist(dist) => IevDistribution(dist)
|
||||
| FRValueArray(elements) => IevArray(elements->E.A2.fmap(matchReverse))
|
||||
| FRValueRecord(frValueRecord) => {
|
||||
let record =
|
||||
frValueRecord->E.A2.fmap(((name, value)) => (name, matchReverse(value)))->E.Dict.fromArray
|
||||
EvRecord(record)
|
||||
let map =
|
||||
frValueRecord
|
||||
->E.A2.fmap(((name, value)) => (name, matchReverse(value)))
|
||||
->Belt.Map.String.fromArray
|
||||
IevRecord(map)
|
||||
}
|
||||
| FRValueDict(frValueRecord) => {
|
||||
let record =
|
||||
let map =
|
||||
frValueRecord
|
||||
->Js.Dict.entries
|
||||
->E.A2.fmap(((name, value)) => (name, matchReverse(value)))
|
||||
->E.Dict.fromArray
|
||||
EvRecord(record)
|
||||
->Belt.Map.String.fromArray
|
||||
IevRecord(map)
|
||||
}
|
||||
| FRValueLambda(l) => EvLambda(l)
|
||||
| FRValueString(string) => EvString(string)
|
||||
| FRValueVariant(string) => EvString(string)
|
||||
| FRValueLambda(l) => IevLambda(l)
|
||||
| FRValueString(string) => IevString(string)
|
||||
| FRValueVariant(string) => IevString(string)
|
||||
| FRValueAny(f) => matchReverse(f)
|
||||
}
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ let impossibleError = "Wrong inputs / Logically impossible"
|
|||
|
||||
module Wrappers = {
|
||||
let symbolic = r => DistributionTypes.Symbolic(r)
|
||||
let evDistribution = r => ReducerInterface_ExpressionValue.EvDistribution(r)
|
||||
let evNumber = r => ReducerInterface_ExpressionValue.EvNumber(r)
|
||||
let evArray = r => ReducerInterface_ExpressionValue.EvArray(r)
|
||||
let evRecord = r => ReducerInterface_ExpressionValue.EvRecord(r)
|
||||
let evString = r => ReducerInterface_ExpressionValue.EvString(r)
|
||||
let evDistribution = r => ReducerInterface_InternalExpressionValue.IevDistribution(r)
|
||||
let evNumber = r => ReducerInterface_InternalExpressionValue.IevNumber(r)
|
||||
let evArray = r => ReducerInterface_InternalExpressionValue.IevArray(r)
|
||||
let evRecord = r => ReducerInterface_InternalExpressionValue.IevRecord(r)
|
||||
let evString = r => ReducerInterface_InternalExpressionValue.IevString(r)
|
||||
let symbolicEvDistribution = r => r->DistributionTypes.Symbolic->evDistribution
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ module Declaration = {
|
|||
inputs
|
||||
->E.A2.fmap(getMinMax)
|
||||
->E.A.R.firstErrorOrOpen
|
||||
->E.R2.fmap(args => ReducerInterface_ExpressionValue.EvDeclaration(
|
||||
->E.R2.fmap(args => ReducerInterface_InternalExpressionValue.IevDeclaration(
|
||||
Declaration.make(lambda, args),
|
||||
))
|
||||
}
|
||||
|
@ -43,7 +43,9 @@ 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 => ReducerInterface_ExpressionValue.EvDistribution(PointSet(makeDist(r))))
|
||||
->E.R2.fmap(r => ReducerInterface_InternalExpressionValue.IevDistribution(
|
||||
PointSet(makeDist(r)),
|
||||
))
|
||||
expressionValue
|
||||
}
|
||||
|
||||
|
@ -369,7 +371,7 @@ to(5,10)
|
|||
E.Dict.concat(d1, d2) |> Js.Dict.map((. r) =>
|
||||
FunctionRegistry_Core.FRType.matchReverse(r)
|
||||
)
|
||||
newDict->Wrappers.evRecord->Ok
|
||||
newDict->Js.Dict.entries->Belt.Map.String.fromArray->Wrappers.evRecord->Ok
|
||||
}
|
||||
| _ => Error(impossibleError)
|
||||
}
|
||||
|
@ -390,6 +392,7 @@ to(5,10)
|
|||
->Prepare.ToTypedArray.dicts
|
||||
->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)
|
||||
),
|
||||
],
|
||||
|
@ -462,7 +465,7 @@ to(5,10)
|
|||
}
|
||||
})
|
||||
->E.A.R.firstErrorOrOpen
|
||||
->E.R2.fmap(Js.Dict.fromArray)
|
||||
->E.R2.fmap(Belt.Map.String.fromArray)
|
||||
->E.R2.fmap(Wrappers.evRecord)
|
||||
inputs->getOrError(0)->E.R.bind(Prepare.ToValueArray.Array.arrayOfArrays)
|
||||
|> E.R2.bind(convertInternalItems)
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
module ErrorValue = Reducer_ErrorValue
|
||||
module Expression = Reducer_Expression
|
||||
module ExpressionValue = ReducerInterface_ExpressionValue
|
||||
module ExternalExpressionValue = ReducerInterface_ExpressionValue
|
||||
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||
module Lambda = Reducer_Expression_Lambda
|
||||
|
||||
type environment = ReducerInterface_ExpressionValue.environment
|
||||
type environment = ReducerInterface_InternalExpressionValue.environment
|
||||
type errorValue = Reducer_ErrorValue.errorValue
|
||||
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
||||
type expressionValue = ExternalExpressionValue.expressionValue
|
||||
type externalBindings = ReducerInterface_ExpressionValue.externalBindings
|
||||
type lambdaValue = ExpressionValue.lambdaValue
|
||||
type lambdaValue = ExternalExpressionValue.lambdaValue
|
||||
|
||||
let evaluate = Expression.evaluate
|
||||
let evaluateUsingOptions = Expression.evaluateUsingOptions
|
||||
|
@ -15,13 +16,20 @@ let evaluatePartialUsingExternalBindings = Expression.evaluatePartialUsingExtern
|
|||
let parse = Expression.parse
|
||||
|
||||
let foreignFunctionInterface = (
|
||||
lambdaValue: lambdaValue,
|
||||
lambdaValue: ExternalExpressionValue.lambdaValue,
|
||||
argArray: array<expressionValue>,
|
||||
environment: ExpressionValue.environment,
|
||||
environment: ExternalExpressionValue.environment,
|
||||
) => {
|
||||
Lambda.foreignFunctionInterface(lambdaValue, argArray, environment, Expression.reduceExpression)
|
||||
let internallambdaValue = InternalExpressionValue.lambdaValueToInternal(lambdaValue)
|
||||
let internalArgArray = argArray->Js.Array2.map(InternalExpressionValue.toInternal)
|
||||
Lambda.foreignFunctionInterface(
|
||||
internallambdaValue,
|
||||
internalArgArray,
|
||||
environment,
|
||||
Expression.reduceExpression,
|
||||
)->Belt.Result.map(InternalExpressionValue.toExternal)
|
||||
}
|
||||
|
||||
let defaultEnvironment = ExpressionValue.defaultEnvironment
|
||||
let defaultEnvironment = ExternalExpressionValue.defaultEnvironment
|
||||
|
||||
let defaultExternalBindings = ReducerInterface_StdLib.externalStdLib
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
include Reducer_Category_Module // Bindings inherit from Module
|
||||
|
||||
open ReducerInterface_ExpressionValue
|
||||
|
||||
let emptyBindings = emptyModule
|
||||
|
||||
let toExpressionValue = (container: t): expressionValue => EvRecord(toRecord(container))
|
||||
let fromExpressionValue = (aValue: expressionValue): t =>
|
||||
switch aValue {
|
||||
| EvRecord(r) => fromRecord(r)
|
||||
| _ => emptyBindings
|
||||
}
|
|
@ -1,33 +1,112 @@
|
|||
module ExpressionT = Reducer_Expression_T
|
||||
open ReducerInterface_ExpressionValue
|
||||
open ReducerInterface_InternalExpressionValue
|
||||
let expressionValueToString = toString
|
||||
|
||||
type t = ExpressionT.bindings
|
||||
type t = ReducerInterface_InternalExpressionValue.nameSpace
|
||||
|
||||
let typeAliasesKey = "_typeAliases_"
|
||||
let typeReferencesKey = "_typeReferences_"
|
||||
|
||||
let emptyModule: t = Belt.Map.String.empty
|
||||
let getType = (nameSpace: t, id: string) => {
|
||||
let NameSpace(container) = nameSpace
|
||||
Belt.Map.String.get(container, typeAliasesKey)->Belt.Option.flatMap(aliases =>
|
||||
switch aliases {
|
||||
| IevRecord(r) => Belt.Map.String.get(r, id)
|
||||
| _ => None
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
let cloneRecord = (r: record): record => r->Js.Dict.entries->Js.Dict.fromArray
|
||||
let fromRecord = (r: record): t => Js.Dict.entries(r)->Belt.Map.String.fromArray
|
||||
let toRecord = (container: t): record => Belt.Map.String.toArray(container)->Js.Dict.fromArray
|
||||
let getTypeOf = (nameSpace: t, id: string) => {
|
||||
let NameSpace(container) = nameSpace
|
||||
Belt.Map.String.get(container, typeReferencesKey)->Belt.Option.flatMap(defs =>
|
||||
switch defs {
|
||||
| IevRecord(r) => Belt.Map.String.get(r, id)
|
||||
| _ => None
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
let toExpressionValue = (container: t): expressionValue => EvModule(toRecord(container))
|
||||
let getWithDefault = (nameSpace: t, id: string, default) => {
|
||||
let NameSpace(container) = nameSpace
|
||||
Belt.Map.String.getWithDefault(container, id, default)
|
||||
}
|
||||
|
||||
let get = (nameSpace: t, id: string) => {
|
||||
let NameSpace(container) = nameSpace
|
||||
Belt.Map.String.get(container, id)
|
||||
}
|
||||
|
||||
let emptyMap: map = Belt.Map.String.empty
|
||||
|
||||
let setTypeAlias = (nameSpace: t, id: string, value): t => {
|
||||
let NameSpace(container) = nameSpace
|
||||
let rValue = Belt.Map.String.getWithDefault(container, typeAliasesKey, IevRecord(emptyMap))
|
||||
let r = switch rValue {
|
||||
| IevRecord(r) => r
|
||||
| _ => emptyMap
|
||||
}
|
||||
let r2 = Belt.Map.String.set(r, id, value)->IevRecord
|
||||
Belt.Map.String.set(container, typeAliasesKey, r2)->NameSpace
|
||||
}
|
||||
|
||||
let setTypeOf = (nameSpace: t, id: string, value): t => {
|
||||
let NameSpace(container) = nameSpace
|
||||
let rValue = Belt.Map.String.getWithDefault(container, typeReferencesKey, IevRecord(emptyMap))
|
||||
let r = switch rValue {
|
||||
| IevRecord(r) => r
|
||||
| _ => emptyMap
|
||||
}
|
||||
let r2 = Belt.Map.String.set(r, id, value)->IevRecord
|
||||
Belt.Map.String.set(container, typeReferencesKey, r2)->NameSpace
|
||||
}
|
||||
|
||||
let set = (nameSpace: t, id: string, value): t => {
|
||||
let NameSpace(container) = nameSpace
|
||||
Belt.Map.String.set(container, id, value)->NameSpace
|
||||
}
|
||||
|
||||
let emptyModule: t = NameSpace(Belt.Map.String.empty)
|
||||
|
||||
let fromTypeScriptBindings = ReducerInterface_InternalExpressionValue.nameSpaceFromTypeScriptBindings
|
||||
let toTypeScriptBindings = ReducerInterface_InternalExpressionValue.nameSpaceToTypeScriptBindings
|
||||
|
||||
let toExpressionValue = (nameSpace: t): expressionValue => IevModule(nameSpace)
|
||||
let fromExpressionValue = (aValue: expressionValue): t =>
|
||||
switch aValue {
|
||||
| EvModule(r) => fromRecord(r)
|
||||
| IevModule(nameSpace) => nameSpace
|
||||
| _ => emptyModule
|
||||
}
|
||||
|
||||
let toString = (container: t): string => container->toRecord->EvRecord->expressionValueToString
|
||||
let fromArray = a => Belt.Map.String.fromArray(a)->NameSpace
|
||||
|
||||
let merge = (nameSpace: t, other: t): t => {
|
||||
let NameSpace(container) = nameSpace
|
||||
let NameSpace(otherContainer) = other
|
||||
otherContainer
|
||||
->Belt.Map.String.reduce(container, (container, key, value) =>
|
||||
Belt.Map.String.set(container, key, value)
|
||||
)
|
||||
->NameSpace
|
||||
}
|
||||
|
||||
let removeOther = (nameSpace: t, other: t): t => {
|
||||
let NameSpace(container) = nameSpace
|
||||
let NameSpace(otherContainer) = other
|
||||
let keys = Belt.Map.String.keysToArray(otherContainer)
|
||||
Belt.Map.String.keep(container, (key, _value) => {
|
||||
let removeThis = Js.Array2.includes(keys, key)
|
||||
!removeThis
|
||||
})->NameSpace
|
||||
}
|
||||
|
||||
// -- Module definition
|
||||
let define = (container: t, identifier: string, ev: expressionValue): t =>
|
||||
Belt.Map.String.set(container, identifier, ev) // TODO build lambda for polymorphic functions here
|
||||
let define = (nameSpace: t, identifier: string, ev: expressionValue): t => {
|
||||
let NameSpace(container) = nameSpace
|
||||
Belt.Map.String.set(container, identifier, ev)->NameSpace // TODO build lambda for polymorphic functions here
|
||||
}
|
||||
let defineNumber = (nameSpace: t, identifier: string, value: float): t =>
|
||||
nameSpace->define(identifier, IevNumber(value))
|
||||
|
||||
let defineNumber = (container: t, identifier: string, value: float): t =>
|
||||
container->define(identifier, EvNumber(value))
|
||||
|
||||
let defineModule = (container: t, identifier: string, value: t): t =>
|
||||
container->define(identifier, toExpressionValue(value))
|
||||
let defineModule = (nameSpace: t, identifier: string, value: t): t =>
|
||||
nameSpace->define(identifier, toExpressionValue(value))
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
module ExpressionValue = ReducerInterface_InternalExpressionValue
|
||||
module ExpressionT = Reducer_Expression_T
|
||||
open ExpressionValue
|
||||
|
||||
let isOfResolvedType = (aType, aValue) => {
|
||||
let caseTypeIdentifier = (aTypeIdentifier0, aValue) => {
|
||||
let valueType = aValue->valueToValueType->valueTypeToString->Js.String2.toLowerCase
|
||||
let aTypeIdentifier = aTypeIdentifier0->Js.String2.toLowerCase
|
||||
aTypeIdentifier === valueType
|
||||
}
|
||||
|
||||
switch aType {
|
||||
| IevTypeIdentifier(aTypeIdentifier) => caseTypeIdentifier(aTypeIdentifier, aValue)
|
||||
| _ => false
|
||||
}
|
||||
}
|
||||
|
||||
// let compileTypeExpression = (typeExpression: string, bindings: ExpressionT.bindings, reducerFn: ExpressionT.reducerFn) => {
|
||||
// statement = `type compiled=${typeExpression}`
|
||||
|
||||
// }
|
|
@ -1,10 +1,11 @@
|
|||
module Bindings = Reducer_Expression_Bindings
|
||||
module BindingsReplacer = Reducer_Expression_BindingsReplacer
|
||||
module ExpressionT = Reducer_Expression_T
|
||||
module ExternalLibrary = ReducerInterface.ExternalLibrary
|
||||
module Lambda = Reducer_Expression_Lambda
|
||||
module MathJs = Reducer_MathJs
|
||||
module Module = Reducer_Category_Module
|
||||
module Result = Belt.Result
|
||||
open ReducerInterface.ExpressionValue
|
||||
open ReducerInterface_InternalExpressionValue
|
||||
open Reducer_ErrorValue
|
||||
|
||||
/*
|
||||
|
@ -31,12 +32,12 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
|
|||
let constructRecord = arrayOfPairs => {
|
||||
Belt.Array.map(arrayOfPairs, pairValue =>
|
||||
switch pairValue {
|
||||
| EvArray([EvString(key), valueValue]) => (key, valueValue)
|
||||
| _ => ("wrong key type", pairValue->toStringWithType->EvString)
|
||||
| IevArray([IevString(key), valueValue]) => (key, valueValue)
|
||||
| _ => ("wrong key type", pairValue->toStringWithType->IevString)
|
||||
}
|
||||
)
|
||||
->Js.Dict.fromArray
|
||||
->EvRecord
|
||||
->Belt.Map.String.fromArray
|
||||
->IevRecord
|
||||
->Ok
|
||||
}
|
||||
|
||||
|
@ -46,8 +47,14 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
|
|||
| None => REArrayIndexNotFound("Array index not found", Belt.Int.fromFloat(fIndex))->Error
|
||||
}
|
||||
|
||||
let recordAtIndex = (dict: Js.Dict.t<expressionValue>, sIndex) =>
|
||||
switch Js.Dict.get(dict, sIndex) {
|
||||
let moduleAtIndex = (nameSpace: nameSpace, sIndex) =>
|
||||
switch Module.get(nameSpace, sIndex) {
|
||||
| Some(value) => value->Ok
|
||||
| None => RERecordPropertyNotFound("Module property not found", sIndex)->Error
|
||||
}
|
||||
|
||||
let recordAtIndex = (dict: Belt.Map.String.t<expressionValue>, sIndex) =>
|
||||
switch Belt.Map.String.get(dict, sIndex) {
|
||||
| Some(value) => value->Ok
|
||||
| None => RERecordPropertyNotFound("Record property not found", sIndex)->Error
|
||||
}
|
||||
|
@ -55,11 +62,11 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
|
|||
let doAddArray = (originalA, b) => {
|
||||
let a = originalA->Js.Array2.copy
|
||||
let _ = Js.Array2.pushMany(a, b)
|
||||
a->EvArray->Ok
|
||||
a->IevArray->Ok
|
||||
}
|
||||
let doAddString = (a, b) => {
|
||||
let answer = Js.String2.concat(a, b)
|
||||
answer->EvString->Ok
|
||||
answer->IevString->Ok
|
||||
}
|
||||
|
||||
let inspect = (value: expressionValue) => {
|
||||
|
@ -72,53 +79,17 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
|
|||
value->Ok
|
||||
}
|
||||
|
||||
let doSetBindings = (
|
||||
externalBindings: externalBindings,
|
||||
symbol: string,
|
||||
value: expressionValue,
|
||||
) => {
|
||||
Bindings.fromExternalBindings(externalBindings)
|
||||
->Belt.Map.String.set(symbol, value)
|
||||
->Bindings.toExternalBindings
|
||||
->EvRecord
|
||||
->Ok
|
||||
let doSetBindings = (bindings: nameSpace, symbol: string, value: expressionValue) => {
|
||||
Module.set(bindings, symbol, value)->IevModule->Ok
|
||||
}
|
||||
|
||||
let doSetBindingsInNamespace = (
|
||||
externalBindings: externalBindings,
|
||||
symbol: string,
|
||||
value: expressionValue,
|
||||
namespace: string,
|
||||
) => {
|
||||
let bindings = Bindings.fromExternalBindings(externalBindings)
|
||||
let evAliases = bindings->Belt.Map.String.getWithDefault(namespace, EvRecord(Js.Dict.empty()))
|
||||
let newEvAliases = switch evAliases {
|
||||
| EvRecord(dict) => {
|
||||
Js.Dict.set(dict, symbol, value)
|
||||
dict->EvRecord
|
||||
}
|
||||
| _ => Js.Dict.empty()->EvRecord
|
||||
}
|
||||
bindings
|
||||
->Belt.Map.String.set(namespace, newEvAliases)
|
||||
->Bindings.toExternalBindings
|
||||
->EvRecord
|
||||
->Ok
|
||||
}
|
||||
let doSetTypeAliasBindings = (bindings: nameSpace, symbol: string, value: expressionValue) =>
|
||||
Module.setTypeAlias(bindings, symbol, value)->IevModule->Ok
|
||||
|
||||
let doSetTypeAliasBindings = (
|
||||
externalBindings: externalBindings,
|
||||
symbol: string,
|
||||
value: expressionValue,
|
||||
) => doSetBindingsInNamespace(externalBindings, symbol, value, Bindings.typeAliasesKey)
|
||||
let doSetTypeOfBindings = (bindings: nameSpace, symbol: string, value: expressionValue) =>
|
||||
Module.setTypeOf(bindings, symbol, value)->IevModule->Ok
|
||||
|
||||
let doSetTypeOfBindings = (
|
||||
externalBindings: externalBindings,
|
||||
symbol: string,
|
||||
value: expressionValue,
|
||||
) => doSetBindingsInNamespace(externalBindings, symbol, value, Bindings.typeReferencesKey)
|
||||
|
||||
let doExportBindings = (externalBindings: externalBindings) => EvRecord(externalBindings)->Ok
|
||||
let doExportBindings = (bindings: nameSpace) => bindings->Module.toExpressionValue->Ok
|
||||
|
||||
let doKeepArray = (aValueArray, aLambdaValue) => {
|
||||
let rMappedList = aValueArray->Belt.Array.reduceReverse(Ok(list{}), (rAcc, elem) =>
|
||||
|
@ -126,13 +97,13 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
|
|||
let rNewElem = Lambda.doLambdaCall(aLambdaValue, list{elem}, environment, reducer)
|
||||
rNewElem->Result.map(newElem =>
|
||||
switch newElem {
|
||||
| EvBool(true) => list{elem, ...acc}
|
||||
| IevBool(true) => list{elem, ...acc}
|
||||
| _ => acc
|
||||
}
|
||||
)
|
||||
})
|
||||
)
|
||||
rMappedList->Result.map(mappedList => mappedList->Belt.List.toArray->EvArray)
|
||||
rMappedList->Result.map(mappedList => mappedList->Belt.List.toArray->IevArray)
|
||||
}
|
||||
|
||||
let doMapArray = (aValueArray, aLambdaValue) => {
|
||||
|
@ -142,35 +113,36 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
|
|||
rNewElem->Result.map(newElem => list{newElem, ...acc})
|
||||
})
|
||||
)
|
||||
rMappedList->Result.map(mappedList => mappedList->Belt.List.toArray->EvArray)
|
||||
rMappedList->Result.map(mappedList => mappedList->Belt.List.toArray->IevArray)
|
||||
}
|
||||
|
||||
module SampleMap = {
|
||||
type t = SampleSetDist.t
|
||||
let doLambdaCall = (aLambdaValue, list) =>
|
||||
switch Lambda.doLambdaCall(aLambdaValue, list, environment, reducer) {
|
||||
| Ok(EvNumber(f)) => Ok(f)
|
||||
| Ok(IevNumber(f)) => Ok(f)
|
||||
| _ => Error(Operation.SampleMapNeedsNtoNFunction)
|
||||
}
|
||||
|
||||
let toType = r =>
|
||||
switch r {
|
||||
| Ok(r) => Ok(EvDistribution(SampleSet(r)))
|
||||
| Ok(r) => Ok(IevDistribution(SampleSet(r)))
|
||||
| Error(r) => Error(REDistributionError(SampleSetError(r)))
|
||||
}
|
||||
|
||||
let map1 = (sampleSetDist: t, aLambdaValue) => {
|
||||
let fn = r => doLambdaCall(aLambdaValue, list{EvNumber(r)})
|
||||
let fn = r => doLambdaCall(aLambdaValue, list{IevNumber(r)})
|
||||
toType(SampleSetDist.samplesMap(~fn, sampleSetDist))
|
||||
}
|
||||
|
||||
let map2 = (t1: t, t2: t, aLambdaValue) => {
|
||||
let fn = (a, b) => doLambdaCall(aLambdaValue, list{EvNumber(a), EvNumber(b)})
|
||||
let fn = (a, b) => doLambdaCall(aLambdaValue, list{IevNumber(a), IevNumber(b)})
|
||||
SampleSetDist.map2(~fn, ~t1, ~t2)->toType
|
||||
}
|
||||
|
||||
let map3 = (t1: t, t2: t, t3: t, aLambdaValue) => {
|
||||
let fn = (a, b, c) => doLambdaCall(aLambdaValue, list{EvNumber(a), EvNumber(b), EvNumber(c)})
|
||||
let fn = (a, b, c) =>
|
||||
doLambdaCall(aLambdaValue, list{IevNumber(a), IevNumber(b), IevNumber(c)})
|
||||
SampleSetDist.map3(~fn, ~t1, ~t2, ~t3)->toType
|
||||
}
|
||||
}
|
||||
|
@ -192,132 +164,128 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
|
|||
}
|
||||
|
||||
let typeModifier_memberOf = (aType, anArray) => {
|
||||
let newRecord = Js.Dict.fromArray([
|
||||
("typeTag", EvString("typeIdentifier")),
|
||||
let newRecord = Belt.Map.String.fromArray([
|
||||
("typeTag", IevString("typeIdentifier")),
|
||||
("typeIdentifier", aType),
|
||||
])
|
||||
newRecord->Js.Dict.set("memberOf", anArray)
|
||||
newRecord->EvRecord->Ok
|
||||
newRecord->Belt.Map.String.set("memberOf", anArray)->IevRecord->Ok
|
||||
}
|
||||
let typeModifier_memberOf_update = (aRecord, anArray) => {
|
||||
let newRecord = aRecord->Js.Dict.entries->Js.Dict.fromArray
|
||||
newRecord->Js.Dict.set("memberOf", anArray)
|
||||
newRecord->EvRecord->Ok
|
||||
aRecord->Belt.Map.String.set("memberOf", anArray)->IevRecord->Ok
|
||||
}
|
||||
|
||||
let typeModifier_min = (aType, value) => {
|
||||
let newRecord = Js.Dict.fromArray([
|
||||
("typeTag", EvString("typeIdentifier")),
|
||||
let newRecord = Belt.Map.String.fromArray([
|
||||
("typeTag", IevString("typeIdentifier")),
|
||||
("typeIdentifier", aType),
|
||||
])
|
||||
newRecord->Js.Dict.set("min", value)
|
||||
newRecord->EvRecord->Ok
|
||||
newRecord->Belt.Map.String.set("min", value)->IevRecord->Ok
|
||||
}
|
||||
let typeModifier_min_update = (aRecord, value) => {
|
||||
let newRecord = aRecord->Js.Dict.entries->Js.Dict.fromArray
|
||||
newRecord->Js.Dict.set("min", value)
|
||||
newRecord->EvRecord->Ok
|
||||
aRecord->Belt.Map.String.set("min", value)->IevRecord->Ok
|
||||
}
|
||||
|
||||
let typeModifier_max = (aType, value) => {
|
||||
let newRecord = Js.Dict.fromArray([
|
||||
("typeTag", EvString("typeIdentifier")),
|
||||
let newRecord = Belt.Map.String.fromArray([
|
||||
("typeTag", IevString("typeIdentifier")),
|
||||
("typeIdentifier", aType),
|
||||
])
|
||||
newRecord->Js.Dict.set("max", value)
|
||||
newRecord->EvRecord->Ok
|
||||
}
|
||||
let typeModifier_max_update = (aRecord, value) => {
|
||||
let newRecord = aRecord->Js.Dict.entries->Js.Dict.fromArray
|
||||
newRecord->Js.Dict.set("max", value)
|
||||
newRecord->EvRecord->Ok
|
||||
newRecord->Belt.Map.String.set("max", value)->IevRecord->Ok
|
||||
}
|
||||
let typeModifier_max_update = (aRecord, value) =>
|
||||
aRecord->Belt.Map.String.set("max", value)->IevRecord->Ok
|
||||
|
||||
let typeModifier_opaque_update = aRecord => {
|
||||
let newRecord = aRecord->Js.Dict.entries->Js.Dict.fromArray
|
||||
newRecord->Js.Dict.set("opaque", EvBool(true))
|
||||
newRecord->EvRecord->Ok
|
||||
}
|
||||
let typeModifier_opaque_update = aRecord =>
|
||||
aRecord->Belt.Map.String.set("opaque", IevBool(true))->IevRecord->Ok
|
||||
|
||||
let typeOr = evArray => {
|
||||
let newRecord = Js.Dict.fromArray([("typeTag", EvString("typeOr")), ("typeOr", evArray)])
|
||||
newRecord->EvRecord->Ok
|
||||
let newRecord = Belt.Map.String.fromArray([
|
||||
("typeTag", IevString("typeOr")),
|
||||
("typeOr", evArray),
|
||||
])
|
||||
newRecord->IevRecord->Ok
|
||||
}
|
||||
let typeFunction = anArray => {
|
||||
let output = Belt.Array.getUnsafe(anArray, Js.Array2.length(anArray) - 1)
|
||||
let inputs = Js.Array2.slice(anArray, ~start=0, ~end_=-1)
|
||||
let newRecord = Js.Dict.fromArray([
|
||||
("typeTag", EvString("typeFunction")),
|
||||
("inputs", EvArray(inputs)),
|
||||
let newRecord = Belt.Map.String.fromArray([
|
||||
("typeTag", IevString("typeFunction")),
|
||||
("inputs", IevArray(inputs)),
|
||||
("output", output),
|
||||
])
|
||||
newRecord->EvRecord->Ok
|
||||
newRecord->IevRecord->Ok
|
||||
}
|
||||
|
||||
switch call {
|
||||
| ("$_atIndex_$", [EvArray(aValueArray), EvNumber(fIndex)]) => arrayAtIndex(aValueArray, fIndex)
|
||||
| ("$_atIndex_$", [EvModule(dict), EvString(sIndex)]) => recordAtIndex(dict, sIndex)
|
||||
| ("$_atIndex_$", [EvRecord(dict), EvString(sIndex)]) => recordAtIndex(dict, sIndex)
|
||||
| ("$_constructArray_$", [EvArray(aValueArray)]) => EvArray(aValueArray)->Ok
|
||||
| ("$_constructRecord_$", [EvArray(arrayOfPairs)]) => constructRecord(arrayOfPairs)
|
||||
| ("$_exportBindings_$", [EvRecord(externalBindings)]) => doExportBindings(externalBindings)
|
||||
| ("$_setBindings_$", [EvRecord(externalBindings), EvSymbol(symbol), value]) =>
|
||||
doSetBindings(externalBindings, symbol, value)
|
||||
| ("$_setTypeAliasBindings_$", [EvRecord(externalBindings), EvTypeIdentifier(symbol), value]) =>
|
||||
doSetTypeAliasBindings(externalBindings, symbol, value)
|
||||
| ("$_setTypeOfBindings_$", [EvRecord(externalBindings), EvSymbol(symbol), value]) =>
|
||||
doSetTypeOfBindings(externalBindings, symbol, value)
|
||||
| ("$_typeModifier_memberOf_$", [EvTypeIdentifier(typeIdentifier), EvArray(arr)]) =>
|
||||
typeModifier_memberOf(EvTypeIdentifier(typeIdentifier), EvArray(arr))
|
||||
| ("$_typeModifier_memberOf_$", [EvRecord(typeRecord), EvArray(arr)]) =>
|
||||
typeModifier_memberOf_update(typeRecord, EvArray(arr))
|
||||
| ("$_typeModifier_min_$", [EvTypeIdentifier(typeIdentifier), value]) =>
|
||||
typeModifier_min(EvTypeIdentifier(typeIdentifier), value)
|
||||
| ("$_typeModifier_min_$", [EvRecord(typeRecord), value]) =>
|
||||
| ("$_atIndex_$", [IevArray(aValueArray), IevNumber(fIndex)]) => arrayAtIndex(aValueArray, fIndex)
|
||||
| ("$_atIndex_$", [IevModule(dict), IevString(sIndex)]) => moduleAtIndex(dict, sIndex)
|
||||
| ("$_atIndex_$", [IevRecord(dict), IevString(sIndex)]) => recordAtIndex(dict, sIndex)
|
||||
| ("$_constructArray_$", [IevArray(aValueArray)]) => IevArray(aValueArray)->Ok
|
||||
| ("$_constructRecord_$", [IevArray(arrayOfPairs)]) => constructRecord(arrayOfPairs)
|
||||
| ("$_exportBindings_$", [IevModule(nameSpace)]) => doExportBindings(nameSpace)
|
||||
| ("$_setBindings_$", [IevModule(nameSpace), IevSymbol(symbol), value]) =>
|
||||
doSetBindings(nameSpace, symbol, value)
|
||||
| ("$_setTypeAliasBindings_$", [IevModule(nameSpace), IevTypeIdentifier(symbol), value]) =>
|
||||
doSetTypeAliasBindings(nameSpace, symbol, value)
|
||||
| ("$_setTypeOfBindings_$", [IevModule(nameSpace), IevSymbol(symbol), value]) =>
|
||||
doSetTypeOfBindings(nameSpace, symbol, value)
|
||||
| ("$_typeModifier_memberOf_$", [IevTypeIdentifier(typeIdentifier), IevArray(arr)]) =>
|
||||
typeModifier_memberOf(IevTypeIdentifier(typeIdentifier), IevArray(arr))
|
||||
| ("$_typeModifier_memberOf_$", [IevRecord(typeRecord), IevArray(arr)]) =>
|
||||
typeModifier_memberOf_update(typeRecord, IevArray(arr))
|
||||
| ("$_typeModifier_min_$", [IevTypeIdentifier(typeIdentifier), value]) =>
|
||||
typeModifier_min(IevTypeIdentifier(typeIdentifier), value)
|
||||
| ("$_typeModifier_min_$", [IevRecord(typeRecord), value]) =>
|
||||
typeModifier_min_update(typeRecord, value)
|
||||
| ("$_typeModifier_max_$", [EvTypeIdentifier(typeIdentifier), value]) =>
|
||||
typeModifier_max(EvTypeIdentifier(typeIdentifier), value)
|
||||
| ("$_typeModifier_max_$", [EvRecord(typeRecord), value]) =>
|
||||
| ("$_typeModifier_max_$", [IevTypeIdentifier(typeIdentifier), value]) =>
|
||||
typeModifier_max(IevTypeIdentifier(typeIdentifier), value)
|
||||
| ("$_typeModifier_max_$", [IevRecord(typeRecord), value]) =>
|
||||
typeModifier_max_update(typeRecord, value)
|
||||
| ("$_typeModifier_opaque_$", [EvRecord(typeRecord)]) => typeModifier_opaque_update(typeRecord)
|
||||
| ("$_typeOr_$", [EvArray(arr)]) => typeOr(EvArray(arr))
|
||||
| ("$_typeFunction_$", [EvArray(arr)]) => typeFunction(arr)
|
||||
| ("concat", [EvArray(aValueArray), EvArray(bValueArray)]) => doAddArray(aValueArray, bValueArray)
|
||||
| ("concat", [EvString(aValueString), EvString(bValueString)]) =>
|
||||
| ("$_typeModifier_opaque_$", [IevRecord(typeRecord)]) => typeModifier_opaque_update(typeRecord)
|
||||
| ("$_typeOr_$", [IevArray(arr)]) => typeOr(IevArray(arr))
|
||||
| ("$_typeFunction_$", [IevArray(arr)]) => typeFunction(arr)
|
||||
| ("concat", [IevArray(aValueArray), IevArray(bValueArray)]) =>
|
||||
doAddArray(aValueArray, bValueArray)
|
||||
| ("concat", [IevString(aValueString), IevString(bValueString)]) =>
|
||||
doAddString(aValueString, bValueString)
|
||||
| ("inspect", [value, EvString(label)]) => inspectLabel(value, label)
|
||||
| ("inspect", [value, IevString(label)]) => inspectLabel(value, label)
|
||||
| ("inspect", [value]) => inspect(value)
|
||||
| ("filter", [EvArray(aValueArray), EvLambda(aLambdaValue)]) =>
|
||||
| ("filter", [IevArray(aValueArray), IevLambda(aLambdaValue)]) =>
|
||||
doKeepArray(aValueArray, aLambdaValue)
|
||||
| ("map", [EvArray(aValueArray), EvLambda(aLambdaValue)]) => doMapArray(aValueArray, aLambdaValue)
|
||||
| ("mapSamples", [EvDistribution(SampleSet(dist)), EvLambda(aLambdaValue)]) =>
|
||||
| ("map", [IevArray(aValueArray), IevLambda(aLambdaValue)]) =>
|
||||
doMapArray(aValueArray, aLambdaValue)
|
||||
| ("mapSamples", [IevDistribution(SampleSet(dist)), IevLambda(aLambdaValue)]) =>
|
||||
SampleMap.map1(dist, aLambdaValue)
|
||||
| (
|
||||
"mapSamples2",
|
||||
[EvDistribution(SampleSet(dist1)), EvDistribution(SampleSet(dist2)), EvLambda(aLambdaValue)],
|
||||
[
|
||||
IevDistribution(SampleSet(dist1)),
|
||||
IevDistribution(SampleSet(dist2)),
|
||||
IevLambda(aLambdaValue),
|
||||
],
|
||||
) =>
|
||||
SampleMap.map2(dist1, dist2, aLambdaValue)
|
||||
| (
|
||||
"mapSamples3",
|
||||
[
|
||||
EvDistribution(SampleSet(dist1)),
|
||||
EvDistribution(SampleSet(dist2)),
|
||||
EvDistribution(SampleSet(dist3)),
|
||||
EvLambda(aLambdaValue),
|
||||
IevDistribution(SampleSet(dist1)),
|
||||
IevDistribution(SampleSet(dist2)),
|
||||
IevDistribution(SampleSet(dist3)),
|
||||
IevLambda(aLambdaValue),
|
||||
],
|
||||
) =>
|
||||
SampleMap.map3(dist1, dist2, dist3, aLambdaValue)
|
||||
| ("reduce", [EvArray(aValueArray), initialValue, EvLambda(aLambdaValue)]) =>
|
||||
| ("reduce", [IevArray(aValueArray), initialValue, IevLambda(aLambdaValue)]) =>
|
||||
doReduceArray(aValueArray, initialValue, aLambdaValue)
|
||||
| ("reduceReverse", [EvArray(aValueArray), initialValue, EvLambda(aLambdaValue)]) =>
|
||||
| ("reduceReverse", [IevArray(aValueArray), initialValue, IevLambda(aLambdaValue)]) =>
|
||||
doReduceReverseArray(aValueArray, initialValue, aLambdaValue)
|
||||
| ("reverse", [EvArray(aValueArray)]) => aValueArray->Belt.Array.reverse->EvArray->Ok
|
||||
| (_, [EvBool(_)])
|
||||
| (_, [EvNumber(_)])
|
||||
| (_, [EvString(_)])
|
||||
| (_, [EvBool(_), EvBool(_)])
|
||||
| (_, [EvNumber(_), EvNumber(_)])
|
||||
| (_, [EvString(_), EvString(_)]) =>
|
||||
| ("reverse", [IevArray(aValueArray)]) => aValueArray->Belt.Array.reverse->IevArray->Ok
|
||||
| (_, [IevBool(_)])
|
||||
| (_, [IevNumber(_)])
|
||||
| (_, [IevString(_)])
|
||||
| (_, [IevBool(_), IevBool(_)])
|
||||
| (_, [IevNumber(_), IevNumber(_)])
|
||||
| (_, [IevString(_), IevString(_)]) =>
|
||||
callMathJs(call)
|
||||
| call =>
|
||||
Error(REFunctionNotFound(call->functionCallToCallSignature->functionCallSignatureToString)) // Report full type signature as error
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
they take expressions as parameters and return a new expression.
|
||||
Macros are used to define language building blocks. They are like Lisp macros.
|
||||
*/
|
||||
module Bindings = Reducer_Expression_Bindings
|
||||
module BindingsReplacer = Reducer_Expression_BindingsReplacer
|
||||
module ErrorValue = Reducer_ErrorValue
|
||||
module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
|
||||
module ExpressionT = Reducer_Expression_T
|
||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
||||
module ExpressionValue = ReducerInterface_InternalExpressionValue
|
||||
module ExpressionWithContext = Reducer_ExpressionWithContext
|
||||
module Module = Reducer_Category_Module
|
||||
module Result = Belt.Result
|
||||
open Reducer_Expression_ExpressionBuilder
|
||||
|
||||
|
@ -27,13 +28,13 @@ let dispatchMacroCall = (
|
|||
let useExpressionToSetBindings = (bindingExpr: expression, environment, statement, newCode) => {
|
||||
let rExternalBindingsValue = reduceExpression(bindingExpr, bindings, environment)
|
||||
|
||||
rExternalBindingsValue->Result.flatMap(externalBindingsValue => {
|
||||
let newBindings = Bindings.fromValue(externalBindingsValue)
|
||||
rExternalBindingsValue->Result.flatMap(nameSpaceValue => {
|
||||
let newBindings = Module.fromExpressionValue(nameSpaceValue)
|
||||
|
||||
let rNewStatement = Bindings.replaceSymbols(newBindings, statement)
|
||||
let rNewStatement = BindingsReplacer.replaceSymbols(newBindings, statement)
|
||||
rNewStatement->Result.map(boundStatement =>
|
||||
ExpressionWithContext.withContext(
|
||||
newCode(newBindings->Bindings.toExternalBindings->eRecord, boundStatement),
|
||||
newCode(newBindings->eModule, boundStatement),
|
||||
newBindings,
|
||||
)
|
||||
)
|
||||
|
@ -51,7 +52,7 @@ let dispatchMacroCall = (
|
|||
let doBindStatement = (bindingExpr: expression, statement: expression, environment) => {
|
||||
let defaultStatement = ErrorValue.REAssignmentExpected->Error
|
||||
switch statement {
|
||||
| ExpressionT.EList(list{ExpressionT.EValue(EvCall(callName)), symbolExpr, statement}) => {
|
||||
| ExpressionT.EList(list{ExpressionT.EValue(IevCall(callName)), symbolExpr, statement}) => {
|
||||
let setBindingsFn = correspondingSetBindingsFn(callName)
|
||||
if setBindingsFn !== "" {
|
||||
useExpressionToSetBindings(bindingExpr, environment, statement, (
|
||||
|
@ -77,7 +78,7 @@ let dispatchMacroCall = (
|
|||
) => boundStatement)
|
||||
|
||||
switch statement {
|
||||
| ExpressionT.EList(list{ExpressionT.EValue(EvCall(callName)), symbolExpr, statement}) => {
|
||||
| ExpressionT.EList(list{ExpressionT.EValue(IevCall(callName)), symbolExpr, statement}) => {
|
||||
let setBindingsFn = correspondingSetBindingsFn(callName)
|
||||
if setBindingsFn !== "" {
|
||||
useExpressionToSetBindings(bindingExpr, environment, statement, (
|
||||
|
@ -123,10 +124,7 @@ let dispatchMacroCall = (
|
|||
bindings: ExpressionT.bindings,
|
||||
parameters: array<string>,
|
||||
lambdaDefinition: ExpressionT.expression,
|
||||
) =>
|
||||
ExpressionWithContext.noContext(
|
||||
eLambda(parameters, bindings->Bindings.toExternalBindings, lambdaDefinition),
|
||||
)->Ok
|
||||
) => ExpressionWithContext.noContext(eLambda(parameters, bindings, lambdaDefinition))->Ok
|
||||
|
||||
let doTernary = (
|
||||
condition: expression,
|
||||
|
@ -139,11 +137,11 @@ let dispatchMacroCall = (
|
|||
let rCondition = reduceExpression(blockCondition, bindings, environment)
|
||||
rCondition->Result.flatMap(conditionValue =>
|
||||
switch conditionValue {
|
||||
| ExpressionValue.EvBool(false) => {
|
||||
| ExpressionValue.IevBool(false) => {
|
||||
let ifFalseBlock = eBlock(list{ifFalse})
|
||||
ExpressionWithContext.withContext(ifFalseBlock, bindings)->Ok
|
||||
}
|
||||
| ExpressionValue.EvBool(true) => {
|
||||
| ExpressionValue.IevBool(true) => {
|
||||
let ifTrueBlock = eBlock(list{ifTrue})
|
||||
ExpressionWithContext.withContext(ifTrueBlock, bindings)->Ok
|
||||
}
|
||||
|
@ -158,32 +156,32 @@ let dispatchMacroCall = (
|
|||
> =>
|
||||
switch aList {
|
||||
| list{
|
||||
ExpressionT.EValue(EvCall("$$_bindStatement_$$")),
|
||||
ExpressionT.EValue(IevCall("$$_bindStatement_$$")),
|
||||
bindingExpr: ExpressionT.expression,
|
||||
statement,
|
||||
} =>
|
||||
doBindStatement(bindingExpr, statement, environment)
|
||||
| list{ExpressionT.EValue(EvCall("$$_bindStatement_$$")), statement} =>
|
||||
| list{ExpressionT.EValue(IevCall("$$_bindStatement_$$")), statement} =>
|
||||
// bindings of the context are used when there is no binding expression
|
||||
doBindStatement(eRecord(Bindings.toExternalBindings(bindings)), statement, environment)
|
||||
doBindStatement(eModule(bindings), statement, environment)
|
||||
| list{
|
||||
ExpressionT.EValue(EvCall("$$_bindExpression_$$")),
|
||||
ExpressionT.EValue(IevCall("$$_bindExpression_$$")),
|
||||
bindingExpr: ExpressionT.expression,
|
||||
expression,
|
||||
} =>
|
||||
doBindExpression(bindingExpr, expression, environment)
|
||||
| list{ExpressionT.EValue(EvCall("$$_bindExpression_$$")), expression} =>
|
||||
| list{ExpressionT.EValue(IevCall("$$_bindExpression_$$")), expression} =>
|
||||
// bindings of the context are used when there is no binding expression
|
||||
doBindExpression(eRecord(Bindings.toExternalBindings(bindings)), expression, environment)
|
||||
| list{ExpressionT.EValue(EvCall("$$_block_$$")), ...exprs} =>
|
||||
doBindExpression(eModule(bindings), expression, environment)
|
||||
| list{ExpressionT.EValue(IevCall("$$_block_$$")), ...exprs} =>
|
||||
doBlock(exprs, bindings, environment)
|
||||
| list{
|
||||
ExpressionT.EValue(EvCall("$$_lambda_$$")),
|
||||
ExpressionT.EValue(EvArrayString(parameters)),
|
||||
ExpressionT.EValue(IevCall("$$_lambda_$$")),
|
||||
ExpressionT.EValue(IevArrayString(parameters)),
|
||||
lambdaDefinition,
|
||||
} =>
|
||||
doLambdaDefinition(bindings, parameters, lambdaDefinition)
|
||||
| list{ExpressionT.EValue(EvCall("$$_ternary_$$")), condition, ifTrue, ifFalse} =>
|
||||
| list{ExpressionT.EValue(IevCall("$$_ternary_$$")), condition, ifTrue, ifFalse} =>
|
||||
doTernary(condition, ifTrue, ifFalse, bindings, environment)
|
||||
| _ => ExpressionWithContext.noContext(ExpressionT.EList(aList))->Ok
|
||||
}
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
module Bindings = Reducer_Expression_Bindings
|
||||
module BindingsReplacer = Reducer_Expression_BindingsReplacer
|
||||
module BuiltIn = Reducer_Dispatch_BuiltIn
|
||||
module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
|
||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
||||
module Extra = Reducer_Extra
|
||||
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||
module Lambda = Reducer_Expression_Lambda
|
||||
module Macro = Reducer_Expression_Macro
|
||||
module MathJs = Reducer_MathJs
|
||||
module Module = Reducer_Category_Module
|
||||
module Result = Belt.Result
|
||||
module T = Reducer_Expression_T
|
||||
|
||||
type environment = ReducerInterface_ExpressionValue.environment
|
||||
type environment = InternalExpressionValue.environment
|
||||
type errorValue = Reducer_ErrorValue.errorValue
|
||||
type expression = T.expression
|
||||
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
||||
type externalBindings = ReducerInterface_ExpressionValue.externalBindings
|
||||
type internalCode = ReducerInterface_ExpressionValue.internalCode
|
||||
type expressionValue = InternalExpressionValue.expressionValue
|
||||
type externalExpressionValue = ReducerInterface_ExpressionValue.expressionValue
|
||||
type tmpExternalBindings = InternalExpressionValue.tmpExternalBindings
|
||||
type t = expression
|
||||
|
||||
/*
|
||||
|
@ -35,7 +36,7 @@ let rec reduceExpression = (expression: t, bindings: T.bindings, environment: en
|
|||
| T.EValue(value) => value->Ok
|
||||
| T.EList(list) =>
|
||||
switch list {
|
||||
| list{EValue(EvCall(fName)), ..._args} =>
|
||||
| list{EValue(IevCall(fName)), ..._args} =>
|
||||
switch Macro.isMacroName(fName) {
|
||||
// A macro expands then reduces itself
|
||||
| true => Macro.doMacroCall(expression, bindings, environment, reduceExpression)
|
||||
|
@ -74,7 +75,7 @@ and reduceValueList = (valueList: list<expressionValue>, environment): result<
|
|||
'e,
|
||||
> =>
|
||||
switch valueList {
|
||||
| list{EvCall(fName), ...args} => {
|
||||
| list{IevCall(fName), ...args} => {
|
||||
let rCheckedArgs = switch fName {
|
||||
| "$_setBindings_$" | "$_setTypeOfBindings_$" | "$_setTypeAliasBindings_$" => args->Ok
|
||||
| _ => args->Lambda.checkIfReduced
|
||||
|
@ -84,14 +85,14 @@ and reduceValueList = (valueList: list<expressionValue>, environment): result<
|
|||
(fName, checkedArgs->Belt.List.toArray)->BuiltIn.dispatch(environment, reduceExpression)
|
||||
)
|
||||
}
|
||||
| list{EvLambda(_)} =>
|
||||
| list{IevLambda(_)} =>
|
||||
// TODO: remove on solving issue#558
|
||||
valueList
|
||||
->Lambda.checkIfReduced
|
||||
->Result.flatMap(reducedValueList =>
|
||||
reducedValueList->Belt.List.toArray->ExpressionValue.EvArray->Ok
|
||||
reducedValueList->Belt.List.toArray->InternalExpressionValue.IevArray->Ok
|
||||
)
|
||||
| list{EvLambda(lamdaCall), ...args} =>
|
||||
| list{IevLambda(lamdaCall), ...args} =>
|
||||
args
|
||||
->Lambda.checkIfReduced
|
||||
->Result.flatMap(checkedArgs =>
|
||||
|
@ -102,7 +103,7 @@ and reduceValueList = (valueList: list<expressionValue>, environment): result<
|
|||
valueList
|
||||
->Lambda.checkIfReduced
|
||||
->Result.flatMap(reducedValueList =>
|
||||
reducedValueList->Belt.List.toArray->ExpressionValue.EvArray->Ok
|
||||
reducedValueList->Belt.List.toArray->InternalExpressionValue.IevArray->Ok
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -115,40 +116,35 @@ let evaluateUsingOptions = (
|
|||
~environment: option<ReducerInterface_ExpressionValue.environment>,
|
||||
~externalBindings: option<ReducerInterface_ExpressionValue.externalBindings>,
|
||||
code: string,
|
||||
): result<expressionValue, errorValue> => {
|
||||
): result<externalExpressionValue, errorValue> => {
|
||||
let anEnvironment = Belt.Option.getWithDefault(
|
||||
environment,
|
||||
ReducerInterface_ExpressionValue.defaultEnvironment,
|
||||
)
|
||||
|
||||
let anExternalBindings = switch externalBindings {
|
||||
| Some(bindings) => {
|
||||
let cloneLib = ReducerInterface_StdLib.externalStdLib->Reducer_Category_Bindings.cloneRecord
|
||||
Js.Dict.entries(bindings)->Js.Array2.reduce((acc, (key, value)) => {
|
||||
acc->Js.Dict.set(key, value)
|
||||
acc
|
||||
}, cloneLib)
|
||||
}
|
||||
| None => ReducerInterface_StdLib.externalStdLib
|
||||
}
|
||||
let mergedBindings: InternalExpressionValue.nameSpace = Module.merge(
|
||||
ReducerInterface_StdLib.internalStdLib,
|
||||
Belt.Option.map(externalBindings, Module.fromTypeScriptBindings)->Belt.Option.getWithDefault(
|
||||
Module.emptyModule,
|
||||
),
|
||||
)
|
||||
|
||||
let bindings = anExternalBindings->Bindings.fromExternalBindings
|
||||
|
||||
parse(code)->Result.flatMap(expr => evalUsingBindingsExpression_(expr, bindings, anEnvironment))
|
||||
parse(code)
|
||||
->Result.flatMap(expr => evalUsingBindingsExpression_(expr, mergedBindings, anEnvironment))
|
||||
->Result.map(ReducerInterface_InternalExpressionValue.toExternal)
|
||||
}
|
||||
|
||||
/*
|
||||
Evaluates Squiggle code and bindings via Reducer and answers the result
|
||||
Ievaluates Squiggle code and bindings via Reducer and answers the result
|
||||
*/
|
||||
let evaluate = (code: string): result<expressionValue, errorValue> => {
|
||||
let evaluate = (code: string): result<externalExpressionValue, errorValue> => {
|
||||
evaluateUsingOptions(~environment=None, ~externalBindings=None, code)
|
||||
}
|
||||
let eval = evaluate
|
||||
let evaluatePartialUsingExternalBindings = (
|
||||
code: string,
|
||||
externalBindings: ReducerInterface_ExpressionValue.externalBindings,
|
||||
environment: ReducerInterface_ExpressionValue.environment,
|
||||
): result<externalBindings, errorValue> => {
|
||||
): result<ReducerInterface_ExpressionValue.externalBindings, errorValue> => {
|
||||
let rAnswer = evaluateUsingOptions(
|
||||
~environment=Some(environment),
|
||||
~externalBindings=Some(externalBindings),
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
module Bindings = Reducer_Expression_Bindings
|
||||
module BindingsReplacer = Reducer_Expression_BindingsReplacer
|
||||
module ErrorValue = Reducer_ErrorValue
|
||||
module ExpressionT = Reducer_Expression_T
|
||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
||||
module ExpressionValue = ReducerInterface_InternalExpressionValue
|
||||
module Result = Belt.Result
|
||||
module Module = Reducer_Category_Module
|
||||
|
||||
type bindings = ExpressionT.bindings
|
||||
type context = bindings
|
||||
|
@ -10,7 +11,6 @@ type environment = ExpressionValue.environment
|
|||
type errorValue = Reducer_ErrorValue.errorValue
|
||||
type expression = ExpressionT.expression
|
||||
type expressionValue = ExpressionValue.expressionValue
|
||||
type externalBindings = ReducerInterface_ExpressionValue.externalBindings
|
||||
type reducerFn = ExpressionT.reducerFn
|
||||
|
||||
type expressionWithContext =
|
||||
|
@ -40,7 +40,9 @@ let toString = expressionWithContext =>
|
|||
switch expressionWithContext {
|
||||
| ExpressionNoContext(expr) => ExpressionT.toString(expr)
|
||||
| ExpressionWithContext(expr, context) =>
|
||||
`${ExpressionT.toString(expr)} context: ${Bindings.toString(context)}`
|
||||
`${ExpressionT.toString(expr)} context: ${context
|
||||
->Module.toExpressionValue
|
||||
->ExpressionValue.toString}`
|
||||
}
|
||||
|
||||
let toStringResult = rExpressionWithContext =>
|
||||
|
|
|
@ -1,27 +1,15 @@
|
|||
module ErrorValue = Reducer_ErrorValue
|
||||
module ExpressionT = Reducer_Expression_T
|
||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
||||
module ExpressionValue = ReducerInterface_InternalExpressionValue
|
||||
module Result = Belt.Result
|
||||
module Bindings = Reducer_Category_Bindings
|
||||
module Module = Reducer_Category_Module
|
||||
|
||||
type errorValue = Reducer_ErrorValue.errorValue
|
||||
type expression = ExpressionT.expression
|
||||
type expressionValue = ExpressionValue.expressionValue
|
||||
type tmpExternalBindings = ReducerInterface_InternalExpressionValue.tmpExternalBindings
|
||||
type externalBindings = ReducerInterface_ExpressionValue.externalBindings
|
||||
|
||||
let emptyBindings = Reducer_Category_Bindings.emptyBindings
|
||||
|
||||
let typeAliasesKey = Bindings.typeAliasesKey
|
||||
let typeReferencesKey = Bindings.typeReferencesKey
|
||||
|
||||
let toExternalBindings = (bindings: ExpressionT.bindings): externalBindings =>
|
||||
Bindings.toRecord(bindings)
|
||||
|
||||
let fromExternalBindings = (externalBindings: externalBindings): ExpressionT.bindings =>
|
||||
Bindings.fromRecord(externalBindings)
|
||||
|
||||
let fromValue = (aValue: expressionValue) => Bindings.fromExpressionValue(aValue)
|
||||
|
||||
let isMacroName = (fName: string): bool => fName->Js.String2.startsWith("$$")
|
||||
|
||||
let rec replaceSymbols = (bindings: ExpressionT.bindings, expression: expression): result<
|
||||
|
@ -33,7 +21,7 @@ let rec replaceSymbols = (bindings: ExpressionT.bindings, expression: expression
|
|||
replaceSymbolOnValue(bindings, value)->Result.map(evValue => evValue->ExpressionT.EValue)
|
||||
| ExpressionT.EList(list) =>
|
||||
switch list {
|
||||
| list{EValue(EvCall(fName)), ..._args} =>
|
||||
| list{EValue(IevCall(fName)), ..._args} =>
|
||||
switch isMacroName(fName) {
|
||||
// A macro reduces itself so we dont dive in it
|
||||
| true => expression->Ok
|
||||
|
@ -55,18 +43,12 @@ and replaceSymbolsOnExpressionList = (bindings, list) => {
|
|||
}
|
||||
and replaceSymbolOnValue = (bindings, evValue: expressionValue) =>
|
||||
switch evValue {
|
||||
| EvSymbol(symbol) => Belt.Map.String.getWithDefault(bindings, symbol, evValue)->Ok
|
||||
| EvCall(symbol) => Belt.Map.String.getWithDefault(bindings, symbol, evValue)->checkIfCallable
|
||||
| IevSymbol(symbol) => Module.getWithDefault(bindings, symbol, evValue)->Ok
|
||||
| IevCall(symbol) => Module.getWithDefault(bindings, symbol, evValue)->checkIfCallable
|
||||
| _ => evValue->Ok
|
||||
}
|
||||
and checkIfCallable = (evValue: expressionValue) =>
|
||||
switch evValue {
|
||||
| EvCall(_) | EvLambda(_) => evValue->Ok
|
||||
| IevCall(_) | IevLambda(_) => evValue->Ok
|
||||
| _ => ErrorValue.RENotAFunction(ExpressionValue.toString(evValue))->Error
|
||||
}
|
||||
|
||||
let toString = (bindings: ExpressionT.bindings) =>
|
||||
bindings->toExternalBindings->ExpressionValue.EvRecord->ExpressionValue.toString
|
||||
|
||||
let externalBindingsToString = (externalBindings: externalBindings) =>
|
||||
externalBindings->ExpressionValue.EvRecord->ExpressionValue.toString
|
|
@ -1,24 +1,27 @@
|
|||
module BBindings = Reducer_Expression_Bindings
|
||||
module BBindingsReplacer = Reducer_Expression_BindingsReplacer
|
||||
module BErrorValue = Reducer_ErrorValue
|
||||
module BExpressionT = Reducer_Expression_T
|
||||
module BExpressionValue = ReducerInterface.ExpressionValue
|
||||
module BExpressionValue = ReducerInterface_InternalExpressionValue
|
||||
module BModule = Reducer_Category_Module
|
||||
|
||||
type errorValue = BErrorValue.errorValue
|
||||
type expression = BExpressionT.expression
|
||||
type internalCode = ReducerInterface_ExpressionValue.internalCode
|
||||
type expressionOrFFI = BExpressionT.expressionOrFFI
|
||||
type ffiFn = BExpressionT.ffiFn
|
||||
type internalCode = ReducerInterface_InternalExpressionValue.internalCode
|
||||
|
||||
external castExpressionToInternalCode: expression => internalCode = "%identity"
|
||||
external castExpressionToInternalCode: expressionOrFFI => internalCode = "%identity"
|
||||
|
||||
let eArray = anArray => anArray->BExpressionValue.EvArray->BExpressionT.EValue
|
||||
let eArray = anArray => anArray->BExpressionValue.IevArray->BExpressionT.EValue
|
||||
|
||||
let eArrayString = anArray => anArray->BExpressionValue.EvArrayString->BExpressionT.EValue
|
||||
let eArrayString = anArray => anArray->BExpressionValue.IevArrayString->BExpressionT.EValue
|
||||
|
||||
let eBindings = (anArray: array<(string, BExpressionValue.expressionValue)>) =>
|
||||
anArray->Js.Dict.fromArray->BExpressionValue.EvRecord->BExpressionT.EValue
|
||||
anArray->BModule.fromArray->BModule.toExpressionValue->BExpressionT.EValue
|
||||
|
||||
let eBool = aBool => aBool->BExpressionValue.EvBool->BExpressionT.EValue
|
||||
let eBool = aBool => aBool->BExpressionValue.IevBool->BExpressionT.EValue
|
||||
|
||||
let eCall = (name: string): expression => name->BExpressionValue.EvCall->BExpressionT.EValue
|
||||
let eCall = (name: string): expression => name->BExpressionValue.IevCall->BExpressionT.EValue
|
||||
|
||||
let eFunction = (fName: string, lispArgs: list<expression>): expression => {
|
||||
let fn = fName->eCall
|
||||
|
@ -27,29 +30,40 @@ let eFunction = (fName: string, lispArgs: list<expression>): expression => {
|
|||
|
||||
let eLambda = (
|
||||
parameters: array<string>,
|
||||
context: BExpressionValue.externalBindings,
|
||||
context: BExpressionValue.nameSpace,
|
||||
expr: expression,
|
||||
) => {
|
||||
// Js.log(`eLambda context ${BBindings.externalBindingsToString(context)}`)
|
||||
BExpressionValue.EvLambda({
|
||||
BExpressionValue.IevLambda({
|
||||
parameters: parameters,
|
||||
context: context,
|
||||
body: expr->castExpressionToInternalCode,
|
||||
body: NotFFI(expr)->castExpressionToInternalCode,
|
||||
})->BExpressionT.EValue
|
||||
}
|
||||
|
||||
let eNumber = aNumber => aNumber->BExpressionValue.EvNumber->BExpressionT.EValue
|
||||
let eLambdaFFI = (parameters: array<string>, ffiFn: ffiFn) => {
|
||||
let context = BModule.emptyModule
|
||||
BExpressionValue.IevLambda({
|
||||
parameters: parameters,
|
||||
context: context,
|
||||
body: FFI(ffiFn)->castExpressionToInternalCode,
|
||||
})->BExpressionT.EValue
|
||||
}
|
||||
|
||||
let eRecord = aRecord => aRecord->BExpressionValue.EvRecord->BExpressionT.EValue
|
||||
let eNumber = aNumber => aNumber->BExpressionValue.IevNumber->BExpressionT.EValue
|
||||
|
||||
let eString = aString => aString->BExpressionValue.EvString->BExpressionT.EValue
|
||||
let eRecord = aMap => aMap->BExpressionValue.IevRecord->BExpressionT.EValue
|
||||
|
||||
let eSymbol = (name: string): expression => name->BExpressionValue.EvSymbol->BExpressionT.EValue
|
||||
let eString = aString => aString->BExpressionValue.IevString->BExpressionT.EValue
|
||||
|
||||
let eSymbol = (name: string): expression => name->BExpressionValue.IevSymbol->BExpressionT.EValue
|
||||
|
||||
let eList = (list: list<expression>): expression => list->BExpressionT.EList
|
||||
|
||||
let eBlock = (exprs: list<expression>): expression => eFunction("$$_block_$$", exprs)
|
||||
|
||||
let eModule = (nameSpace: BExpressionValue.nameSpace): expression =>
|
||||
nameSpace->BExpressionValue.IevModule->BExpressionT.EValue
|
||||
|
||||
let eLetStatement = (symbol: string, valueExpression: expression): expression =>
|
||||
eFunction("$_let_$", list{eSymbol(symbol), valueExpression})
|
||||
|
||||
|
@ -65,7 +79,8 @@ let eBindExpression = (bindingExpr: expression, expression: expression): express
|
|||
let eBindExpressionDefault = (expression: expression): expression =>
|
||||
eFunction("$$_bindExpression_$$", list{expression})
|
||||
|
||||
let eIdentifier = (name: string): expression => name->BExpressionValue.EvSymbol->BExpressionT.EValue
|
||||
let eIdentifier = (name: string): expression =>
|
||||
name->BExpressionValue.IevSymbol->BExpressionT.EValue
|
||||
|
||||
let eTypeIdentifier = (name: string): expression =>
|
||||
name->BExpressionValue.EvTypeIdentifier->BExpressionT.EValue
|
||||
name->BExpressionValue.IevTypeIdentifier->BExpressionT.EValue
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
module Bindings = Reducer_Expression_Bindings
|
||||
module BindingsReplacer = Reducer_Expression_BindingsReplacer
|
||||
module ErrorValue = Reducer_ErrorValue
|
||||
module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
|
||||
module ExpressionT = Reducer_Expression_T
|
||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
||||
module ExpressionValue = ReducerInterface_InternalExpressionValue
|
||||
module Module = Reducer_Category_Module
|
||||
module Result = Belt.Result
|
||||
|
||||
type environment = ReducerInterface_ExpressionValue.environment
|
||||
type environment = ReducerInterface_InternalExpressionValue.environment
|
||||
type expression = ExpressionT.expression
|
||||
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
||||
type externalBindings = ReducerInterface_ExpressionValue.externalBindings
|
||||
type internalCode = ReducerInterface_ExpressionValue.internalCode
|
||||
type expressionOrFFI = ExpressionT.expressionOrFFI
|
||||
type expressionValue = ReducerInterface_InternalExpressionValue.expressionValue
|
||||
// type tmpExternalBindings = ReducerInterface_InternalExpressionValue.tmpExternalBindings
|
||||
type internalCode = ReducerInterface_InternalExpressionValue.internalCode
|
||||
|
||||
external castInternalCodeToExpression: internalCode => expression = "%identity"
|
||||
external castInternalCodeToExpression: internalCode => expressionOrFFI = "%identity"
|
||||
|
||||
let checkArity = (lambdaValue: ExpressionValue.lambdaValue, args: list<expressionValue>) => {
|
||||
let argsLength = Belt.List.length(args)
|
||||
|
@ -27,12 +29,27 @@ let checkIfReduced = (args: list<expressionValue>) =>
|
|||
args->Belt.List.reduceReverse(Ok(list{}), (rAcc, arg) =>
|
||||
rAcc->Result.flatMap(acc =>
|
||||
switch arg {
|
||||
| EvSymbol(symbol) => ErrorValue.RESymbolNotFound(symbol)->Error
|
||||
| IevSymbol(symbol) => ErrorValue.RESymbolNotFound(symbol)->Error
|
||||
| _ => list{arg, ...acc}->Ok
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
let caseNotFFI = (lambdaValue: ExpressionValue.lambdaValue, expr, args, environment, reducer) => {
|
||||
let parameterList = lambdaValue.parameters->Belt.List.fromArray
|
||||
let zippedParameterList = parameterList->Belt.List.zip(args)
|
||||
let bindings = Belt.List.reduce(zippedParameterList, lambdaValue.context, (
|
||||
acc,
|
||||
(variable, variableValue),
|
||||
) => acc->Module.set(variable, variableValue))
|
||||
let newExpression = ExpressionBuilder.eBlock(list{expr})
|
||||
reducer(newExpression, bindings, environment)
|
||||
}
|
||||
|
||||
let caseFFI = (ffiFn: ExpressionT.ffiFn, args, environment) => {
|
||||
ffiFn(args->Belt.List.toArray, environment)
|
||||
}
|
||||
|
||||
let applyParametersToLambda = (
|
||||
lambdaValue: ExpressionValue.lambdaValue,
|
||||
args,
|
||||
|
@ -41,16 +58,11 @@ let applyParametersToLambda = (
|
|||
): result<expressionValue, 'e> => {
|
||||
checkArity(lambdaValue, args)->Result.flatMap(args =>
|
||||
checkIfReduced(args)->Result.flatMap(args => {
|
||||
let expr = castInternalCodeToExpression(lambdaValue.body)
|
||||
let parameterList = lambdaValue.parameters->Belt.List.fromArray
|
||||
let zippedParameterList = parameterList->Belt.List.zip(args)
|
||||
let bindings = Belt.List.reduce(
|
||||
zippedParameterList,
|
||||
lambdaValue.context->Bindings.fromExternalBindings,
|
||||
(acc, (variable, variableValue)) => acc->Belt.Map.String.set(variable, variableValue),
|
||||
)
|
||||
let newExpression = ExpressionBuilder.eBlock(list{expr})
|
||||
reducer(newExpression, bindings, environment)
|
||||
let exprOrFFI = castInternalCodeToExpression(lambdaValue.body)
|
||||
switch exprOrFFI {
|
||||
| NotFFI(expr) => caseNotFFI(lambdaValue, expr, args, environment, reducer)
|
||||
| FFI(ffiFn) => caseFFI(ffiFn, args, environment)
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module ExpressionT = Reducer_Expression_T
|
||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
||||
module ExpressionValue = ReducerInterface_InternalExpressionValue
|
||||
module ExpressionWithContext = Reducer_ExpressionWithContext
|
||||
module Result = Belt.Result
|
||||
|
||||
|
|
|
@ -7,15 +7,15 @@
|
|||
The act of defining the semantics of a functional language is to write it in terms of Lisp AST.
|
||||
*/
|
||||
module Extra = Reducer_Extra
|
||||
module ExpressionValue = ReducerInterface.ExpressionValue
|
||||
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||
|
||||
type expressionValue = ExpressionValue.expressionValue
|
||||
type environment = ExpressionValue.environment
|
||||
type expressionValue = InternalExpressionValue.expressionValue
|
||||
type environment = ReducerInterface_InternalExpressionValue.environment
|
||||
|
||||
type rec expression =
|
||||
| EList(list<expression>) // A list to map-reduce
|
||||
| EValue(expressionValue) // Irreducible built-in value. Reducer should not know the internals. External libraries are responsible
|
||||
and bindings = Belt.Map.String.t<expressionValue>
|
||||
and bindings = InternalExpressionValue.nameSpace
|
||||
|
||||
type reducerFn = (
|
||||
expression,
|
||||
|
@ -28,7 +28,7 @@ type reducerFn = (
|
|||
*/
|
||||
let rec toString = expression =>
|
||||
switch expression {
|
||||
| EList(list{EValue(EvCall("$$_block_$$")), ...statements}) =>
|
||||
| EList(list{EValue(IevCall("$$_block_$$")), ...statements}) =>
|
||||
`{${Belt.List.map(statements, aValue => toString(aValue))
|
||||
->Extra.List.interperse("; ")
|
||||
->Belt.List.toArray
|
||||
|
@ -38,7 +38,7 @@ let rec toString = expression =>
|
|||
->Extra.List.interperse(" ")
|
||||
->Belt.List.toArray
|
||||
->Js.String.concatMany("")})`
|
||||
| EValue(aValue) => ExpressionValue.toString(aValue)
|
||||
| EValue(aValue) => InternalExpressionValue.toString(aValue)
|
||||
}
|
||||
|
||||
let toStringResult = codeResult =>
|
||||
|
@ -65,3 +65,12 @@ let inspectResult = (r: result<expression, Reducer_ErrorValue.errorValue>): resu
|
|||
Js.log(toStringResult(r))
|
||||
r
|
||||
}
|
||||
|
||||
type ffiFn = (
|
||||
array<expressionValue>,
|
||||
environment,
|
||||
) => result<expressionValue, Reducer_ErrorValue.errorValue>
|
||||
|
||||
type expressionOrFFI =
|
||||
| NotFFI(expression)
|
||||
| FFI(ffiFn)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
open ReducerInterface.ExpressionValue
|
||||
open ReducerInterface_InternalExpressionValue
|
||||
open Reducer_ErrorValue
|
||||
|
||||
external castBool: unit => bool = "%identity"
|
||||
|
@ -8,10 +8,10 @@ external castString: unit => string = "%identity"
|
|||
/*
|
||||
As JavaScript returns us any type, we need to type check and cast type propertype before using it
|
||||
*/
|
||||
let jsToEv = (jsValue): result<expressionValue, errorValue> =>
|
||||
let jsToIev = (jsValue): result<expressionValue, errorValue> =>
|
||||
switch Js.typeof(jsValue) {
|
||||
| "boolean" => jsValue->castBool->EvBool->Ok
|
||||
| "number" => jsValue->castNumber->EvNumber->Ok
|
||||
| "string" => jsValue->castString->EvString->Ok
|
||||
| "boolean" => jsValue->castBool->IevBool->Ok
|
||||
| "number" => jsValue->castNumber->IevNumber->Ok
|
||||
| "string" => jsValue->castString->IevString->Ok
|
||||
| other => RETodo(`Unhandled MathJs literal type: ${Js.String.make(other)}`)->Error
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module JavaScript = Reducer_Js
|
||||
open ReducerInterface.ExpressionValue
|
||||
open ReducerInterface_InternalExpressionValue
|
||||
open Reducer_ErrorValue
|
||||
|
||||
@module("mathjs") external dummy_: string => unit = "evaluate"
|
||||
|
@ -20,7 +20,7 @@ let eval__: string => 'a = %raw(`function (expr) { return {value: Mathjs.evaluat
|
|||
let eval = (expr: string): result<expressionValue, errorValue> => {
|
||||
try {
|
||||
let answer = eval__(expr)
|
||||
answer["value"]->JavaScript.Gate.jsToEv
|
||||
answer["value"]->JavaScript.Gate.jsToIev
|
||||
} catch {
|
||||
| Js.Exn.Error(obj) => REJavaScriptExn(Js.Exn.message(obj), Js.Exn.name(obj))->Error
|
||||
}
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
module ExpressionValue = ReducerInterface_ExpressionValue
|
||||
module ExternalExpressionValue = ReducerInterface_ExpressionValue
|
||||
module ExternalLibrary = ReducerInterface_ExternalLibrary
|
||||
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
|
||||
module StdLib = ReducerInterface_StdLib
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
module EV = ReducerInterface_ExpressionValue
|
||||
module EV = ReducerInterface_InternalExpressionValue
|
||||
type expressionValue = EV.expressionValue
|
||||
|
||||
let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
|
||||
result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
|
||||
> => {
|
||||
switch call {
|
||||
| ("toString", [EvDate(t)]) => EV.EvString(DateTime.Date.toString(t))->Ok->Some
|
||||
| ("makeDateFromYear", [EvNumber(year)]) =>
|
||||
| ("toString", [IevDate(t)]) => EV.IevString(DateTime.Date.toString(t))->Ok->Some
|
||||
| ("makeDateFromYear", [IevNumber(year)]) =>
|
||||
switch DateTime.Date.makeFromYear(year) {
|
||||
| Ok(t) => EV.EvDate(t)->Ok->Some
|
||||
| Ok(t) => EV.IevDate(t)->Ok->Some
|
||||
| Error(e) => Reducer_ErrorValue.RETodo(e)->Error->Some
|
||||
}
|
||||
| ("dateFromNumber", [EvNumber(f)]) => EV.EvDate(DateTime.Date.fromFloat(f))->Ok->Some
|
||||
| ("toNumber", [EvDate(f)]) => EV.EvNumber(DateTime.Date.toFloat(f))->Ok->Some
|
||||
| ("subtract", [EvDate(d1), EvDate(d2)]) =>
|
||||
| ("dateFromNumber", [IevNumber(f)]) => EV.IevDate(DateTime.Date.fromFloat(f))->Ok->Some
|
||||
| ("toNumber", [IevDate(f)]) => EV.IevNumber(DateTime.Date.toFloat(f))->Ok->Some
|
||||
| ("subtract", [IevDate(d1), IevDate(d2)]) =>
|
||||
switch DateTime.Date.subtract(d1, d2) {
|
||||
| Ok(d) => EV.EvTimeDuration(d)->Ok
|
||||
| Ok(d) => EV.IevTimeDuration(d)->Ok
|
||||
| Error(e) => Error(RETodo(e))
|
||||
}->Some
|
||||
| ("subtract", [EvDate(d1), EvTimeDuration(d2)]) =>
|
||||
EV.EvDate(DateTime.Date.subtractDuration(d1, d2))->Ok->Some
|
||||
| ("add", [EvDate(d1), EvTimeDuration(d2)]) =>
|
||||
EV.EvDate(DateTime.Date.addDuration(d1, d2))->Ok->Some
|
||||
| ("subtract", [IevDate(d1), IevTimeDuration(d2)]) =>
|
||||
EV.IevDate(DateTime.Date.subtractDuration(d1, d2))->Ok->Some
|
||||
| ("add", [IevDate(d1), IevTimeDuration(d2)]) =>
|
||||
EV.IevDate(DateTime.Date.addDuration(d1, d2))->Ok->Some
|
||||
| _ => None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +1,35 @@
|
|||
module EV = ReducerInterface_ExpressionValue
|
||||
module EV = ReducerInterface_InternalExpressionValue
|
||||
type expressionValue = EV.expressionValue
|
||||
|
||||
let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
|
||||
result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
|
||||
> => {
|
||||
switch call {
|
||||
| ("toString", [EvTimeDuration(t)]) => EV.EvString(DateTime.Duration.toString(t))->Ok->Some
|
||||
| ("minutes", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromMinutes(f))->Ok->Some
|
||||
| ("fromUnit_minutes", [EvNumber(f)]) =>
|
||||
EV.EvTimeDuration(DateTime.Duration.fromMinutes(f))->Ok->Some
|
||||
| ("hours", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some
|
||||
| ("fromUnit_hours", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some
|
||||
| ("days", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
|
||||
| ("fromUnit_days", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
|
||||
| ("years", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
|
||||
| ("fromUnit_years", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
|
||||
| ("toHours", [EvTimeDuration(f)]) => EV.EvNumber(DateTime.Duration.toHours(f))->Ok->Some
|
||||
| ("toMinutes", [EvTimeDuration(f)]) => EV.EvNumber(DateTime.Duration.toMinutes(f))->Ok->Some
|
||||
| ("toDays", [EvTimeDuration(f)]) => EV.EvNumber(DateTime.Duration.toDays(f))->Ok->Some
|
||||
| ("toYears", [EvTimeDuration(f)]) => EV.EvNumber(DateTime.Duration.toYears(f))->Ok->Some
|
||||
| ("add", [EvTimeDuration(d1), EvTimeDuration(d2)]) =>
|
||||
EV.EvTimeDuration(DateTime.Duration.add(d1, d2))->Ok->Some
|
||||
| ("subtract", [EvTimeDuration(d1), EvTimeDuration(d2)]) =>
|
||||
EV.EvTimeDuration(DateTime.Duration.subtract(d1, d2))->Ok->Some
|
||||
| ("multiply", [EvTimeDuration(d1), EvNumber(d2)]) =>
|
||||
EV.EvTimeDuration(DateTime.Duration.multiply(d1, d2))->Ok->Some
|
||||
| ("divide", [EvTimeDuration(d1), EvNumber(d2)]) =>
|
||||
EV.EvTimeDuration(DateTime.Duration.divide(d1, d2))->Ok->Some
|
||||
| ("divide", [EvTimeDuration(d1), EvTimeDuration(d2)]) => EV.EvNumber(d1 /. d2)->Ok->Some
|
||||
| ("toString", [IevTimeDuration(t)]) => EV.IevString(DateTime.Duration.toString(t))->Ok->Some
|
||||
| ("minutes", [IevNumber(f)]) => EV.IevTimeDuration(DateTime.Duration.fromMinutes(f))->Ok->Some
|
||||
| ("fromUnit_minutes", [IevNumber(f)]) =>
|
||||
EV.IevTimeDuration(DateTime.Duration.fromMinutes(f))->Ok->Some
|
||||
| ("hours", [IevNumber(f)]) => EV.IevTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some
|
||||
| ("fromUnit_hours", [IevNumber(f)]) =>
|
||||
EV.IevTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some
|
||||
| ("days", [IevNumber(f)]) => EV.IevTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
|
||||
| ("fromUnit_days", [IevNumber(f)]) => EV.IevTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
|
||||
| ("years", [IevNumber(f)]) => EV.IevTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
|
||||
| ("fromUnit_years", [IevNumber(f)]) =>
|
||||
EV.IevTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
|
||||
| ("toHours", [IevTimeDuration(f)]) => EV.IevNumber(DateTime.Duration.toHours(f))->Ok->Some
|
||||
| ("toMinutes", [IevTimeDuration(f)]) => EV.IevNumber(DateTime.Duration.toMinutes(f))->Ok->Some
|
||||
| ("toDays", [IevTimeDuration(f)]) => EV.IevNumber(DateTime.Duration.toDays(f))->Ok->Some
|
||||
| ("toYears", [IevTimeDuration(f)]) => EV.IevNumber(DateTime.Duration.toYears(f))->Ok->Some
|
||||
| ("add", [IevTimeDuration(d1), IevTimeDuration(d2)]) =>
|
||||
EV.IevTimeDuration(DateTime.Duration.add(d1, d2))->Ok->Some
|
||||
| ("subtract", [IevTimeDuration(d1), IevTimeDuration(d2)]) =>
|
||||
EV.IevTimeDuration(DateTime.Duration.subtract(d1, d2))->Ok->Some
|
||||
| ("multiply", [IevTimeDuration(d1), IevNumber(d2)]) =>
|
||||
EV.IevTimeDuration(DateTime.Duration.multiply(d1, d2))->Ok->Some
|
||||
| ("divide", [IevTimeDuration(d1), IevNumber(d2)]) =>
|
||||
EV.IevTimeDuration(DateTime.Duration.divide(d1, d2))->Ok->Some
|
||||
| ("divide", [IevTimeDuration(d1), IevTimeDuration(d2)]) => EV.IevNumber(d1 /. d2)->Ok->Some
|
||||
| _ => None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,25 +68,6 @@ and toStringRecord = aRecord => {
|
|||
`{${pairs}}`
|
||||
}
|
||||
|
||||
let toStringWithType = aValue =>
|
||||
switch aValue {
|
||||
| EvArray(_) => `Array::${toString(aValue)}`
|
||||
| EvArrayString(_) => `ArrayString::${toString(aValue)}`
|
||||
| EvBool(_) => `Bool::${toString(aValue)}`
|
||||
| EvCall(_) => `Call::${toString(aValue)}`
|
||||
| EvDistribution(_) => `Distribution::${toString(aValue)}`
|
||||
| EvLambda(_) => `Lambda::${toString(aValue)}`
|
||||
| EvNumber(_) => `Number::${toString(aValue)}`
|
||||
| EvRecord(_) => `Record::${toString(aValue)}`
|
||||
| EvString(_) => `String::${toString(aValue)}`
|
||||
| EvSymbol(_) => `Symbol::${toString(aValue)}`
|
||||
| EvDate(_) => `Date::${toString(aValue)}`
|
||||
| EvTimeDuration(_) => `Date::${toString(aValue)}`
|
||||
| EvDeclaration(_) => `Declaration::${toString(aValue)}`
|
||||
| EvTypeIdentifier(_) => `TypeIdentifier::${toString(aValue)}`
|
||||
| EvModule(_) => `Module::${toString(aValue)}`
|
||||
}
|
||||
|
||||
let argsToString = (args: array<expressionValue>): string => {
|
||||
args->Js.Array2.map(arg => arg->toString)->Js.Array2.toString
|
||||
}
|
||||
|
@ -99,17 +80,17 @@ let toStringResult = x =>
|
|||
| Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
||||
}
|
||||
|
||||
let toStringResultOkless = (codeResult: result<expressionValue, ErrorValue.errorValue>): string =>
|
||||
switch codeResult {
|
||||
| Ok(a) => toString(a)
|
||||
| Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
||||
}
|
||||
// let toStringResultOkless = (codeResult: result<expressionValue, ErrorValue.errorValue>): string =>
|
||||
// switch codeResult {
|
||||
// | Ok(a) => toString(a)
|
||||
// | Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
||||
// }
|
||||
|
||||
let toStringResultRecord = x =>
|
||||
switch x {
|
||||
| Ok(a) => `Ok(${toStringRecord(a)})`
|
||||
| Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
||||
}
|
||||
// let toStringResultRecord = x =>
|
||||
// switch x {
|
||||
// | Ok(a) => `Ok(${toStringRecord(a)})`
|
||||
// | Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
||||
// }
|
||||
|
||||
@genType
|
||||
type environment = DistributionOperation.env
|
||||
|
@ -141,14 +122,14 @@ type functionDefinitionSignature =
|
|||
let valueToValueType = value =>
|
||||
switch value {
|
||||
| EvArray(_) => EvtArray
|
||||
| EvArrayString(_) => EvtArray
|
||||
| EvArrayString(_) => EvtArrayString
|
||||
| EvBool(_) => EvtBool
|
||||
| EvCall(_) => EvtCall
|
||||
| EvDistribution(_) => EvtDistribution
|
||||
| EvLambda(_) => EvtLambda
|
||||
| EvNumber(_) => EvtNumber
|
||||
| EvRecord(_) => EvtRecord
|
||||
| EvString(_) => EvtArray
|
||||
| EvString(_) => EvtString
|
||||
| EvSymbol(_) => EvtSymbol
|
||||
| EvDate(_) => EvtDate
|
||||
| EvTimeDuration(_) => EvtTimeDuration
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module ExpressionValue = ReducerInterface_ExpressionValue
|
||||
module ExpressionValue = ReducerInterface_InternalExpressionValue
|
||||
|
||||
type expressionValue = ExpressionValue.expressionValue
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module ExpressionValue = ReducerInterface_ExpressionValue
|
||||
module ExpressionValue = ReducerInterface_InternalExpressionValue
|
||||
type expressionValue = ExpressionValue.expressionValue
|
||||
|
||||
module Helpers = {
|
||||
|
@ -23,9 +23,9 @@ module Helpers = {
|
|||
DistributionTypes.genericDist,
|
||||
)> =>
|
||||
switch args {
|
||||
| [EvDistribution(a), EvDistribution(b)] => Some((a, b))
|
||||
| [EvNumber(a), EvDistribution(b)] => Some((GenericDist.fromFloat(a), b))
|
||||
| [EvDistribution(a), EvNumber(b)] => Some((a, GenericDist.fromFloat(b)))
|
||||
| [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
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ module Helpers = {
|
|||
|
||||
let parseNumber = (args: expressionValue): Belt.Result.t<float, string> =>
|
||||
switch args {
|
||||
| EvNumber(x) => Ok(x)
|
||||
| IevNumber(x) => Ok(x)
|
||||
| _ => Error("Not a number")
|
||||
}
|
||||
|
||||
|
@ -91,8 +91,8 @@ module Helpers = {
|
|||
|
||||
let parseDist = (args: expressionValue): Belt.Result.t<DistributionTypes.genericDist, string> =>
|
||||
switch args {
|
||||
| EvDistribution(x) => Ok(x)
|
||||
| EvNumber(x) => Ok(GenericDist.fromFloat(x))
|
||||
| IevDistribution(x) => Ok(x)
|
||||
| IevNumber(x) => Ok(GenericDist.fromFloat(x))
|
||||
| _ => Error("Not a distribution")
|
||||
}
|
||||
|
||||
|
@ -128,12 +128,12 @@ module Helpers = {
|
|||
let error = (err: string): DistributionOperation.outputType =>
|
||||
err->DistributionTypes.ArgumentError->GenDistError
|
||||
switch args {
|
||||
| [EvArray(distributions)] =>
|
||||
| [IevArray(distributions)] =>
|
||||
switch parseDistributionArray(distributions) {
|
||||
| Ok(distrs) => mixtureWithDefaultWeights(distrs, ~env)
|
||||
| Error(err) => error(err)
|
||||
}
|
||||
| [EvArray(distributions), EvArray(weights)] =>
|
||||
| [IevArray(distributions), IevArray(weights)] =>
|
||||
switch (parseDistributionArray(distributions), parseNumberArray(weights)) {
|
||||
| (Ok(distrs), Ok(wghts)) => mixtureWithGivenWeights(distrs, wghts, ~env)
|
||||
| (Error(err), Ok(_)) => error(err)
|
||||
|
@ -142,7 +142,7 @@ module Helpers = {
|
|||
}
|
||||
| _ =>
|
||||
switch E.A.last(args) {
|
||||
| Some(EvArray(b)) => {
|
||||
| Some(IevArray(b)) => {
|
||||
let weights = parseNumberArray(b)
|
||||
let distributions = parseDistributionArray(
|
||||
Belt.Array.slice(args, ~offset=0, ~len=E.A.length(args) - 1),
|
||||
|
@ -152,8 +152,8 @@ module Helpers = {
|
|||
| Error(err) => error(err)
|
||||
}
|
||||
}
|
||||
| Some(EvNumber(_))
|
||||
| Some(EvDistribution(_)) =>
|
||||
| Some(IevNumber(_))
|
||||
| Some(IevDistribution(_)) =>
|
||||
switch parseDistributionArray(args) {
|
||||
| Ok(distributions) => mixtureWithDefaultWeights(distributions, ~env)
|
||||
| Error(err) => error(err)
|
||||
|
@ -200,14 +200,14 @@ let dispatchToGenericOutput = (
|
|||
): option<DistributionOperation.outputType> => {
|
||||
let (fnName, args) = call
|
||||
switch (fnName, args) {
|
||||
| ("triangular" as fnName, [EvNumber(f1), EvNumber(f2), EvNumber(f3)]) =>
|
||||
| ("triangular" as fnName, [IevNumber(f1), IevNumber(f2), IevNumber(f3)]) =>
|
||||
SymbolicConstructors.threeFloat(fnName)
|
||||
->E.R.bind(r => r(f1, f2, f3))
|
||||
->SymbolicConstructors.symbolicResultToOutput
|
||||
| ("sample", [EvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist, ~env)
|
||||
| ("sampleN", [EvDistribution(dist), EvNumber(n)]) =>
|
||||
| ("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, [EvDistribution(dist)]) => {
|
||||
| (("mean" | "stdev" | "variance" | "min" | "max" | "mode") as op, [IevDistribution(dist)]) => {
|
||||
let fn = switch op {
|
||||
| "mean" => #Mean
|
||||
| "stdev" => #Stdev
|
||||
|
@ -219,13 +219,13 @@ let dispatchToGenericOutput = (
|
|||
}
|
||||
Helpers.toFloatFn(fn, dist, ~env)
|
||||
}
|
||||
| ("integralSum", [EvDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist, ~env)
|
||||
| ("toString", [EvDistribution(dist)]) => Helpers.toStringFn(ToString, dist, ~env)
|
||||
| ("toSparkline", [EvDistribution(dist)]) =>
|
||||
| ("integralSum", [IevDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist, ~env)
|
||||
| ("toString", [IevDistribution(dist)]) => Helpers.toStringFn(ToString, dist, ~env)
|
||||
| ("toSparkline", [IevDistribution(dist)]) =>
|
||||
Helpers.toStringFn(ToSparkline(MagicNumbers.Environment.sparklineLength), dist, ~env)
|
||||
| ("toSparkline", [EvDistribution(dist), EvNumber(n)]) =>
|
||||
| ("toSparkline", [IevDistribution(dist), IevNumber(n)]) =>
|
||||
Helpers.toStringFn(ToSparkline(Belt.Float.toInt(n)), dist, ~env)
|
||||
| ("exp", [EvDistribution(a)]) =>
|
||||
| ("exp", [IevDistribution(a)]) =>
|
||||
// https://mathjs.org/docs/reference/functions/exp.html
|
||||
Helpers.twoDiststoDistFn(
|
||||
Algebraic(AsDefault),
|
||||
|
@ -234,51 +234,58 @@ let dispatchToGenericOutput = (
|
|||
a,
|
||||
~env,
|
||||
)->Some
|
||||
| ("normalize", [EvDistribution(dist)]) => Helpers.toDistFn(Normalize, dist, ~env)
|
||||
| ("klDivergence", [EvDistribution(prediction), EvDistribution(answer)]) =>
|
||||
| ("normalize", [IevDistribution(dist)]) => Helpers.toDistFn(Normalize, dist, ~env)
|
||||
| ("klDivergence", [IevDistribution(prediction), IevDistribution(answer)]) =>
|
||||
Some(DistributionOperation.run(FromDist(ToScore(KLDivergence(answer)), prediction), ~env))
|
||||
| ("klDivergence", [EvDistribution(prediction), EvDistribution(answer), EvDistribution(prior)]) =>
|
||||
| (
|
||||
"klDivergence",
|
||||
[IevDistribution(prediction), IevDistribution(answer), IevDistribution(prior)],
|
||||
) =>
|
||||
Helpers.klDivergenceWithPrior(prediction, answer, prior, env)
|
||||
| (
|
||||
"logScoreWithPointAnswer",
|
||||
[EvDistribution(prediction), EvNumber(answer), EvDistribution(prior)],
|
||||
[IevDistribution(prediction), IevNumber(answer), IevDistribution(prior)],
|
||||
)
|
||||
| (
|
||||
"logScoreWithPointAnswer",
|
||||
[EvDistribution(prediction), EvDistribution(Symbolic(#Float(answer))), EvDistribution(prior)],
|
||||
[
|
||||
IevDistribution(prediction),
|
||||
IevDistribution(Symbolic(#Float(answer))),
|
||||
IevDistribution(prior),
|
||||
],
|
||||
) =>
|
||||
DistributionOperation.run(
|
||||
FromDist(ToScore(LogScore(answer, prior->Some)), prediction),
|
||||
~env,
|
||||
)->Some
|
||||
| ("logScoreWithPointAnswer", [EvDistribution(prediction), EvNumber(answer)])
|
||||
| ("logScoreWithPointAnswer", [IevDistribution(prediction), IevNumber(answer)])
|
||||
| (
|
||||
"logScoreWithPointAnswer",
|
||||
[EvDistribution(prediction), EvDistribution(Symbolic(#Float(answer)))],
|
||||
[IevDistribution(prediction), IevDistribution(Symbolic(#Float(answer)))],
|
||||
) =>
|
||||
DistributionOperation.run(FromDist(ToScore(LogScore(answer, None)), prediction), ~env)->Some
|
||||
| ("isNormalized", [EvDistribution(dist)]) => Helpers.toBoolFn(IsNormalized, dist, ~env)
|
||||
| ("toPointSet", [EvDistribution(dist)]) => Helpers.toDistFn(ToPointSet, dist, ~env)
|
||||
| ("scaleLog", [EvDistribution(dist)]) =>
|
||||
| ("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", [EvDistribution(dist)]) => Helpers.toDistFn(Scale(#Logarithm, 10.0), dist, ~env)
|
||||
| ("scaleLog", [EvDistribution(dist), EvNumber(float)]) =>
|
||||
| ("scaleLog10", [IevDistribution(dist)]) => Helpers.toDistFn(Scale(#Logarithm, 10.0), dist, ~env)
|
||||
| ("scaleLog", [IevDistribution(dist), IevNumber(float)]) =>
|
||||
Helpers.toDistFn(Scale(#Logarithm, float), dist, ~env)
|
||||
| ("scaleLogWithThreshold", [EvDistribution(dist), EvNumber(base), EvNumber(eps)]) =>
|
||||
| ("scaleLogWithThreshold", [IevDistribution(dist), IevNumber(base), IevNumber(eps)]) =>
|
||||
Helpers.toDistFn(Scale(#LogarithmWithThreshold(eps), base), dist, ~env)
|
||||
| ("scalePow", [EvDistribution(dist), EvNumber(float)]) =>
|
||||
| ("scalePow", [IevDistribution(dist), IevNumber(float)]) =>
|
||||
Helpers.toDistFn(Scale(#Power, float), dist, ~env)
|
||||
| ("scaleExp", [EvDistribution(dist)]) =>
|
||||
| ("scaleExp", [IevDistribution(dist)]) =>
|
||||
Helpers.toDistFn(Scale(#Power, MagicNumbers.Math.e), dist, ~env)
|
||||
| ("cdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Cdf(float), dist, ~env)
|
||||
| ("pdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Pdf(float), dist, ~env)
|
||||
| ("inv", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Inv(float), dist, ~env)
|
||||
| ("toSampleSet", [EvDistribution(dist), EvNumber(float)]) =>
|
||||
| ("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)
|
||||
| ("toSampleSet", [IevDistribution(dist), IevNumber(float)]) =>
|
||||
Helpers.toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist, ~env)
|
||||
| ("toSampleSet", [EvDistribution(dist)]) =>
|
||||
| ("toSampleSet", [IevDistribution(dist)]) =>
|
||||
Helpers.toDistFn(ToSampleSet(env.sampleCount), dist, ~env)
|
||||
| ("toList", [EvDistribution(SampleSet(dist))]) => Some(FloatArray(SampleSetDist.T.get(dist)))
|
||||
| ("fromSamples", [EvArray(inputArray)]) => {
|
||||
| ("toList", [IevDistribution(SampleSet(dist))]) => Some(FloatArray(SampleSetDist.T.get(dist)))
|
||||
| ("fromSamples", [IevArray(inputArray)]) => {
|
||||
let _wrapInputErrors = x => SampleSetDist.NonNumericInput(x)
|
||||
let parsedArray = Helpers.parseNumberArray(inputArray)->E.R2.errMap(_wrapInputErrors)
|
||||
switch parsedArray {
|
||||
|
@ -286,15 +293,15 @@ let dispatchToGenericOutput = (
|
|||
| Error(e) => GenDistError(SampleSetError(e))
|
||||
}->Some
|
||||
}
|
||||
| ("inspect", [EvDistribution(dist)]) => Helpers.toDistFn(Inspect, dist, ~env)
|
||||
| ("truncateLeft", [EvDistribution(dist), EvNumber(float)]) =>
|
||||
| ("inspect", [IevDistribution(dist)]) => Helpers.toDistFn(Inspect, dist, ~env)
|
||||
| ("truncateLeft", [IevDistribution(dist), IevNumber(float)]) =>
|
||||
Helpers.toDistFn(Truncate(Some(float), None), dist, ~env)
|
||||
| ("truncateRight", [EvDistribution(dist), EvNumber(float)]) =>
|
||||
| ("truncateRight", [IevDistribution(dist), IevNumber(float)]) =>
|
||||
Helpers.toDistFn(Truncate(None, Some(float)), dist, ~env)
|
||||
| ("truncate", [EvDistribution(dist), EvNumber(float1), EvNumber(float2)]) =>
|
||||
| ("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", [EvDistribution(a)]) =>
|
||||
| ("log", [IevDistribution(a)]) =>
|
||||
Helpers.twoDiststoDistFn(
|
||||
Algebraic(AsDefault),
|
||||
"log",
|
||||
|
@ -302,7 +309,7 @@ let dispatchToGenericOutput = (
|
|||
GenericDist.fromFloat(MagicNumbers.Math.e),
|
||||
~env,
|
||||
)->Some
|
||||
| ("log10", [EvDistribution(a)]) =>
|
||||
| ("log10", [IevDistribution(a)]) =>
|
||||
Helpers.twoDiststoDistFn(
|
||||
Algebraic(AsDefault),
|
||||
"log",
|
||||
|
@ -310,7 +317,7 @@ let dispatchToGenericOutput = (
|
|||
GenericDist.fromFloat(10.0),
|
||||
~env,
|
||||
)->Some
|
||||
| ("unaryMinus", [EvDistribution(a)]) =>
|
||||
| ("unaryMinus", [IevDistribution(a)]) =>
|
||||
Helpers.twoDiststoDistFn(
|
||||
Algebraic(AsDefault),
|
||||
"multiply",
|
||||
|
@ -333,7 +340,7 @@ let dispatchToGenericOutput = (
|
|||
Helpers.catchAndConvertTwoArgsToDists(args)->E.O2.fmap(((fst, snd)) =>
|
||||
Helpers.twoDiststoDistFn(Pointwise, arithmetic, fst, snd, ~env)
|
||||
)
|
||||
| ("dotExp", [EvDistribution(a)]) =>
|
||||
| ("dotExp", [IevDistribution(a)]) =>
|
||||
Helpers.twoDiststoDistFn(
|
||||
Pointwise,
|
||||
"dotPow",
|
||||
|
@ -350,11 +357,12 @@ let genericOutputToReducerValue = (o: DistributionOperation.outputType): result<
|
|||
Reducer_ErrorValue.errorValue,
|
||||
> =>
|
||||
switch o {
|
||||
| Dist(d) => Ok(ReducerInterface_ExpressionValue.EvDistribution(d))
|
||||
| Float(d) => Ok(EvNumber(d))
|
||||
| String(d) => Ok(EvString(d))
|
||||
| Bool(d) => Ok(EvBool(d))
|
||||
| FloatArray(d) => Ok(EvArray(d |> E.A.fmap(r => ReducerInterface_ExpressionValue.EvNumber(r))))
|
||||
| Dist(d) => Ok(ReducerInterface_InternalExpressionValue.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 => ReducerInterface_InternalExpressionValue.IevNumber(r))))
|
||||
| GenDistError(err) => Error(REDistributionError(err))
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
let dispatch: (
|
||||
ReducerInterface_ExpressionValue.functionCall,
|
||||
ReducerInterface_InternalExpressionValue.functionCall,
|
||||
ReducerInterface_ExpressionValue.environment,
|
||||
) => option<result<ReducerInterface_ExpressionValue.expressionValue, Reducer_ErrorValue.errorValue>>
|
||||
) => option<
|
||||
result<ReducerInterface_InternalExpressionValue.expressionValue, Reducer_ErrorValue.errorValue>,
|
||||
>
|
||||
|
|
|
@ -0,0 +1,260 @@
|
|||
module ErrorValue = Reducer_ErrorValue
|
||||
module ExternalExpressionValue = ReducerInterface_ExpressionValue
|
||||
module Extra_Array = Reducer_Extra_Array
|
||||
type internalCode = ExternalExpressionValue.internalCode
|
||||
type environment = ExternalExpressionValue.environment
|
||||
|
||||
let defaultEnvironment = ExternalExpressionValue.defaultEnvironment
|
||||
|
||||
type rec expressionValue =
|
||||
| IevArray(array<expressionValue>) // FIXME: Convert
|
||||
| IevArrayString(array<string>) // FIXME: Convert
|
||||
| IevBool(bool)
|
||||
| IevCall(string) // External function call
|
||||
| IevDate(Js.Date.t)
|
||||
| IevDeclaration(lambdaDeclaration)
|
||||
| IevDistribution(DistributionTypes.genericDist)
|
||||
| IevLambda(lambdaValue)
|
||||
| IevModule(nameSpace) // FIXME: Convert
|
||||
| IevNumber(float)
|
||||
| IevRecord(map)
|
||||
| IevString(string)
|
||||
| IevSymbol(string)
|
||||
| IevTimeDuration(float)
|
||||
| IevTypeIdentifier(string)
|
||||
and map = Belt.Map.String.t<expressionValue>
|
||||
and nameSpace = NameSpace(Belt.Map.String.t<expressionValue>)
|
||||
and tmpExternalBindings = Js.Dict.t<expressionValue> // FIXME: Remove
|
||||
and lambdaValue = {
|
||||
parameters: array<string>,
|
||||
context: nameSpace,
|
||||
body: internalCode,
|
||||
}
|
||||
and lambdaDeclaration = Declaration.declaration<lambdaValue>
|
||||
|
||||
type t = expressionValue
|
||||
|
||||
type functionCall = (string, array<expressionValue>)
|
||||
|
||||
let rec toString = aValue =>
|
||||
switch aValue {
|
||||
| IevArray(anArray) => {
|
||||
let args = anArray->Js.Array2.map(each => toString(each))->Js.Array2.toString
|
||||
`[${args}]`
|
||||
}
|
||||
| IevArrayString(anArray) => {
|
||||
let args = anArray->Js.Array2.toString
|
||||
`[${args}]`
|
||||
}
|
||||
| IevBool(aBool) => Js.String.make(aBool)
|
||||
| IevCall(fName) => `:${fName}`
|
||||
| IevDate(date) => DateTime.Date.toString(date)
|
||||
| IevDeclaration(d) => Declaration.toString(d, r => toString(IevLambda(r)))
|
||||
| IevDistribution(dist) => GenericDist.toString(dist)
|
||||
| IevLambda(lambdaValue) => `lambda(${Js.Array2.toString(lambdaValue.parameters)}=>internal code)`
|
||||
| IevModule(m) => `@${m->toStringNameSpace}`
|
||||
| IevNumber(aNumber) => Js.String.make(aNumber)
|
||||
| IevRecord(aMap) => aMap->toStringMap
|
||||
| IevString(aString) => `'${aString}'`
|
||||
| IevSymbol(aString) => `:${aString}`
|
||||
| IevTimeDuration(t) => DateTime.Duration.toString(t)
|
||||
| IevTypeIdentifier(id) => `#${id}`
|
||||
}
|
||||
and toStringMap = aMap => {
|
||||
let pairs =
|
||||
aMap
|
||||
->Belt.Map.String.toArray
|
||||
->Js.Array2.map(((eachKey, eachValue)) => `${eachKey}: ${toString(eachValue)}`)
|
||||
->Js.Array2.toString
|
||||
`{${pairs}}`
|
||||
}
|
||||
and toStringNameSpace = nameSpace => {
|
||||
let NameSpace(container) = nameSpace
|
||||
container->toStringMap
|
||||
}
|
||||
|
||||
let toStringWithType = aValue =>
|
||||
switch aValue {
|
||||
| IevArray(_) => `Array::${toString(aValue)}`
|
||||
| IevArrayString(_) => `ArrayString::${toString(aValue)}`
|
||||
| IevBool(_) => `Bool::${toString(aValue)}`
|
||||
| IevCall(_) => `Call::${toString(aValue)}`
|
||||
| IevDistribution(_) => `Distribution::${toString(aValue)}`
|
||||
| IevLambda(_) => `Lambda::${toString(aValue)}`
|
||||
| IevNumber(_) => `Number::${toString(aValue)}`
|
||||
| IevRecord(_) => `Record::${toString(aValue)}`
|
||||
| IevString(_) => `String::${toString(aValue)}`
|
||||
| IevSymbol(_) => `Symbol::${toString(aValue)}`
|
||||
| IevDate(_) => `Date::${toString(aValue)}`
|
||||
| IevTimeDuration(_) => `Date::${toString(aValue)}`
|
||||
| IevDeclaration(_) => `Declaration::${toString(aValue)}`
|
||||
| IevTypeIdentifier(_) => `TypeIdentifier::${toString(aValue)}`
|
||||
| IevModule(_) => `Module::${toString(aValue)}`
|
||||
}
|
||||
|
||||
let argsToString = (args: array<expressionValue>): string => {
|
||||
args->Js.Array2.map(arg => arg->toString)->Js.Array2.toString
|
||||
}
|
||||
|
||||
let toStringFunctionCall = ((fn, args)): string => `${fn}(${argsToString(args)})`
|
||||
|
||||
let toStringResult = x =>
|
||||
switch x {
|
||||
| Ok(a) => `Ok(${toString(a)})`
|
||||
| Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
||||
}
|
||||
|
||||
let toStringResultOkless = (codeResult: result<expressionValue, ErrorValue.errorValue>): string =>
|
||||
switch codeResult {
|
||||
| Ok(a) => toString(a)
|
||||
| Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
||||
}
|
||||
|
||||
let toStringResultRecord = x =>
|
||||
switch x {
|
||||
| Ok(a) => `Ok(${ExternalExpressionValue.toStringRecord(a)})`
|
||||
| Error(m) => `Error(${ErrorValue.errorToString(m)})`
|
||||
}
|
||||
|
||||
type expressionValueType =
|
||||
| EvtArray
|
||||
| EvtArrayString
|
||||
| EvtBool
|
||||
| EvtCall
|
||||
| EvtDistribution
|
||||
| EvtLambda
|
||||
| EvtNumber
|
||||
| EvtRecord
|
||||
| EvtString
|
||||
| EvtSymbol
|
||||
| EvtDate
|
||||
| EvtTimeDuration
|
||||
| EvtDeclaration
|
||||
| EvtTypeIdentifier
|
||||
| EvtModule
|
||||
|
||||
type functionCallSignature = CallSignature(string, array<expressionValueType>)
|
||||
type functionDefinitionSignature =
|
||||
FunctionDefinitionSignature(functionCallSignature, expressionValueType)
|
||||
|
||||
let valueToValueType = value =>
|
||||
switch value {
|
||||
| IevArray(_) => EvtArray
|
||||
| IevArrayString(_) => EvtArrayString
|
||||
| IevBool(_) => EvtBool
|
||||
| IevCall(_) => EvtCall
|
||||
| IevDistribution(_) => EvtDistribution
|
||||
| IevLambda(_) => EvtLambda
|
||||
| IevNumber(_) => EvtNumber
|
||||
| IevRecord(_) => EvtRecord
|
||||
| IevString(_) => EvtString
|
||||
| IevSymbol(_) => EvtSymbol
|
||||
| IevDate(_) => EvtDate
|
||||
| IevTimeDuration(_) => EvtTimeDuration
|
||||
| IevDeclaration(_) => EvtDeclaration
|
||||
| IevTypeIdentifier(_) => EvtTypeIdentifier
|
||||
| IevModule(_) => EvtModule
|
||||
}
|
||||
|
||||
let functionCallToCallSignature = (functionCall: functionCall): functionCallSignature => {
|
||||
let (fn, args) = functionCall
|
||||
CallSignature(fn, args->Js.Array2.map(valueToValueType))
|
||||
}
|
||||
|
||||
let valueTypeToString = (valueType: expressionValueType): string =>
|
||||
switch valueType {
|
||||
| EvtArray => `Array`
|
||||
| EvtArrayString => `ArrayString`
|
||||
| EvtBool => `Bool`
|
||||
| EvtCall => `Call`
|
||||
| EvtDistribution => `Distribution`
|
||||
| EvtLambda => `Lambda`
|
||||
| EvtNumber => `Number`
|
||||
| EvtRecord => `Record`
|
||||
| EvtString => `String`
|
||||
| EvtSymbol => `Symbol`
|
||||
| EvtDate => `Date`
|
||||
| EvtTimeDuration => `Duration`
|
||||
| EvtDeclaration => `Declaration`
|
||||
| EvtTypeIdentifier => `TypeIdentifier`
|
||||
| EvtModule => `Module`
|
||||
}
|
||||
|
||||
let functionCallSignatureToString = (functionCallSignature: functionCallSignature): string => {
|
||||
let CallSignature(fn, args) = functionCallSignature
|
||||
`${fn}(${args->Js.Array2.map(valueTypeToString)->Js.Array2.toString})`
|
||||
}
|
||||
|
||||
let rec toExternal = (iev: expressionValue): ExternalExpressionValue.expressionValue => {
|
||||
switch iev {
|
||||
| IevArray(v) => v->Belt.Array.map(e => toExternal(e))->EvArray
|
||||
| IevArrayString(v) => EvArrayString(v)
|
||||
| IevBool(v) => EvBool(v)
|
||||
| IevCall(v) => EvCall(v)
|
||||
| IevDistribution(v) => EvDistribution(v)
|
||||
| IevLambda(v) => EvLambda(lambdaValueToExternal(v))
|
||||
| IevNumber(v) => EvNumber(v)
|
||||
| IevRecord(v) => v->mapToExternal->EvRecord
|
||||
| IevString(v) => EvString(v)
|
||||
| IevSymbol(v) => EvSymbol(v)
|
||||
| IevDate(v) => EvDate(v)
|
||||
| IevTimeDuration(v) => EvTimeDuration(v)
|
||||
| IevDeclaration(v) => {
|
||||
let fn = lambdaValueToExternal(v.fn)
|
||||
let args = v.args
|
||||
EvDeclaration({fn: fn, args: args})
|
||||
}
|
||||
| IevTypeIdentifier(v) => EvTypeIdentifier(v)
|
||||
| IevModule(v) => v->nameSpaceToTypeScriptBindings->EvModule
|
||||
}
|
||||
}
|
||||
and mapToExternal = v =>
|
||||
v->Belt.Map.String.map(e => toExternal(e))->Belt.Map.String.toArray->Js.Dict.fromArray
|
||||
and lambdaValueToExternal = v => {
|
||||
let p = v.parameters
|
||||
let c = v.context->nameSpaceToTypeScriptBindings
|
||||
let b = v.body
|
||||
{parameters: p, context: c, body: b}
|
||||
}
|
||||
and nameSpaceToTypeScriptBindings = (
|
||||
nameSpace: nameSpace,
|
||||
): ReducerInterface_ExpressionValue.externalBindings => {
|
||||
let NameSpace(container) = nameSpace
|
||||
Belt.Map.String.map(container, e => toExternal(e))->Belt.Map.String.toArray->Js.Dict.fromArray
|
||||
}
|
||||
|
||||
let rec toInternal = (ev: ExternalExpressionValue.expressionValue): expressionValue => {
|
||||
switch ev {
|
||||
| EvArray(v) => v->Belt.Array.map(e => toInternal(e))->IevArray
|
||||
| EvArrayString(v) => IevArrayString(v)
|
||||
| EvBool(v) => IevBool(v)
|
||||
| EvCall(v) => IevCall(v)
|
||||
| EvDistribution(v) => IevDistribution(v)
|
||||
| EvLambda(v) => IevLambda(lambdaValueToInternal(v))
|
||||
| EvNumber(v) => IevNumber(v)
|
||||
| EvRecord(v) => v->recordToInternal->IevRecord
|
||||
| EvString(v) => IevString(v)
|
||||
| EvSymbol(v) => IevSymbol(v)
|
||||
| EvDate(v) => IevDate(v)
|
||||
| EvTimeDuration(v) => IevTimeDuration(v)
|
||||
| EvDeclaration(v) => {
|
||||
let fn = lambdaValueToInternal(v.fn)
|
||||
let args = v.args
|
||||
IevDeclaration({fn: fn, args: args})
|
||||
}
|
||||
| EvTypeIdentifier(v) => IevTypeIdentifier(v)
|
||||
| EvModule(v) => v->nameSpaceFromTypeScriptBindings->IevModule
|
||||
}
|
||||
}
|
||||
and recordToInternal = v =>
|
||||
v->Js.Dict.entries->Belt.Map.String.fromArray->Belt.Map.String.map(e => toInternal(e))
|
||||
and lambdaValueToInternal = v => {
|
||||
let p = v.parameters
|
||||
let c = v.context->nameSpaceFromTypeScriptBindings
|
||||
let b = v.body
|
||||
{parameters: p, context: c, body: b}
|
||||
}
|
||||
and nameSpaceFromTypeScriptBindings = (
|
||||
r: ReducerInterface_ExpressionValue.externalBindings,
|
||||
): nameSpace =>
|
||||
r->Js.Dict.entries->Belt.Map.String.fromArray->Belt.Map.String.map(e => toInternal(e))->NameSpace
|
|
@ -1,4 +1,4 @@
|
|||
module EV = ReducerInterface_ExpressionValue
|
||||
module EV = ReducerInterface_InternalExpressionValue
|
||||
type expressionValue = EV.expressionValue
|
||||
|
||||
module ScientificUnit = {
|
||||
|
@ -37,9 +37,9 @@ let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
|
|||
| "fromUnit_G"
|
||||
| "fromUnit_T"
|
||||
| "fromUnit_P") as op,
|
||||
[EvNumber(f)],
|
||||
[IevNumber(f)],
|
||||
) =>
|
||||
op->ScientificUnit.getMultiplier->E.O2.fmap(multiplier => EV.EvNumber(f *. multiplier)->Ok)
|
||||
op->ScientificUnit.getMultiplier->E.O2.fmap(multiplier => EV.IevNumber(f *. multiplier)->Ok)
|
||||
| _ => None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
module Bindings = Reducer_Category_Bindings
|
||||
module Module = Reducer_Category_Module
|
||||
|
||||
let internalStdLib = Bindings.emptyBindings->SquiggleLibrary_Math.makeBindings
|
||||
let internalStdLib = Module.emptyModule->SquiggleLibrary_Math.makeBindings
|
||||
|
||||
@genType
|
||||
let externalStdLib = internalStdLib->Bindings.toRecord
|
||||
let externalStdLib = internalStdLib->Module.toTypeScriptBindings
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
module Bindings = Reducer_Category_Bindings
|
||||
module Bindings = Reducer_Category_Module
|
||||
module Module = Reducer_Category_Module
|
||||
|
||||
let m =
|
||||
Module.emptyModule->Module.defineNumber("pi", Js.Math._PI)->Module.defineNumber("e", Js.Math._E)
|
||||
|
||||
let makeBindings = (previousBindings: Bindings.t): Bindings.t =>
|
||||
let makeBindings = (previousBindings: Module.t): Module.t =>
|
||||
previousBindings->Bindings.defineModule("Math", m)
|
||||
|
|
Loading…
Reference in New Issue
Block a user