Reducer InternalExpressionValue created

this will allow complicated changes to execution without changing the typescript interface
This commit is contained in:
Umur Ozkul 2022-06-16 14:08:59 +02:00
parent 27a411e848
commit ac9a468aa6
46 changed files with 951 additions and 594 deletions

View File

@ -0,0 +1,4 @@
open Jest
open Expect
test("todo", () => expect("1")->toBe("1"))

View File

@ -19,23 +19,23 @@ describe("bindStatement", () => {
testMacro( testMacro(
[], [],
eBindStatement(eBindings([]), exampleStatementY), eBindStatement(eBindings([]), exampleStatementY),
"Ok((:$_setBindings_$ {} :y 1) context: {})", "Ok((:$_setBindings_$ @{} :y 1) context: @{})",
) )
// Then it answers the bindings for the next statement when reduced // 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 // Now let's feed a binding to see what happens
testMacro( testMacro(
[], [],
eBindStatement(eBindings([("x", EvNumber(2.))]), exampleStatementX), eBindStatement(eBindings([("x", IevNumber(2.))]), exampleStatementX),
"Ok((:$_setBindings_$ {x: 2} :y 2) context: {x: 2})", "Ok((:$_setBindings_$ @{x: 2} :y 2) context: @{x: 2})",
) )
// An expression does not return a binding, thus error // An expression does not return a binding, thus error
testMacro([], eBindStatement(eBindings([]), exampleExpression), "Assignment expected") 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 // When bindings from previous statement are missing the context is injected. This must be the first statement of a block
testMacro( testMacro(
[("z", EvNumber(99.))], [("z", IevNumber(99.))],
eBindStatementDefault(exampleStatementY), 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 // x is simply bound in the expression
testMacro( testMacro(
[], [],
eBindExpression(eBindings([("x", EvNumber(2.))]), eSymbol("x")), eBindExpression(eBindings([("x", IevNumber(2.))]), eSymbol("x")),
"Ok(2 context: {x: 2})", "Ok(2 context: @{x: 2})",
) )
// When an let statement is the end expression then bindings are returned // When an let statement is the end expression then bindings are returned
testMacro( testMacro(
[], [],
eBindExpression(eBindings([("x", EvNumber(2.))]), exampleStatementY), eBindExpression(eBindings([("x", IevNumber(2.))]), exampleStatementY),
"Ok((:$_exportBindings_$ (:$_setBindings_$ {x: 2} :y 1)) context: {x: 2})", "Ok((:$_exportBindings_$ (:$_setBindings_$ @{x: 2} :y 1)) context: @{x: 2})",
) )
// Now let's reduce that expression // Now let's reduce that expression
testMacroEval( testMacroEval(
[], [],
eBindExpression(eBindings([("x", EvNumber(2.))]), exampleStatementY), eBindExpression(eBindings([("x", IevNumber(2.))]), exampleStatementY),
"Ok({x: 2,y: 1})", "Ok(@{x: 2,y: 1})",
) )
// When bindings are missing the context is injected. This must be the first and last statement of a block // When bindings are missing the context is injected. This must be the first and last statement of a block
testMacroEval( testMacroEval(
[("z", EvNumber(99.))], [("z", IevNumber(99.))],
eBindExpressionDefault(exampleStatementY), eBindExpressionDefault(exampleStatementY),
"Ok({y: 1,z: 99})", "Ok(@{y: 1,z: 99})",
) )
}) })
@ -72,7 +72,7 @@ describe("block", () => {
testMacroEval([], eBlock(list{exampleExpression}), "Ok(1)") testMacroEval([], eBlock(list{exampleExpression}), "Ok(1)")
// Block with a single statement // Block with a single statement
testMacro([], eBlock(list{exampleStatementY}), "Ok((:$$_bindExpression_$$ (:$_let_$ :y 1)))") 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 // Block with a statement and an expression
testMacro( testMacro(
[], [],
@ -86,7 +86,7 @@ describe("block", () => {
eBlock(list{exampleStatementY, exampleStatementZ}), eBlock(list{exampleStatementY, exampleStatementZ}),
"Ok((:$$_bindExpression_$$ (:$$_bindStatement_$$ (:$_let_$ :y 1)) (:$_let_$ :z :y)))", "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 // Block inside a block
testMacro([], eBlock(list{eBlock(list{exampleExpression})}), "Ok((:$$_bindExpression_$$ {1}))") testMacro([], eBlock(list{eBlock(list{exampleExpression})}), "Ok((:$$_bindExpression_$$ {1}))")
testMacroEval([], eBlock(list{eBlock(list{exampleExpression})}), "Ok(1)") testMacroEval([], eBlock(list{eBlock(list{exampleExpression})}), "Ok(1)")
@ -99,7 +99,7 @@ describe("block", () => {
testMacroEval( testMacroEval(
[], [],
eBlock(list{eLetStatement("z", eBlock(list{eBlock(list{exampleExpressionY})}))}), eBlock(list{eLetStatement("z", eBlock(list{eBlock(list{exampleExpressionY})}))}),
"Ok({z: :y})", "Ok(@{z: :y})",
) )
// Empty block // Empty block
testMacro([], eBlock(list{}), "Ok(:undefined block)") //TODO: should be an error 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}))", "Ok((:$$_bindExpression_$$ {(:$_let_$ :y (:add :x 1)); :y}))",
) )
testMacroEval( testMacroEval(
[("x", EvNumber(1.))], [("x", IevNumber(1.))],
eBlock(list{ eBlock(list{
eBlock(list{ eBlock(list{
eLetStatement("y", eFunction("add", list{eSymbol("x"), eNumber(1.)})), eLetStatement("y", eFunction("add", list{eSymbol("x"), eNumber(1.)})),
@ -135,12 +135,12 @@ describe("lambda", () => {
testMacro([], callLambdaExpression, "Ok(((:$$_lambda_$$ [y] :y) 1))") testMacro([], callLambdaExpression, "Ok(((:$$_lambda_$$ [y] :y) 1))")
testMacroEval([], callLambdaExpression, "Ok(1)") testMacroEval([], callLambdaExpression, "Ok(1)")
// Parameters shadow the outer scope // 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 // When not shadowed by the parameters, the outer scope variables are available
let lambdaExpression = eFunction( let lambdaExpression = eFunction(
"$$_lambda_$$", "$$_lambda_$$",
list{eArrayString(["z"]), eFunction("add", list{eSymbol("y"), eSymbol("z")})}, list{eArrayString(["z"]), eFunction("add", list{eSymbol("y"), eSymbol("z")})},
) )
let callLambdaExpression = eList(list{lambdaExpression, eNumber(1.)}) let callLambdaExpression = eList(list{lambdaExpression, eNumber(1.)})
testMacroEval([("y", EvNumber(666.))], callLambdaExpression, "Ok(667)") testMacroEval([("y", IevNumber(666.))], callLambdaExpression, "Ok(667)")
}) })

View File

@ -1,4 +1,4 @@
module ExpressionValue = ReducerInterface.ExpressionValue module ExpressionValue = ReducerInterface.ExternalExpressionValue
open Jest open Jest
open Expect open Expect

View File

@ -1,19 +1,24 @@
module ExpressionT = Reducer_Expression_T // Reducer_Helpers
module ExpressionValue = ReducerInterface.ExpressionValue
module ErrorValue = Reducer_ErrorValue 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 => let removeDefaultsInternal = (iev: InternalExpressionValue.expressionValue) => {
switch ev { switch iev {
| EvRecord(extbindings) => { | InternalExpressionValue.IevModule(nameSpace) =>
let bindings: Bindings.t = Bindings.fromRecord(extbindings) Module.removeOther(
let keys = Js.Dict.keys(Reducer.defaultExternalBindings) nameSpace,
Belt.Map.String.keep(bindings, (key, _value) => { ReducerInterface.StdLib.internalStdLib,
let removeThis = Js.Array2.includes(keys, key) )->InternalExpressionValue.IevModule
!removeThis
})->Bindings.toExpressionValue
}
| value => value | 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)

View File

@ -1,4 +1,3 @@
open ReducerInterface.ExpressionValue
module MathJs = Reducer_MathJs module MathJs = Reducer_MathJs
module ErrorValue = Reducer.ErrorValue module ErrorValue = Reducer.ErrorValue
@ -6,14 +5,14 @@ open Jest
open ExpectJs open ExpectJs
describe("eval", () => { describe("eval", () => {
test("Number", () => expect(MathJs.Eval.eval("1"))->toEqual(Ok(EvNumber(1.)))) test("Number", () => expect(MathJs.Eval.eval("1"))->toEqual(Ok(IevNumber(1.))))
test("Number expr", () => expect(MathJs.Eval.eval("1-1"))->toEqual(Ok(EvNumber(0.)))) test("Number expr", () => expect(MathJs.Eval.eval("1-1"))->toEqual(Ok(IevNumber(0.))))
test("String", () => expect(MathJs.Eval.eval("'hello'"))->toEqual(Ok(EvString("hello")))) test("String", () => expect(MathJs.Eval.eval("'hello'"))->toEqual(Ok(IevString("hello"))))
test("String expr", () => 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", () => expect(MathJs.Eval.eval("true"))->toEqual(Ok(IevBool(true))))
test("Boolean expr", () => expect(MathJs.Eval.eval("2>1"))->toEqual(Ok(EvBool(true)))) test("Boolean expr", () => expect(MathJs.Eval.eval("2>1"))->toEqual(Ok(IevBool(true))))
}) })
describe("errors", () => { describe("errors", () => {

View File

@ -1,6 +1,6 @@
module Expression = Reducer_Expression module Expression = Reducer_Expression
module ExpressionT = Reducer_Expression_T module ExpressionT = Reducer_Expression_T
module ExpressionValue = ReducerInterface_ExpressionValue module ExpressionValue = ReducerInterface.InternalExpressionValue
module Parse = Reducer_Peggy_Parse module Parse = Reducer_Peggy_Parse
module Result = Belt.Result module Result = Belt.Result
module ToExpression = Reducer_Peggy_ToExpression module ToExpression = Reducer_Peggy_ToExpression
@ -29,7 +29,7 @@ let expectToExpressionToBe = (expr, answer, ~v="_", ()) => {
ExpressionValue.defaultEnvironment, ExpressionValue.defaultEnvironment,
) )
) )
->Reducer_Helpers.rRemoveDefaults ->Reducer_Helpers.rRemoveDefaultsInternal
->ExpressionValue.toStringResultOkless ->ExpressionValue.toStringResultOkless
(a1, a2)->expect->toEqual((answer, v)) (a1, a2)->expect->toEqual((answer, v))
} }

View File

@ -22,11 +22,11 @@ describe("Peggy to Expression", () => {
describe("multi-line", () => { describe("multi-line", () => {
testToExpression("x=1; 2", "{(:$_let_$ :x {1}); 2}", ~v="2", ()) 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", () => { 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", "{:x}", ~v=":x", ()) //TODO: value should return error
testToExpression("x = 1; x", "{(:$_let_$ :x {1}); :x}", ~v="1", ()) testToExpression("x = 1; x", "{(:$_let_$ :x {1}); :x}", ~v="1", ())
}) })
@ -35,7 +35,7 @@ describe("Peggy to Expression", () => {
testToExpression( testToExpression(
"identity(x) = x", "identity(x) = x",
"{(:$_let_$ :identity (:$$_lambda_$$ [x] {:x}))}", "{(:$_let_$ :identity (:$$_lambda_$$ [x] {:x}))}",
~v="{identity: lambda(x=>internal code)}", ~v="@{identity: lambda(x=>internal code)}",
(), (),
) // Function definitions become lambda assignments ) // Function definitions become lambda assignments
testToExpression("identity(x)", "{(:identity :x)}", ()) // Note value returns error properly testToExpression("identity(x)", "{(:identity :x)}", ()) // Note value returns error properly
@ -155,7 +155,7 @@ describe("Peggy to Expression", () => {
testToExpression( testToExpression(
"y=99; x={y=1; y}", "y=99; x={y=1; y}",
"{(:$_let_$ :y {99}); (:$_let_$ :x {(:$_let_$ :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( testToExpression(
"f={|x| x}", "f={|x| x}",
"{(:$_let_$ :f {(:$$_lambda_$$ [x] {:x})})}", "{(:$_let_$ :f {(:$$_lambda_$$ [x] {:x})})}",
~v="{f: lambda(x=>internal code)}", ~v="@{f: lambda(x=>internal code)}",
(), (),
) )
testToExpression( testToExpression(
"f(x)=x", "f(x)=x",
"{(:$_let_$ :f (:$$_lambda_$$ [x] {:x}))}", "{(:$_let_$ :f (:$$_lambda_$$ [x] {:x}))}",
~v="{f: lambda(x=>internal code)}", ~v="@{f: lambda(x=>internal code)}",
(), (),
) // Function definitions are lambda assignments ) // Function definitions are lambda assignments
testToExpression( testToExpression(
"f(x)=x ? 1 : 0", "f(x)=x ? 1 : 0",
"{(:$_let_$ :f (:$$_lambda_$$ [x] {(:$$_ternary_$$ :x 1 0)}))}", "{(:$_let_$ :f (:$$_lambda_$$ [x] {(:$$_ternary_$$ :x 1 0)}))}",
~v="{f: lambda(x=>internal code)}", ~v="@{f: lambda(x=>internal code)}",
(), (),
) )
}) })

View File

@ -6,7 +6,7 @@ describe("Peggy Types to Expression", () => {
testToExpression( testToExpression(
"p: number", "p: number",
"{(:$_typeOf_$ :p #number)}", "{(:$_typeOf_$ :p #number)}",
~v="{_typeReferences_: {p: #number}}", ~v="@{_typeReferences_: {p: #number}}",
(), (),
) )
}) })
@ -14,7 +14,7 @@ describe("Peggy Types to Expression", () => {
testToExpression( testToExpression(
"type index=number", "type index=number",
"{(:$_typeAlias_$ #index #number)}", "{(:$_typeAlias_$ #index #number)}",
~v="{_typeAliases_: {index: #number}}", ~v="@{_typeAliases_: {index: #number}}",
(), (),
) )
}) })
@ -22,7 +22,7 @@ describe("Peggy Types to Expression", () => {
testToExpression( testToExpression(
"answer: number|string|distribution", "answer: number|string|distribution",
"{(:$_typeOf_$ :answer (:$_typeOr_$ (:$_constructArray_$ (#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( testToExpression(
"f: number=>number=>number", "f: number=>number=>number",
"{(:$_typeOf_$ :f (:$_typeFunction_$ (:$_constructArray_$ (#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( testToExpression(
"f: number=>number", "f: number=>number",
"{(:$_typeOf_$ :f (:$_typeFunction_$ (:$_constructArray_$ (#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( testToExpression(
"answer: number<-min(1)<-max(100)|string", "answer: number<-min(1)<-max(100)|string",
"{(:$_typeOf_$ :answer (:$_typeOr_$ (:$_constructArray_$ ((:$_typeModifier_max_$ (:$_typeModifier_min_$ #number 1) 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( testToExpression(
"answer: number<-memberOf([1,3,5])", "answer: number<-memberOf([1,3,5])",
"{(:$_typeOf_$ :answer (:$_typeModifier_memberOf_$ #number (:$_constructArray_$ (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( testToExpression(
"answer: number<-min(1)", "answer: number<-min(1)",
"{(:$_typeOf_$ :answer (:$_typeModifier_min_$ #number 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( testToExpression(
"answer: number<-max(10)", "answer: number<-max(10)",
"{(:$_typeOf_$ :answer (:$_typeModifier_max_$ #number 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( testToExpression(
"answer: number<-min(1)<-max(10)", "answer: number<-min(1)<-max(10)",
"{(:$_typeOf_$ :answer (:$_typeModifier_max_$ (:$_typeModifier_min_$ #number 1) 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( testToExpression(
"answer: number<-max(10)<-min(1)", "answer: number<-max(10)<-min(1)",
"{(:$_typeOf_$ :answer (:$_typeModifier_min_$ (:$_typeModifier_max_$ #number 10) 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( testToExpression(
"answer: number | string $ opaque", "answer: number | string $ opaque",
"{(:$_typeOf_$ :answer (:$_typeModifier_opaque_$ (:$_typeOr_$ (:$_constructArray_$ (#number #string)))))}", "{(:$_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( testToExpression(
"odds1 = [1,3,5]; odds2 = [7, 9]; type odds = number<-memberOf(concat(odds1, odds2))", "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)))}", "{(:$_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]}",
(), (),
) )
}) })

View File

@ -1,7 +1,6 @@
module ExpressionT = Reducer_Expression_T module ExpressionT = Reducer_Expression_T
module ExpressionValue = ReducerInterface.ExpressionValue module ExternalExpressionValue = ReducerInterface.ExternalExpressionValue
module ErrorValue = Reducer_ErrorValue module ErrorValue = Reducer_ErrorValue
module Bindings = Reducer_Category_Bindings
open Jest open Jest
open Expect open Expect
@ -9,7 +8,7 @@ open Expect
let unwrapRecord = rValue => let unwrapRecord = rValue =>
rValue->Belt.Result.flatMap(value => rValue->Belt.Result.flatMap(value =>
switch value { switch value {
| ExpressionValue.EvRecord(aRecord) => Ok(aRecord) | ExternalExpressionValue.EvRecord(aRecord) => Ok(aRecord)
| _ => ErrorValue.RETodo("TODO: External bindings must be returned")->Error | _ => 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) => let expectEvalToBe = (expr: string, answer: string) =>
Reducer.evaluate(expr) Reducer.evaluate(expr)
->Reducer_Helpers.rRemoveDefaults ->Reducer_Helpers.rRemoveDefaultsExternal
->ExpressionValue.toStringResult ->ExternalExpressionValue.toStringResult
->expect ->expect
->toBe(answer) ->toBe(answer)
let expectEvalError = (expr: string) => 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) => let expectEvalBindingsToBe = (expr: string, bindings: Reducer.externalBindings, answer: string) =>
Reducer.evaluateUsingOptions(expr, ~externalBindings=Some(bindings), ~environment=None) Reducer.evaluateUsingOptions(expr, ~externalBindings=Some(bindings), ~environment=None)
->Reducer_Helpers.rRemoveDefaults ->Reducer_Helpers.rRemoveDefaultsExternal
->ExpressionValue.toStringResult ->ExternalExpressionValue.toStringResult
->expect ->expect
->toBe(answer) ->toBe(answer)

View File

@ -1,25 +1,27 @@
open Jest open Jest
open Expect open Expect
module Bindings = Reducer_Expression_Bindings module BindingsReplacer = Reducer_Expression_BindingsReplacer
module Expression = Reducer_Expression module Expression = Reducer_Expression
module ExpressionValue = ReducerInterface_ExpressionValue // module ExpressionValue = ReducerInterface.ExpressionValue
module InternalExpressionValue = ReducerInterface.InternalExpressionValue
module ExpressionWithContext = Reducer_ExpressionWithContext module ExpressionWithContext = Reducer_ExpressionWithContext
module Macro = Reducer_Expression_Macro module Macro = Reducer_Expression_Macro
module T = Reducer_Expression_T module T = Reducer_Expression_T
module Module = Reducer_Category_Module
let testMacro_ = ( let testMacro_ = (
tester, tester,
bindArray: array<(string, ExpressionValue.expressionValue)>, bindArray: array<(string, InternalExpressionValue.expressionValue)>,
expr: T.expression, expr: T.expression,
expectedCode: string, expectedCode: string,
) => { ) => {
let bindings = Belt.Map.String.fromArray(bindArray) let bindings = Module.fromArray(bindArray)
tester(expr->T.toString, () => tester(expr->T.toString, () =>
expr expr
->Macro.expandMacroCall( ->Macro.expandMacroCall(
bindings, bindings,
ExpressionValue.defaultEnvironment, InternalExpressionValue.defaultEnvironment,
Expression.reduceExpression, Expression.reduceExpression,
) )
->ExpressionWithContext.toStringResult ->ExpressionWithContext.toStringResult
@ -30,39 +32,43 @@ let testMacro_ = (
let testMacroEval_ = ( let testMacroEval_ = (
tester, tester,
bindArray: array<(string, ExpressionValue.expressionValue)>, bindArray: array<(string, InternalExpressionValue.expressionValue)>,
expr: T.expression, expr: T.expression,
expectedValue: string, expectedValue: string,
) => { ) => {
let bindings = Belt.Map.String.fromArray(bindArray) let bindings = Module.fromArray(bindArray)
tester(expr->T.toString, () => tester(expr->T.toString, () =>
expr expr
->Macro.doMacroCall(bindings, ExpressionValue.defaultEnvironment, Expression.reduceExpression) ->Macro.doMacroCall(
->ExpressionValue.toStringResult bindings,
InternalExpressionValue.defaultEnvironment,
Expression.reduceExpression,
)
->InternalExpressionValue.toStringResult
->expect ->expect
->toEqual(expectedValue) ->toEqual(expectedValue)
) )
} }
let testMacro = ( let testMacro = (
bindArray: array<(string, ExpressionValue.expressionValue)>, bindArray: array<(string, InternalExpressionValue.expressionValue)>,
expr: T.expression, expr: T.expression,
expectedExpr: string, expectedExpr: string,
) => testMacro_(test, bindArray, expr, expectedExpr) ) => testMacro_(test, bindArray, expr, expectedExpr)
let testMacroEval = ( let testMacroEval = (
bindArray: array<(string, ExpressionValue.expressionValue)>, bindArray: array<(string, InternalExpressionValue.expressionValue)>,
expr: T.expression, expr: T.expression,
expectedValue: string, expectedValue: string,
) => testMacroEval_(test, bindArray, expr, expectedValue) ) => testMacroEval_(test, bindArray, expr, expectedValue)
module MySkip = { module MySkip = {
let testMacro = ( let testMacro = (
bindArray: array<(string, ExpressionValue.expressionValue)>, bindArray: array<(string, InternalExpressionValue.expressionValue)>,
expr: T.expression, expr: T.expression,
expectedExpr: string, expectedExpr: string,
) => testMacro_(Skip.test, bindArray, expr, expectedExpr) ) => testMacro_(Skip.test, bindArray, expr, expectedExpr)
let testMacroEval = ( let testMacroEval = (
bindArray: array<(string, ExpressionValue.expressionValue)>, bindArray: array<(string, InternalExpressionValue.expressionValue)>,
expr: T.expression, expr: T.expression,
expectedValue: string, expectedValue: string,
) => testMacroEval_(Skip.test, bindArray, expr, expectedValue) ) => testMacroEval_(Skip.test, bindArray, expr, expectedValue)
@ -70,12 +76,12 @@ module MySkip = {
module MyOnly = { module MyOnly = {
let testMacro = ( let testMacro = (
bindArray: array<(string, ExpressionValue.expressionValue)>, bindArray: array<(string, InternalExpressionValue.expressionValue)>,
expr: T.expression, expr: T.expression,
expectedExpr: string, expectedExpr: string,
) => testMacro_(Only.test, bindArray, expr, expectedExpr) ) => testMacro_(Only.test, bindArray, expr, expectedExpr)
let testMacroEval = ( let testMacroEval = (
bindArray: array<(string, ExpressionValue.expressionValue)>, bindArray: array<(string, InternalExpressionValue.expressionValue)>,
expr: T.expression, expr: T.expression,
expectedValue: string, expectedValue: string,
) => testMacroEval_(Only.test, bindArray, expr, expectedValue) ) => testMacroEval_(Only.test, bindArray, expr, expectedValue)

View File

@ -1,11 +1,14 @@
// TODO: Reimplement with usual parse
open Jest open Jest
open Reducer_TestHelpers open Reducer_TestHelpers
describe("Eval with Bindings", () => { describe("Eval with Bindings", () => {
testEvalBindingsToBe("x", list{("x", ExpressionValue.EvNumber(1.))}, "Ok(1)") testEvalBindingsToBe("x", list{("x", ExternalExpressionValue.EvNumber(1.))}, "Ok(1)")
testEvalBindingsToBe("x+1", list{("x", ExpressionValue.EvNumber(1.))}, "Ok(2)") testEvalBindingsToBe("x+1", list{("x", ExternalExpressionValue.EvNumber(1.))}, "Ok(2)")
testParseToBe("y = x+1; y", "Ok({(:$_let_$ :y {(:add :x 1)}); :y})") 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; y", list{("x", ExternalExpressionValue.EvNumber(1.))}, "Ok(2)")
testEvalBindingsToBe("y = x+1", list{("x", ExpressionValue.EvNumber(1.))}, "Ok({x: 1,y: 2})") testEvalBindingsToBe(
"y = x+1",
list{("x", ExternalExpressionValue.EvNumber(1.))},
"Ok(@{x: 1,y: 2})",
)
}) })

View File

@ -39,15 +39,15 @@ describe("symbol not defined", () => {
}) })
describe("call and bindings", () => { 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(x)=x+1; f(1)", "Ok(2)")
testEvalToBe("f=1;y=2", "Ok({f: 1,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)", "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); 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( testEvalToBe(
"f(x)=x+1; g(x)=f(x)+1", "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( testParseToBe(
"f=99; g(x)=f; g(2)", "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; g(x)=f(x); g(2)", "Ok(2)")
testEvalToBe( testEvalToBe(
"f(x)=x+1; g(x)=f(x)+1; y=g(2)", "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)") 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", () => { describe("function tricks", () => {
testEvalError("f(x)=f(y)=2; f(2)") //Error because chain assignment is not allowed 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)=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); 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 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))") 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", () => { describe("lambda in structures", () => {
testEvalToBe( testEvalToBe(
"myadd(x,y)=x+y; z=[myadd]", "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]", "Ok(lambda(x,y=>internal code))")
testEvalToBe("myadd(x,y)=x+y; z=[myadd]; z[0](3,2)", "Ok(5)") testEvalToBe("myadd(x,y)=x+y; z=[myadd]; z[0](3,2)", "Ok(5)")

View File

@ -39,7 +39,7 @@ describe("eval", () => {
testEvalToBe("x=1; y=x+1; y+1", "Ok(3)") testEvalToBe("x=1; y=x+1; y+1", "Ok(3)")
testEvalError("1; x=1") testEvalError("1; x=1")
testEvalError("1; 1") testEvalError("1; 1")
testEvalToBe("x=1; x=1", "Ok({x: 1})") testEvalToBe("x=1; x=1", "Ok(@{x: 1})")
}) })
}) })

View File

@ -1,4 +1,4 @@
open ReducerInterface.ExpressionValue open ReducerInterface.ExternalExpressionValue
open Jest open Jest
open Expect open Expect

View File

@ -5,6 +5,7 @@
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"peggy": "peggy --cache", "peggy": "peggy --cache",
"rescript": "rescript",
"build": "yarn build:peggy && yarn build:rescript && yarn build:typescript", "build": "yarn build:peggy && yarn build:rescript && yarn build:typescript",
"build:peggy": "find . -type f -name *.peggy -exec yarn peggy {} \\;", "build:peggy": "find . -type f -name *.peggy -exec yarn peggy {} \\;",
"build:rescript": "rescript build -with-deps", "build:rescript": "rescript build -with-deps",

View File

@ -1,3 +1,4 @@
@@warning("-27") //TODO: Remove and fix the warning
open Distributions open Distributions
type t = PointSetTypes.discreteShape type t = PointSetTypes.discreteShape

View File

@ -1,3 +1,5 @@
@@warning("-27") //TODO: Remove and fix the warning
@@warning("-32") //TODO: Remove and fix the warning
open Distributions open Distributions
type t = PointSetTypes.mixedShape type t = PointSetTypes.mixedShape

View File

@ -1,4 +1,4 @@
type expressionValue = ReducerInterface_ExpressionValue.expressionValue type expressionValue = ReducerInterface_InternalExpressionValue.expressionValue
/* /*
Function Registry "Type". A type, without any other information. Function Registry "Type". A type, without any other information.
@ -28,7 +28,7 @@ type rec frValue =
| FRValueArray(array<frValue>) | FRValueArray(array<frValue>)
| FRValueDistOrNumber(frValueDistOrNumber) | FRValueDistOrNumber(frValueDistOrNumber)
| FRValueRecord(frValueRecord) | FRValueRecord(frValueRecord)
| FRValueLambda(ReducerInterface_ExpressionValue.lambdaValue) | FRValueLambda(ReducerInterface_InternalExpressionValue.lambdaValue)
| FRValueString(string) | FRValueString(string)
| FRValueVariant(string) | FRValueVariant(string)
| FRValueAny(frValue) | FRValueAny(frValue)
@ -75,14 +75,14 @@ module FRType = {
let rec toFrValue = (r: expressionValue): option<frValue> => let rec toFrValue = (r: expressionValue): option<frValue> =>
switch r { switch r {
| EvNumber(f) => Some(FRValueNumber(f)) | IevNumber(f) => Some(FRValueNumber(f))
| EvString(f) => Some(FRValueString(f)) | IevString(f) => Some(FRValueString(f))
| EvDistribution(f) => Some(FRValueDistOrNumber(FRValueDist(f))) | IevDistribution(f) => Some(FRValueDistOrNumber(FRValueDist(f)))
| EvLambda(f) => Some(FRValueLambda(f)) | IevLambda(f) => Some(FRValueLambda(f))
| EvArray(elements) => | IevArray(elements) =>
elements->E.A2.fmap(toFrValue)->E.A.O.openIfAllSome->E.O2.fmap(r => FRValueArray(r)) elements->E.A2.fmap(toFrValue)->E.A.O.openIfAllSome->E.O2.fmap(r => FRValueArray(r))
| EvRecord(record) => | IevRecord(map) =>
Js.Dict.entries(record) Belt.Map.String.toArray(map)
->E.A2.fmap(((key, item)) => item->toFrValue->E.O2.fmap(o => (key, o))) ->E.A2.fmap(((key, item)) => item->toFrValue->E.O2.fmap(o => (key, o)))
->E.A.O.openIfAllSome ->E.A.O.openIfAllSome
->E.O2.fmap(r => FRValueRecord(r)) ->E.O2.fmap(r => FRValueRecord(r))
@ -92,28 +92,28 @@ module FRType = {
let rec matchWithExpressionValue = (t: t, r: expressionValue): option<frValue> => let rec matchWithExpressionValue = (t: t, r: expressionValue): option<frValue> =>
switch (t, r) { switch (t, r) {
| (FRTypeAny, f) => toFrValue(f) | (FRTypeAny, f) => toFrValue(f)
| (FRTypeString, EvString(f)) => Some(FRValueString(f)) | (FRTypeString, IevString(f)) => Some(FRValueString(f))
| (FRTypeNumber, EvNumber(f)) => Some(FRValueNumber(f)) | (FRTypeNumber, IevNumber(f)) => Some(FRValueNumber(f))
| (FRTypeDistOrNumber, EvNumber(f)) => Some(FRValueDistOrNumber(FRValueNumber(f))) | (FRTypeDistOrNumber, IevNumber(f)) => Some(FRValueDistOrNumber(FRValueNumber(f)))
| (FRTypeDistOrNumber, EvDistribution(Symbolic(#Float(f)))) => | (FRTypeDistOrNumber, IevDistribution(Symbolic(#Float(f)))) =>
Some(FRValueDistOrNumber(FRValueNumber(f))) Some(FRValueDistOrNumber(FRValueNumber(f)))
| (FRTypeDistOrNumber, EvDistribution(f)) => Some(FRValueDistOrNumber(FRValueDist(f))) | (FRTypeDistOrNumber, IevDistribution(f)) => Some(FRValueDistOrNumber(FRValueDist(f)))
| (FRTypeNumeric, EvNumber(f)) => Some(FRValueNumber(f)) | (FRTypeNumeric, IevNumber(f)) => Some(FRValueNumber(f))
| (FRTypeNumeric, EvDistribution(Symbolic(#Float(f)))) => Some(FRValueNumber(f)) | (FRTypeNumeric, IevDistribution(Symbolic(#Float(f)))) => Some(FRValueNumber(f))
| (FRTypeLambda, EvLambda(f)) => Some(FRValueLambda(f)) | (FRTypeLambda, IevLambda(f)) => Some(FRValueLambda(f))
| (FRTypeArray(intendedType), EvArray(elements)) => { | (FRTypeArray(intendedType), IevArray(elements)) => {
let el = elements->E.A2.fmap(matchWithExpressionValue(intendedType)) let el = elements->E.A2.fmap(matchWithExpressionValue(intendedType))
E.A.O.openIfAllSome(el)->E.O2.fmap(r => FRValueArray(r)) E.A.O.openIfAllSome(el)->E.O2.fmap(r => FRValueArray(r))
} }
| (FRTypeDict(r), EvRecord(record)) => | (FRTypeDict(r), IevRecord(map)) =>
record map
->Js.Dict.entries ->Belt.Map.String.toArray
->E.A2.fmap(((key, item)) => matchWithExpressionValue(r, item)->E.O2.fmap(o => (key, o))) ->E.A2.fmap(((key, item)) => matchWithExpressionValue(r, item)->E.O2.fmap(o => (key, o)))
->E.A.O.openIfAllSome ->E.A.O.openIfAllSome
->E.O2.fmap(r => FRValueDict(Js.Dict.fromArray(r))) ->E.O2.fmap(r => FRValueDict(Js.Dict.fromArray(r)))
| (FRTypeRecord(recordParams), EvRecord(record)) => { | (FRTypeRecord(recordParams), IevRecord(map)) => {
let getAndMatch = (name, input) => 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 //All names in the type must be present. If any are missing, the corresponding
//value will be None, and this function would return None. //value will be None, and this function would return None.
let namesAndValues: array<option<(Js.Dict.key, frValue)>> = let namesAndValues: array<option<(Js.Dict.key, frValue)>> =
@ -127,27 +127,29 @@ module FRType = {
let rec matchReverse = (e: frValue): expressionValue => let rec matchReverse = (e: frValue): expressionValue =>
switch e { switch e {
| FRValueNumber(f) => EvNumber(f) | FRValueNumber(f) => IevNumber(f)
| FRValueDistOrNumber(FRValueNumber(n)) => EvNumber(n) | FRValueDistOrNumber(FRValueNumber(n)) => IevNumber(n)
| FRValueDistOrNumber(FRValueDist(n)) => EvDistribution(n) | FRValueDistOrNumber(FRValueDist(n)) => IevDistribution(n)
| FRValueDist(dist) => EvDistribution(dist) | FRValueDist(dist) => IevDistribution(dist)
| FRValueArray(elements) => EvArray(elements->E.A2.fmap(matchReverse)) | FRValueArray(elements) => IevArray(elements->E.A2.fmap(matchReverse))
| FRValueRecord(frValueRecord) => { | FRValueRecord(frValueRecord) => {
let record = let map =
frValueRecord->E.A2.fmap(((name, value)) => (name, matchReverse(value)))->E.Dict.fromArray frValueRecord
EvRecord(record) ->E.A2.fmap(((name, value)) => (name, matchReverse(value)))
->Belt.Map.String.fromArray
IevRecord(map)
} }
| FRValueDict(frValueRecord) => { | FRValueDict(frValueRecord) => {
let record = let map =
frValueRecord frValueRecord
->Js.Dict.entries ->Js.Dict.entries
->E.A2.fmap(((name, value)) => (name, matchReverse(value))) ->E.A2.fmap(((name, value)) => (name, matchReverse(value)))
->E.Dict.fromArray ->Belt.Map.String.fromArray
EvRecord(record) IevRecord(map)
} }
| FRValueLambda(l) => EvLambda(l) | FRValueLambda(l) => IevLambda(l)
| FRValueString(string) => EvString(string) | FRValueString(string) => IevString(string)
| FRValueVariant(string) => EvString(string) | FRValueVariant(string) => IevString(string)
| FRValueAny(f) => matchReverse(f) | FRValueAny(f) => matchReverse(f)
} }

View File

@ -4,11 +4,11 @@ let impossibleError = "Wrong inputs / Logically impossible"
module Wrappers = { module Wrappers = {
let symbolic = r => DistributionTypes.Symbolic(r) let symbolic = r => DistributionTypes.Symbolic(r)
let evDistribution = r => ReducerInterface_ExpressionValue.EvDistribution(r) let evDistribution = r => ReducerInterface_InternalExpressionValue.IevDistribution(r)
let evNumber = r => ReducerInterface_ExpressionValue.EvNumber(r) let evNumber = r => ReducerInterface_InternalExpressionValue.IevNumber(r)
let evArray = r => ReducerInterface_ExpressionValue.EvArray(r) let evArray = r => ReducerInterface_InternalExpressionValue.IevArray(r)
let evRecord = r => ReducerInterface_ExpressionValue.EvRecord(r) let evRecord = r => ReducerInterface_InternalExpressionValue.IevRecord(r)
let evString = r => ReducerInterface_ExpressionValue.EvString(r) let evString = r => ReducerInterface_InternalExpressionValue.IevString(r)
let symbolicEvDistribution = r => r->DistributionTypes.Symbolic->evDistribution let symbolicEvDistribution = r => r->DistributionTypes.Symbolic->evDistribution
} }

View File

@ -20,7 +20,7 @@ module Declaration = {
inputs inputs
->E.A2.fmap(getMinMax) ->E.A2.fmap(getMinMax)
->E.A.R.firstErrorOrOpen ->E.A.R.firstErrorOrOpen
->E.R2.fmap(args => ReducerInterface_ExpressionValue.EvDeclaration( ->E.R2.fmap(args => ReducerInterface_InternalExpressionValue.IevDeclaration(
Declaration.make(lambda, args), Declaration.make(lambda, args),
)) ))
} }
@ -43,7 +43,9 @@ let inputsTodist = (inputs: array<FunctionRegistry_Core.frValue>, makeDist) => {
let expressionValue = let expressionValue =
xyCoords xyCoords
->E.R.bind(r => r->XYShape.T.makeFromZipped->E.R2.errMap(XYShape.Error.toString)) ->E.R.bind(r => r->XYShape.T.makeFromZipped->E.R2.errMap(XYShape.Error.toString))
->E.R2.fmap(r => ReducerInterface_ExpressionValue.EvDistribution(PointSet(makeDist(r)))) ->E.R2.fmap(r => ReducerInterface_InternalExpressionValue.IevDistribution(
PointSet(makeDist(r)),
))
expressionValue expressionValue
} }
@ -369,7 +371,7 @@ to(5,10)
E.Dict.concat(d1, d2) |> Js.Dict.map((. r) => E.Dict.concat(d1, d2) |> Js.Dict.map((. r) =>
FunctionRegistry_Core.FRType.matchReverse(r) FunctionRegistry_Core.FRType.matchReverse(r)
) )
newDict->Wrappers.evRecord->Ok newDict->Js.Dict.entries->Belt.Map.String.fromArray->Wrappers.evRecord->Ok
} }
| _ => Error(impossibleError) | _ => Error(impossibleError)
} }
@ -390,6 +392,7 @@ to(5,10)
->Prepare.ToTypedArray.dicts ->Prepare.ToTypedArray.dicts
->E.R2.fmap(E.Dict.concatMany) ->E.R2.fmap(E.Dict.concatMany)
->E.R2.fmap(Js.Dict.map((. r) => FunctionRegistry_Core.FRType.matchReverse(r))) ->E.R2.fmap(Js.Dict.map((. r) => FunctionRegistry_Core.FRType.matchReverse(r)))
->E.R2.fmap(r => r->Js.Dict.entries->Belt.Map.String.fromArray)
->E.R2.fmap(Wrappers.evRecord) ->E.R2.fmap(Wrappers.evRecord)
), ),
], ],
@ -462,7 +465,7 @@ to(5,10)
} }
}) })
->E.A.R.firstErrorOrOpen ->E.A.R.firstErrorOrOpen
->E.R2.fmap(Js.Dict.fromArray) ->E.R2.fmap(Belt.Map.String.fromArray)
->E.R2.fmap(Wrappers.evRecord) ->E.R2.fmap(Wrappers.evRecord)
inputs->getOrError(0)->E.R.bind(Prepare.ToValueArray.Array.arrayOfArrays) inputs->getOrError(0)->E.R.bind(Prepare.ToValueArray.Array.arrayOfArrays)
|> E.R2.bind(convertInternalItems) |> E.R2.bind(convertInternalItems)

View File

@ -1,13 +1,14 @@
module ErrorValue = Reducer_ErrorValue module ErrorValue = Reducer_ErrorValue
module Expression = Reducer_Expression module Expression = Reducer_Expression
module ExpressionValue = ReducerInterface_ExpressionValue module ExternalExpressionValue = ReducerInterface_ExpressionValue
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
module Lambda = Reducer_Expression_Lambda module Lambda = Reducer_Expression_Lambda
type environment = ReducerInterface_ExpressionValue.environment type environment = ReducerInterface_InternalExpressionValue.environment
type errorValue = Reducer_ErrorValue.errorValue type errorValue = Reducer_ErrorValue.errorValue
type expressionValue = ReducerInterface_ExpressionValue.expressionValue type expressionValue = ExternalExpressionValue.expressionValue
type externalBindings = ReducerInterface_ExpressionValue.externalBindings type externalBindings = ReducerInterface_ExpressionValue.externalBindings
type lambdaValue = ExpressionValue.lambdaValue type lambdaValue = ExternalExpressionValue.lambdaValue
let evaluate = Expression.evaluate let evaluate = Expression.evaluate
let evaluateUsingOptions = Expression.evaluateUsingOptions let evaluateUsingOptions = Expression.evaluateUsingOptions
@ -15,13 +16,20 @@ let evaluatePartialUsingExternalBindings = Expression.evaluatePartialUsingExtern
let parse = Expression.parse let parse = Expression.parse
let foreignFunctionInterface = ( let foreignFunctionInterface = (
lambdaValue: lambdaValue, lambdaValue: ExternalExpressionValue.lambdaValue,
argArray: array<expressionValue>, 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 let defaultExternalBindings = ReducerInterface_StdLib.externalStdLib

View File

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

View File

@ -1,33 +1,112 @@
module ExpressionT = Reducer_Expression_T module ExpressionT = Reducer_Expression_T
open ReducerInterface_ExpressionValue open ReducerInterface_InternalExpressionValue
let expressionValueToString = toString let expressionValueToString = toString
type t = ExpressionT.bindings type t = ReducerInterface_InternalExpressionValue.nameSpace
let typeAliasesKey = "_typeAliases_" let typeAliasesKey = "_typeAliases_"
let typeReferencesKey = "_typeReferences_" 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 getTypeOf = (nameSpace: t, id: string) => {
let fromRecord = (r: record): t => Js.Dict.entries(r)->Belt.Map.String.fromArray let NameSpace(container) = nameSpace
let toRecord = (container: t): record => Belt.Map.String.toArray(container)->Js.Dict.fromArray 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 => let fromExpressionValue = (aValue: expressionValue): t =>
switch aValue { switch aValue {
| EvModule(r) => fromRecord(r) | IevModule(nameSpace) => nameSpace
| _ => emptyModule | _ => 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 // -- Module definition
let define = (container: t, identifier: string, ev: expressionValue): t => let define = (nameSpace: t, identifier: string, ev: expressionValue): t => {
Belt.Map.String.set(container, identifier, ev) // TODO build lambda for polymorphic functions here 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 => let defineModule = (nameSpace: t, identifier: string, value: t): t =>
container->define(identifier, EvNumber(value)) nameSpace->define(identifier, toExpressionValue(value))
let defineModule = (container: t, identifier: string, value: t): t =>
container->define(identifier, toExpressionValue(value))

View File

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

View File

@ -1,10 +1,11 @@
module Bindings = Reducer_Expression_Bindings module BindingsReplacer = Reducer_Expression_BindingsReplacer
module ExpressionT = Reducer_Expression_T module ExpressionT = Reducer_Expression_T
module ExternalLibrary = ReducerInterface.ExternalLibrary module ExternalLibrary = ReducerInterface.ExternalLibrary
module Lambda = Reducer_Expression_Lambda module Lambda = Reducer_Expression_Lambda
module MathJs = Reducer_MathJs module MathJs = Reducer_MathJs
module Module = Reducer_Category_Module
module Result = Belt.Result module Result = Belt.Result
open ReducerInterface.ExpressionValue open ReducerInterface_InternalExpressionValue
open Reducer_ErrorValue open Reducer_ErrorValue
/* /*
@ -31,12 +32,12 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
let constructRecord = arrayOfPairs => { let constructRecord = arrayOfPairs => {
Belt.Array.map(arrayOfPairs, pairValue => Belt.Array.map(arrayOfPairs, pairValue =>
switch pairValue { switch pairValue {
| EvArray([EvString(key), valueValue]) => (key, valueValue) | IevArray([IevString(key), valueValue]) => (key, valueValue)
| _ => ("wrong key type", pairValue->toStringWithType->EvString) | _ => ("wrong key type", pairValue->toStringWithType->IevString)
} }
) )
->Js.Dict.fromArray ->Belt.Map.String.fromArray
->EvRecord ->IevRecord
->Ok ->Ok
} }
@ -46,8 +47,14 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
| None => REArrayIndexNotFound("Array index not found", Belt.Int.fromFloat(fIndex))->Error | None => REArrayIndexNotFound("Array index not found", Belt.Int.fromFloat(fIndex))->Error
} }
let recordAtIndex = (dict: Js.Dict.t<expressionValue>, sIndex) => let moduleAtIndex = (nameSpace: nameSpace, sIndex) =>
switch Js.Dict.get(dict, 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 | Some(value) => value->Ok
| None => RERecordPropertyNotFound("Record property not found", sIndex)->Error | 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 doAddArray = (originalA, b) => {
let a = originalA->Js.Array2.copy let a = originalA->Js.Array2.copy
let _ = Js.Array2.pushMany(a, b) let _ = Js.Array2.pushMany(a, b)
a->EvArray->Ok a->IevArray->Ok
} }
let doAddString = (a, b) => { let doAddString = (a, b) => {
let answer = Js.String2.concat(a, b) let answer = Js.String2.concat(a, b)
answer->EvString->Ok answer->IevString->Ok
} }
let inspect = (value: expressionValue) => { let inspect = (value: expressionValue) => {
@ -72,53 +79,17 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
value->Ok value->Ok
} }
let doSetBindings = ( let doSetBindings = (bindings: nameSpace, symbol: string, value: expressionValue) => {
externalBindings: externalBindings, Module.set(bindings, symbol, value)->IevModule->Ok
symbol: string,
value: expressionValue,
) => {
Bindings.fromExternalBindings(externalBindings)
->Belt.Map.String.set(symbol, value)
->Bindings.toExternalBindings
->EvRecord
->Ok
} }
let doSetBindingsInNamespace = ( let doSetTypeAliasBindings = (bindings: nameSpace, symbol: string, value: expressionValue) =>
externalBindings: externalBindings, Module.setTypeAlias(bindings, symbol, value)->IevModule->Ok
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 = ( let doSetTypeOfBindings = (bindings: nameSpace, symbol: string, value: expressionValue) =>
externalBindings: externalBindings, Module.setTypeOf(bindings, symbol, value)->IevModule->Ok
symbol: string,
value: expressionValue,
) => doSetBindingsInNamespace(externalBindings, symbol, value, Bindings.typeAliasesKey)
let doSetTypeOfBindings = ( let doExportBindings = (bindings: nameSpace) => bindings->Module.toExpressionValue->Ok
externalBindings: externalBindings,
symbol: string,
value: expressionValue,
) => doSetBindingsInNamespace(externalBindings, symbol, value, Bindings.typeReferencesKey)
let doExportBindings = (externalBindings: externalBindings) => EvRecord(externalBindings)->Ok
let doKeepArray = (aValueArray, aLambdaValue) => { let doKeepArray = (aValueArray, aLambdaValue) => {
let rMappedList = aValueArray->Belt.Array.reduceReverse(Ok(list{}), (rAcc, elem) => 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) let rNewElem = Lambda.doLambdaCall(aLambdaValue, list{elem}, environment, reducer)
rNewElem->Result.map(newElem => rNewElem->Result.map(newElem =>
switch newElem { switch newElem {
| EvBool(true) => list{elem, ...acc} | IevBool(true) => list{elem, ...acc}
| _ => acc | _ => acc
} }
) )
}) })
) )
rMappedList->Result.map(mappedList => mappedList->Belt.List.toArray->EvArray) rMappedList->Result.map(mappedList => mappedList->Belt.List.toArray->IevArray)
} }
let doMapArray = (aValueArray, aLambdaValue) => { let doMapArray = (aValueArray, aLambdaValue) => {
@ -142,35 +113,36 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
rNewElem->Result.map(newElem => list{newElem, ...acc}) 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 = { module SampleMap = {
type t = SampleSetDist.t type t = SampleSetDist.t
let doLambdaCall = (aLambdaValue, list) => let doLambdaCall = (aLambdaValue, list) =>
switch Lambda.doLambdaCall(aLambdaValue, list, environment, reducer) { switch Lambda.doLambdaCall(aLambdaValue, list, environment, reducer) {
| Ok(EvNumber(f)) => Ok(f) | Ok(IevNumber(f)) => Ok(f)
| _ => Error(Operation.SampleMapNeedsNtoNFunction) | _ => Error(Operation.SampleMapNeedsNtoNFunction)
} }
let toType = r => let toType = r =>
switch r { switch r {
| Ok(r) => Ok(EvDistribution(SampleSet(r))) | Ok(r) => Ok(IevDistribution(SampleSet(r)))
| Error(r) => Error(REDistributionError(SampleSetError(r))) | Error(r) => Error(REDistributionError(SampleSetError(r)))
} }
let map1 = (sampleSetDist: t, aLambdaValue) => { 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)) toType(SampleSetDist.samplesMap(~fn, sampleSetDist))
} }
let map2 = (t1: t, t2: t, aLambdaValue) => { 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 SampleSetDist.map2(~fn, ~t1, ~t2)->toType
} }
let map3 = (t1: t, t2: t, t3: t, aLambdaValue) => { 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 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 typeModifier_memberOf = (aType, anArray) => {
let newRecord = Js.Dict.fromArray([ let newRecord = Belt.Map.String.fromArray([
("typeTag", EvString("typeIdentifier")), ("typeTag", IevString("typeIdentifier")),
("typeIdentifier", aType), ("typeIdentifier", aType),
]) ])
newRecord->Js.Dict.set("memberOf", anArray) newRecord->Belt.Map.String.set("memberOf", anArray)->IevRecord->Ok
newRecord->EvRecord->Ok
} }
let typeModifier_memberOf_update = (aRecord, anArray) => { let typeModifier_memberOf_update = (aRecord, anArray) => {
let newRecord = aRecord->Js.Dict.entries->Js.Dict.fromArray aRecord->Belt.Map.String.set("memberOf", anArray)->IevRecord->Ok
newRecord->Js.Dict.set("memberOf", anArray)
newRecord->EvRecord->Ok
} }
let typeModifier_min = (aType, value) => { let typeModifier_min = (aType, value) => {
let newRecord = Js.Dict.fromArray([ let newRecord = Belt.Map.String.fromArray([
("typeTag", EvString("typeIdentifier")), ("typeTag", IevString("typeIdentifier")),
("typeIdentifier", aType), ("typeIdentifier", aType),
]) ])
newRecord->Js.Dict.set("min", value) newRecord->Belt.Map.String.set("min", value)->IevRecord->Ok
newRecord->EvRecord->Ok
} }
let typeModifier_min_update = (aRecord, value) => { let typeModifier_min_update = (aRecord, value) => {
let newRecord = aRecord->Js.Dict.entries->Js.Dict.fromArray aRecord->Belt.Map.String.set("min", value)->IevRecord->Ok
newRecord->Js.Dict.set("min", value)
newRecord->EvRecord->Ok
} }
let typeModifier_max = (aType, value) => { let typeModifier_max = (aType, value) => {
let newRecord = Js.Dict.fromArray([ let newRecord = Belt.Map.String.fromArray([
("typeTag", EvString("typeIdentifier")), ("typeTag", IevString("typeIdentifier")),
("typeIdentifier", aType), ("typeIdentifier", aType),
]) ])
newRecord->Js.Dict.set("max", value) newRecord->Belt.Map.String.set("max", value)->IevRecord->Ok
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
} }
let typeModifier_max_update = (aRecord, value) =>
aRecord->Belt.Map.String.set("max", value)->IevRecord->Ok
let typeModifier_opaque_update = aRecord => { let typeModifier_opaque_update = aRecord =>
let newRecord = aRecord->Js.Dict.entries->Js.Dict.fromArray aRecord->Belt.Map.String.set("opaque", IevBool(true))->IevRecord->Ok
newRecord->Js.Dict.set("opaque", EvBool(true))
newRecord->EvRecord->Ok
}
let typeOr = evArray => { let typeOr = evArray => {
let newRecord = Js.Dict.fromArray([("typeTag", EvString("typeOr")), ("typeOr", evArray)]) let newRecord = Belt.Map.String.fromArray([
newRecord->EvRecord->Ok ("typeTag", IevString("typeOr")),
("typeOr", evArray),
])
newRecord->IevRecord->Ok
} }
let typeFunction = anArray => { let typeFunction = anArray => {
let output = Belt.Array.getUnsafe(anArray, Js.Array2.length(anArray) - 1) let output = Belt.Array.getUnsafe(anArray, Js.Array2.length(anArray) - 1)
let inputs = Js.Array2.slice(anArray, ~start=0, ~end_=-1) let inputs = Js.Array2.slice(anArray, ~start=0, ~end_=-1)
let newRecord = Js.Dict.fromArray([ let newRecord = Belt.Map.String.fromArray([
("typeTag", EvString("typeFunction")), ("typeTag", IevString("typeFunction")),
("inputs", EvArray(inputs)), ("inputs", IevArray(inputs)),
("output", output), ("output", output),
]) ])
newRecord->EvRecord->Ok newRecord->IevRecord->Ok
} }
switch call { switch call {
| ("$_atIndex_$", [EvArray(aValueArray), EvNumber(fIndex)]) => arrayAtIndex(aValueArray, fIndex) | ("$_atIndex_$", [IevArray(aValueArray), IevNumber(fIndex)]) => arrayAtIndex(aValueArray, fIndex)
| ("$_atIndex_$", [EvModule(dict), EvString(sIndex)]) => recordAtIndex(dict, sIndex) | ("$_atIndex_$", [IevModule(dict), IevString(sIndex)]) => moduleAtIndex(dict, sIndex)
| ("$_atIndex_$", [EvRecord(dict), EvString(sIndex)]) => recordAtIndex(dict, sIndex) | ("$_atIndex_$", [IevRecord(dict), IevString(sIndex)]) => recordAtIndex(dict, sIndex)
| ("$_constructArray_$", [EvArray(aValueArray)]) => EvArray(aValueArray)->Ok | ("$_constructArray_$", [IevArray(aValueArray)]) => IevArray(aValueArray)->Ok
| ("$_constructRecord_$", [EvArray(arrayOfPairs)]) => constructRecord(arrayOfPairs) | ("$_constructRecord_$", [IevArray(arrayOfPairs)]) => constructRecord(arrayOfPairs)
| ("$_exportBindings_$", [EvRecord(externalBindings)]) => doExportBindings(externalBindings) | ("$_exportBindings_$", [IevModule(nameSpace)]) => doExportBindings(nameSpace)
| ("$_setBindings_$", [EvRecord(externalBindings), EvSymbol(symbol), value]) => | ("$_setBindings_$", [IevModule(nameSpace), IevSymbol(symbol), value]) =>
doSetBindings(externalBindings, symbol, value) doSetBindings(nameSpace, symbol, value)
| ("$_setTypeAliasBindings_$", [EvRecord(externalBindings), EvTypeIdentifier(symbol), value]) => | ("$_setTypeAliasBindings_$", [IevModule(nameSpace), IevTypeIdentifier(symbol), value]) =>
doSetTypeAliasBindings(externalBindings, symbol, value) doSetTypeAliasBindings(nameSpace, symbol, value)
| ("$_setTypeOfBindings_$", [EvRecord(externalBindings), EvSymbol(symbol), value]) => | ("$_setTypeOfBindings_$", [IevModule(nameSpace), IevSymbol(symbol), value]) =>
doSetTypeOfBindings(externalBindings, symbol, value) doSetTypeOfBindings(nameSpace, symbol, value)
| ("$_typeModifier_memberOf_$", [EvTypeIdentifier(typeIdentifier), EvArray(arr)]) => | ("$_typeModifier_memberOf_$", [IevTypeIdentifier(typeIdentifier), IevArray(arr)]) =>
typeModifier_memberOf(EvTypeIdentifier(typeIdentifier), EvArray(arr)) typeModifier_memberOf(IevTypeIdentifier(typeIdentifier), IevArray(arr))
| ("$_typeModifier_memberOf_$", [EvRecord(typeRecord), EvArray(arr)]) => | ("$_typeModifier_memberOf_$", [IevRecord(typeRecord), IevArray(arr)]) =>
typeModifier_memberOf_update(typeRecord, EvArray(arr)) typeModifier_memberOf_update(typeRecord, IevArray(arr))
| ("$_typeModifier_min_$", [EvTypeIdentifier(typeIdentifier), value]) => | ("$_typeModifier_min_$", [IevTypeIdentifier(typeIdentifier), value]) =>
typeModifier_min(EvTypeIdentifier(typeIdentifier), value) typeModifier_min(IevTypeIdentifier(typeIdentifier), value)
| ("$_typeModifier_min_$", [EvRecord(typeRecord), value]) => | ("$_typeModifier_min_$", [IevRecord(typeRecord), value]) =>
typeModifier_min_update(typeRecord, value) typeModifier_min_update(typeRecord, value)
| ("$_typeModifier_max_$", [EvTypeIdentifier(typeIdentifier), value]) => | ("$_typeModifier_max_$", [IevTypeIdentifier(typeIdentifier), value]) =>
typeModifier_max(EvTypeIdentifier(typeIdentifier), value) typeModifier_max(IevTypeIdentifier(typeIdentifier), value)
| ("$_typeModifier_max_$", [EvRecord(typeRecord), value]) => | ("$_typeModifier_max_$", [IevRecord(typeRecord), value]) =>
typeModifier_max_update(typeRecord, value) typeModifier_max_update(typeRecord, value)
| ("$_typeModifier_opaque_$", [EvRecord(typeRecord)]) => typeModifier_opaque_update(typeRecord) | ("$_typeModifier_opaque_$", [IevRecord(typeRecord)]) => typeModifier_opaque_update(typeRecord)
| ("$_typeOr_$", [EvArray(arr)]) => typeOr(EvArray(arr)) | ("$_typeOr_$", [IevArray(arr)]) => typeOr(IevArray(arr))
| ("$_typeFunction_$", [EvArray(arr)]) => typeFunction(arr) | ("$_typeFunction_$", [IevArray(arr)]) => typeFunction(arr)
| ("concat", [EvArray(aValueArray), EvArray(bValueArray)]) => doAddArray(aValueArray, bValueArray) | ("concat", [IevArray(aValueArray), IevArray(bValueArray)]) =>
| ("concat", [EvString(aValueString), EvString(bValueString)]) => doAddArray(aValueArray, bValueArray)
| ("concat", [IevString(aValueString), IevString(bValueString)]) =>
doAddString(aValueString, bValueString) doAddString(aValueString, bValueString)
| ("inspect", [value, EvString(label)]) => inspectLabel(value, label) | ("inspect", [value, IevString(label)]) => inspectLabel(value, label)
| ("inspect", [value]) => inspect(value) | ("inspect", [value]) => inspect(value)
| ("filter", [EvArray(aValueArray), EvLambda(aLambdaValue)]) => | ("filter", [IevArray(aValueArray), IevLambda(aLambdaValue)]) =>
doKeepArray(aValueArray, aLambdaValue) doKeepArray(aValueArray, aLambdaValue)
| ("map", [EvArray(aValueArray), EvLambda(aLambdaValue)]) => doMapArray(aValueArray, aLambdaValue) | ("map", [IevArray(aValueArray), IevLambda(aLambdaValue)]) =>
| ("mapSamples", [EvDistribution(SampleSet(dist)), EvLambda(aLambdaValue)]) => doMapArray(aValueArray, aLambdaValue)
| ("mapSamples", [IevDistribution(SampleSet(dist)), IevLambda(aLambdaValue)]) =>
SampleMap.map1(dist, aLambdaValue) SampleMap.map1(dist, aLambdaValue)
| ( | (
"mapSamples2", "mapSamples2",
[EvDistribution(SampleSet(dist1)), EvDistribution(SampleSet(dist2)), EvLambda(aLambdaValue)], [
IevDistribution(SampleSet(dist1)),
IevDistribution(SampleSet(dist2)),
IevLambda(aLambdaValue),
],
) => ) =>
SampleMap.map2(dist1, dist2, aLambdaValue) SampleMap.map2(dist1, dist2, aLambdaValue)
| ( | (
"mapSamples3", "mapSamples3",
[ [
EvDistribution(SampleSet(dist1)), IevDistribution(SampleSet(dist1)),
EvDistribution(SampleSet(dist2)), IevDistribution(SampleSet(dist2)),
EvDistribution(SampleSet(dist3)), IevDistribution(SampleSet(dist3)),
EvLambda(aLambdaValue), IevLambda(aLambdaValue),
], ],
) => ) =>
SampleMap.map3(dist1, dist2, dist3, aLambdaValue) SampleMap.map3(dist1, dist2, dist3, aLambdaValue)
| ("reduce", [EvArray(aValueArray), initialValue, EvLambda(aLambdaValue)]) => | ("reduce", [IevArray(aValueArray), initialValue, IevLambda(aLambdaValue)]) =>
doReduceArray(aValueArray, initialValue, aLambdaValue) doReduceArray(aValueArray, initialValue, aLambdaValue)
| ("reduceReverse", [EvArray(aValueArray), initialValue, EvLambda(aLambdaValue)]) => | ("reduceReverse", [IevArray(aValueArray), initialValue, IevLambda(aLambdaValue)]) =>
doReduceReverseArray(aValueArray, initialValue, aLambdaValue) doReduceReverseArray(aValueArray, initialValue, aLambdaValue)
| ("reverse", [EvArray(aValueArray)]) => aValueArray->Belt.Array.reverse->EvArray->Ok | ("reverse", [IevArray(aValueArray)]) => aValueArray->Belt.Array.reverse->IevArray->Ok
| (_, [EvBool(_)]) | (_, [IevBool(_)])
| (_, [EvNumber(_)]) | (_, [IevNumber(_)])
| (_, [EvString(_)]) | (_, [IevString(_)])
| (_, [EvBool(_), EvBool(_)]) | (_, [IevBool(_), IevBool(_)])
| (_, [EvNumber(_), EvNumber(_)]) | (_, [IevNumber(_), IevNumber(_)])
| (_, [EvString(_), EvString(_)]) => | (_, [IevString(_), IevString(_)]) =>
callMathJs(call) callMathJs(call)
| call => | call =>
Error(REFunctionNotFound(call->functionCallToCallSignature->functionCallSignatureToString)) // Report full type signature as error Error(REFunctionNotFound(call->functionCallToCallSignature->functionCallSignatureToString)) // Report full type signature as error

View File

@ -3,12 +3,13 @@
they take expressions as parameters and return a new expression. they take expressions as parameters and return a new expression.
Macros are used to define language building blocks. They are like Lisp macros. 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 ErrorValue = Reducer_ErrorValue
module ExpressionBuilder = Reducer_Expression_ExpressionBuilder module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
module ExpressionT = Reducer_Expression_T module ExpressionT = Reducer_Expression_T
module ExpressionValue = ReducerInterface.ExpressionValue module ExpressionValue = ReducerInterface_InternalExpressionValue
module ExpressionWithContext = Reducer_ExpressionWithContext module ExpressionWithContext = Reducer_ExpressionWithContext
module Module = Reducer_Category_Module
module Result = Belt.Result module Result = Belt.Result
open Reducer_Expression_ExpressionBuilder open Reducer_Expression_ExpressionBuilder
@ -27,13 +28,13 @@ let dispatchMacroCall = (
let useExpressionToSetBindings = (bindingExpr: expression, environment, statement, newCode) => { let useExpressionToSetBindings = (bindingExpr: expression, environment, statement, newCode) => {
let rExternalBindingsValue = reduceExpression(bindingExpr, bindings, environment) let rExternalBindingsValue = reduceExpression(bindingExpr, bindings, environment)
rExternalBindingsValue->Result.flatMap(externalBindingsValue => { rExternalBindingsValue->Result.flatMap(nameSpaceValue => {
let newBindings = Bindings.fromValue(externalBindingsValue) let newBindings = Module.fromExpressionValue(nameSpaceValue)
let rNewStatement = Bindings.replaceSymbols(newBindings, statement) let rNewStatement = BindingsReplacer.replaceSymbols(newBindings, statement)
rNewStatement->Result.map(boundStatement => rNewStatement->Result.map(boundStatement =>
ExpressionWithContext.withContext( ExpressionWithContext.withContext(
newCode(newBindings->Bindings.toExternalBindings->eRecord, boundStatement), newCode(newBindings->eModule, boundStatement),
newBindings, newBindings,
) )
) )
@ -51,7 +52,7 @@ let dispatchMacroCall = (
let doBindStatement = (bindingExpr: expression, statement: expression, environment) => { let doBindStatement = (bindingExpr: expression, statement: expression, environment) => {
let defaultStatement = ErrorValue.REAssignmentExpected->Error let defaultStatement = ErrorValue.REAssignmentExpected->Error
switch statement { switch statement {
| ExpressionT.EList(list{ExpressionT.EValue(EvCall(callName)), symbolExpr, statement}) => { | ExpressionT.EList(list{ExpressionT.EValue(IevCall(callName)), symbolExpr, statement}) => {
let setBindingsFn = correspondingSetBindingsFn(callName) let setBindingsFn = correspondingSetBindingsFn(callName)
if setBindingsFn !== "" { if setBindingsFn !== "" {
useExpressionToSetBindings(bindingExpr, environment, statement, ( useExpressionToSetBindings(bindingExpr, environment, statement, (
@ -77,7 +78,7 @@ let dispatchMacroCall = (
) => boundStatement) ) => boundStatement)
switch statement { switch statement {
| ExpressionT.EList(list{ExpressionT.EValue(EvCall(callName)), symbolExpr, statement}) => { | ExpressionT.EList(list{ExpressionT.EValue(IevCall(callName)), symbolExpr, statement}) => {
let setBindingsFn = correspondingSetBindingsFn(callName) let setBindingsFn = correspondingSetBindingsFn(callName)
if setBindingsFn !== "" { if setBindingsFn !== "" {
useExpressionToSetBindings(bindingExpr, environment, statement, ( useExpressionToSetBindings(bindingExpr, environment, statement, (
@ -123,10 +124,7 @@ let dispatchMacroCall = (
bindings: ExpressionT.bindings, bindings: ExpressionT.bindings,
parameters: array<string>, parameters: array<string>,
lambdaDefinition: ExpressionT.expression, lambdaDefinition: ExpressionT.expression,
) => ) => ExpressionWithContext.noContext(eLambda(parameters, bindings, lambdaDefinition))->Ok
ExpressionWithContext.noContext(
eLambda(parameters, bindings->Bindings.toExternalBindings, lambdaDefinition),
)->Ok
let doTernary = ( let doTernary = (
condition: expression, condition: expression,
@ -139,11 +137,11 @@ let dispatchMacroCall = (
let rCondition = reduceExpression(blockCondition, bindings, environment) let rCondition = reduceExpression(blockCondition, bindings, environment)
rCondition->Result.flatMap(conditionValue => rCondition->Result.flatMap(conditionValue =>
switch conditionValue { switch conditionValue {
| ExpressionValue.EvBool(false) => { | ExpressionValue.IevBool(false) => {
let ifFalseBlock = eBlock(list{ifFalse}) let ifFalseBlock = eBlock(list{ifFalse})
ExpressionWithContext.withContext(ifFalseBlock, bindings)->Ok ExpressionWithContext.withContext(ifFalseBlock, bindings)->Ok
} }
| ExpressionValue.EvBool(true) => { | ExpressionValue.IevBool(true) => {
let ifTrueBlock = eBlock(list{ifTrue}) let ifTrueBlock = eBlock(list{ifTrue})
ExpressionWithContext.withContext(ifTrueBlock, bindings)->Ok ExpressionWithContext.withContext(ifTrueBlock, bindings)->Ok
} }
@ -158,32 +156,32 @@ let dispatchMacroCall = (
> => > =>
switch aList { switch aList {
| list{ | list{
ExpressionT.EValue(EvCall("$$_bindStatement_$$")), ExpressionT.EValue(IevCall("$$_bindStatement_$$")),
bindingExpr: ExpressionT.expression, bindingExpr: ExpressionT.expression,
statement, statement,
} => } =>
doBindStatement(bindingExpr, statement, environment) 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 // 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{ | list{
ExpressionT.EValue(EvCall("$$_bindExpression_$$")), ExpressionT.EValue(IevCall("$$_bindExpression_$$")),
bindingExpr: ExpressionT.expression, bindingExpr: ExpressionT.expression,
expression, expression,
} => } =>
doBindExpression(bindingExpr, expression, environment) 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 // bindings of the context are used when there is no binding expression
doBindExpression(eRecord(Bindings.toExternalBindings(bindings)), expression, environment) doBindExpression(eModule(bindings), expression, environment)
| list{ExpressionT.EValue(EvCall("$$_block_$$")), ...exprs} => | list{ExpressionT.EValue(IevCall("$$_block_$$")), ...exprs} =>
doBlock(exprs, bindings, environment) doBlock(exprs, bindings, environment)
| list{ | list{
ExpressionT.EValue(EvCall("$$_lambda_$$")), ExpressionT.EValue(IevCall("$$_lambda_$$")),
ExpressionT.EValue(EvArrayString(parameters)), ExpressionT.EValue(IevArrayString(parameters)),
lambdaDefinition, lambdaDefinition,
} => } =>
doLambdaDefinition(bindings, 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) doTernary(condition, ifTrue, ifFalse, bindings, environment)
| _ => ExpressionWithContext.noContext(ExpressionT.EList(aList))->Ok | _ => ExpressionWithContext.noContext(ExpressionT.EList(aList))->Ok
} }

View File

@ -1,20 +1,21 @@
module Bindings = Reducer_Expression_Bindings module BindingsReplacer = Reducer_Expression_BindingsReplacer
module BuiltIn = Reducer_Dispatch_BuiltIn module BuiltIn = Reducer_Dispatch_BuiltIn
module ExpressionBuilder = Reducer_Expression_ExpressionBuilder module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
module ExpressionValue = ReducerInterface.ExpressionValue
module Extra = Reducer_Extra module Extra = Reducer_Extra
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
module Lambda = Reducer_Expression_Lambda module Lambda = Reducer_Expression_Lambda
module Macro = Reducer_Expression_Macro module Macro = Reducer_Expression_Macro
module MathJs = Reducer_MathJs module MathJs = Reducer_MathJs
module Module = Reducer_Category_Module
module Result = Belt.Result module Result = Belt.Result
module T = Reducer_Expression_T module T = Reducer_Expression_T
type environment = ReducerInterface_ExpressionValue.environment type environment = InternalExpressionValue.environment
type errorValue = Reducer_ErrorValue.errorValue type errorValue = Reducer_ErrorValue.errorValue
type expression = T.expression type expression = T.expression
type expressionValue = ReducerInterface_ExpressionValue.expressionValue type expressionValue = InternalExpressionValue.expressionValue
type externalBindings = ReducerInterface_ExpressionValue.externalBindings type externalExpressionValue = ReducerInterface_ExpressionValue.expressionValue
type internalCode = ReducerInterface_ExpressionValue.internalCode type tmpExternalBindings = InternalExpressionValue.tmpExternalBindings
type t = expression type t = expression
/* /*
@ -35,7 +36,7 @@ let rec reduceExpression = (expression: t, bindings: T.bindings, environment: en
| T.EValue(value) => value->Ok | T.EValue(value) => value->Ok
| T.EList(list) => | T.EList(list) =>
switch list { switch list {
| list{EValue(EvCall(fName)), ..._args} => | list{EValue(IevCall(fName)), ..._args} =>
switch Macro.isMacroName(fName) { switch Macro.isMacroName(fName) {
// A macro expands then reduces itself // A macro expands then reduces itself
| true => Macro.doMacroCall(expression, bindings, environment, reduceExpression) | true => Macro.doMacroCall(expression, bindings, environment, reduceExpression)
@ -74,7 +75,7 @@ and reduceValueList = (valueList: list<expressionValue>, environment): result<
'e, 'e,
> => > =>
switch valueList { switch valueList {
| list{EvCall(fName), ...args} => { | list{IevCall(fName), ...args} => {
let rCheckedArgs = switch fName { let rCheckedArgs = switch fName {
| "$_setBindings_$" | "$_setTypeOfBindings_$" | "$_setTypeAliasBindings_$" => args->Ok | "$_setBindings_$" | "$_setTypeOfBindings_$" | "$_setTypeAliasBindings_$" => args->Ok
| _ => args->Lambda.checkIfReduced | _ => args->Lambda.checkIfReduced
@ -84,14 +85,14 @@ and reduceValueList = (valueList: list<expressionValue>, environment): result<
(fName, checkedArgs->Belt.List.toArray)->BuiltIn.dispatch(environment, reduceExpression) (fName, checkedArgs->Belt.List.toArray)->BuiltIn.dispatch(environment, reduceExpression)
) )
} }
| list{EvLambda(_)} => | list{IevLambda(_)} =>
// TODO: remove on solving issue#558 // TODO: remove on solving issue#558
valueList valueList
->Lambda.checkIfReduced ->Lambda.checkIfReduced
->Result.flatMap(reducedValueList => ->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 args
->Lambda.checkIfReduced ->Lambda.checkIfReduced
->Result.flatMap(checkedArgs => ->Result.flatMap(checkedArgs =>
@ -102,7 +103,7 @@ and reduceValueList = (valueList: list<expressionValue>, environment): result<
valueList valueList
->Lambda.checkIfReduced ->Lambda.checkIfReduced
->Result.flatMap(reducedValueList => ->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>, ~environment: option<ReducerInterface_ExpressionValue.environment>,
~externalBindings: option<ReducerInterface_ExpressionValue.externalBindings>, ~externalBindings: option<ReducerInterface_ExpressionValue.externalBindings>,
code: string, code: string,
): result<expressionValue, errorValue> => { ): result<externalExpressionValue, errorValue> => {
let anEnvironment = Belt.Option.getWithDefault( let anEnvironment = Belt.Option.getWithDefault(
environment, environment,
ReducerInterface_ExpressionValue.defaultEnvironment, ReducerInterface_ExpressionValue.defaultEnvironment,
) )
let anExternalBindings = switch externalBindings { let mergedBindings: InternalExpressionValue.nameSpace = Module.merge(
| Some(bindings) => { ReducerInterface_StdLib.internalStdLib,
let cloneLib = ReducerInterface_StdLib.externalStdLib->Reducer_Category_Bindings.cloneRecord Belt.Option.map(externalBindings, Module.fromTypeScriptBindings)->Belt.Option.getWithDefault(
Js.Dict.entries(bindings)->Js.Array2.reduce((acc, (key, value)) => { Module.emptyModule,
acc->Js.Dict.set(key, value) ),
acc )
}, cloneLib)
}
| None => ReducerInterface_StdLib.externalStdLib
}
let bindings = anExternalBindings->Bindings.fromExternalBindings parse(code)
->Result.flatMap(expr => evalUsingBindingsExpression_(expr, mergedBindings, anEnvironment))
parse(code)->Result.flatMap(expr => evalUsingBindingsExpression_(expr, bindings, 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) evaluateUsingOptions(~environment=None, ~externalBindings=None, code)
} }
let eval = evaluate
let evaluatePartialUsingExternalBindings = ( let evaluatePartialUsingExternalBindings = (
code: string, code: string,
externalBindings: ReducerInterface_ExpressionValue.externalBindings, externalBindings: ReducerInterface_ExpressionValue.externalBindings,
environment: ReducerInterface_ExpressionValue.environment, environment: ReducerInterface_ExpressionValue.environment,
): result<externalBindings, errorValue> => { ): result<ReducerInterface_ExpressionValue.externalBindings, errorValue> => {
let rAnswer = evaluateUsingOptions( let rAnswer = evaluateUsingOptions(
~environment=Some(environment), ~environment=Some(environment),
~externalBindings=Some(externalBindings), ~externalBindings=Some(externalBindings),

View File

@ -1,8 +1,9 @@
module Bindings = Reducer_Expression_Bindings module BindingsReplacer = Reducer_Expression_BindingsReplacer
module ErrorValue = Reducer_ErrorValue module ErrorValue = Reducer_ErrorValue
module ExpressionT = Reducer_Expression_T module ExpressionT = Reducer_Expression_T
module ExpressionValue = ReducerInterface.ExpressionValue module ExpressionValue = ReducerInterface_InternalExpressionValue
module Result = Belt.Result module Result = Belt.Result
module Module = Reducer_Category_Module
type bindings = ExpressionT.bindings type bindings = ExpressionT.bindings
type context = bindings type context = bindings
@ -10,7 +11,6 @@ type environment = ExpressionValue.environment
type errorValue = Reducer_ErrorValue.errorValue type errorValue = Reducer_ErrorValue.errorValue
type expression = ExpressionT.expression type expression = ExpressionT.expression
type expressionValue = ExpressionValue.expressionValue type expressionValue = ExpressionValue.expressionValue
type externalBindings = ReducerInterface_ExpressionValue.externalBindings
type reducerFn = ExpressionT.reducerFn type reducerFn = ExpressionT.reducerFn
type expressionWithContext = type expressionWithContext =
@ -40,7 +40,9 @@ let toString = expressionWithContext =>
switch expressionWithContext { switch expressionWithContext {
| ExpressionNoContext(expr) => ExpressionT.toString(expr) | ExpressionNoContext(expr) => ExpressionT.toString(expr)
| ExpressionWithContext(expr, context) => | ExpressionWithContext(expr, context) =>
`${ExpressionT.toString(expr)} context: ${Bindings.toString(context)}` `${ExpressionT.toString(expr)} context: ${context
->Module.toExpressionValue
->ExpressionValue.toString}`
} }
let toStringResult = rExpressionWithContext => let toStringResult = rExpressionWithContext =>

View File

@ -1,27 +1,15 @@
module ErrorValue = Reducer_ErrorValue module ErrorValue = Reducer_ErrorValue
module ExpressionT = Reducer_Expression_T module ExpressionT = Reducer_Expression_T
module ExpressionValue = ReducerInterface.ExpressionValue module ExpressionValue = ReducerInterface_InternalExpressionValue
module Result = Belt.Result module Result = Belt.Result
module Bindings = Reducer_Category_Bindings module Module = Reducer_Category_Module
type errorValue = Reducer_ErrorValue.errorValue type errorValue = Reducer_ErrorValue.errorValue
type expression = ExpressionT.expression type expression = ExpressionT.expression
type expressionValue = ExpressionValue.expressionValue type expressionValue = ExpressionValue.expressionValue
type tmpExternalBindings = ReducerInterface_InternalExpressionValue.tmpExternalBindings
type externalBindings = ReducerInterface_ExpressionValue.externalBindings 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 isMacroName = (fName: string): bool => fName->Js.String2.startsWith("$$")
let rec replaceSymbols = (bindings: ExpressionT.bindings, expression: expression): result< 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) replaceSymbolOnValue(bindings, value)->Result.map(evValue => evValue->ExpressionT.EValue)
| ExpressionT.EList(list) => | ExpressionT.EList(list) =>
switch list { switch list {
| list{EValue(EvCall(fName)), ..._args} => | list{EValue(IevCall(fName)), ..._args} =>
switch isMacroName(fName) { switch isMacroName(fName) {
// A macro reduces itself so we dont dive in it // A macro reduces itself so we dont dive in it
| true => expression->Ok | true => expression->Ok
@ -55,18 +43,12 @@ and replaceSymbolsOnExpressionList = (bindings, list) => {
} }
and replaceSymbolOnValue = (bindings, evValue: expressionValue) => and replaceSymbolOnValue = (bindings, evValue: expressionValue) =>
switch evValue { switch evValue {
| EvSymbol(symbol) => Belt.Map.String.getWithDefault(bindings, symbol, evValue)->Ok | IevSymbol(symbol) => Module.getWithDefault(bindings, symbol, evValue)->Ok
| EvCall(symbol) => Belt.Map.String.getWithDefault(bindings, symbol, evValue)->checkIfCallable | IevCall(symbol) => Module.getWithDefault(bindings, symbol, evValue)->checkIfCallable
| _ => evValue->Ok | _ => evValue->Ok
} }
and checkIfCallable = (evValue: expressionValue) => and checkIfCallable = (evValue: expressionValue) =>
switch evValue { switch evValue {
| EvCall(_) | EvLambda(_) => evValue->Ok | IevCall(_) | IevLambda(_) => evValue->Ok
| _ => ErrorValue.RENotAFunction(ExpressionValue.toString(evValue))->Error | _ => 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

View File

@ -1,24 +1,27 @@
module BBindings = Reducer_Expression_Bindings module BBindingsReplacer = Reducer_Expression_BindingsReplacer
module BErrorValue = Reducer_ErrorValue module BErrorValue = Reducer_ErrorValue
module BExpressionT = Reducer_Expression_T module BExpressionT = Reducer_Expression_T
module BExpressionValue = ReducerInterface.ExpressionValue module BExpressionValue = ReducerInterface_InternalExpressionValue
module BModule = Reducer_Category_Module
type errorValue = BErrorValue.errorValue type errorValue = BErrorValue.errorValue
type expression = BExpressionT.expression 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)>) => 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 eFunction = (fName: string, lispArgs: list<expression>): expression => {
let fn = fName->eCall let fn = fName->eCall
@ -27,29 +30,40 @@ let eFunction = (fName: string, lispArgs: list<expression>): expression => {
let eLambda = ( let eLambda = (
parameters: array<string>, parameters: array<string>,
context: BExpressionValue.externalBindings, context: BExpressionValue.nameSpace,
expr: expression, expr: expression,
) => { ) => {
// Js.log(`eLambda context ${BBindings.externalBindingsToString(context)}`) BExpressionValue.IevLambda({
BExpressionValue.EvLambda({
parameters: parameters, parameters: parameters,
context: context, context: context,
body: expr->castExpressionToInternalCode, body: NotFFI(expr)->castExpressionToInternalCode,
})->BExpressionT.EValue })->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 eList = (list: list<expression>): expression => list->BExpressionT.EList
let eBlock = (exprs: list<expression>): expression => eFunction("$$_block_$$", exprs) 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 => let eLetStatement = (symbol: string, valueExpression: expression): expression =>
eFunction("$_let_$", list{eSymbol(symbol), valueExpression}) eFunction("$_let_$", list{eSymbol(symbol), valueExpression})
@ -65,7 +79,8 @@ let eBindExpression = (bindingExpr: expression, expression: expression): express
let eBindExpressionDefault = (expression: expression): expression => let eBindExpressionDefault = (expression: expression): expression =>
eFunction("$$_bindExpression_$$", list{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 => let eTypeIdentifier = (name: string): expression =>
name->BExpressionValue.EvTypeIdentifier->BExpressionT.EValue name->BExpressionValue.IevTypeIdentifier->BExpressionT.EValue

View File

@ -1,17 +1,19 @@
module Bindings = Reducer_Expression_Bindings module BindingsReplacer = Reducer_Expression_BindingsReplacer
module ErrorValue = Reducer_ErrorValue module ErrorValue = Reducer_ErrorValue
module ExpressionBuilder = Reducer_Expression_ExpressionBuilder module ExpressionBuilder = Reducer_Expression_ExpressionBuilder
module ExpressionT = Reducer_Expression_T module ExpressionT = Reducer_Expression_T
module ExpressionValue = ReducerInterface.ExpressionValue module ExpressionValue = ReducerInterface_InternalExpressionValue
module Module = Reducer_Category_Module
module Result = Belt.Result module Result = Belt.Result
type environment = ReducerInterface_ExpressionValue.environment type environment = ReducerInterface_InternalExpressionValue.environment
type expression = ExpressionT.expression type expression = ExpressionT.expression
type expressionValue = ReducerInterface_ExpressionValue.expressionValue type expressionOrFFI = ExpressionT.expressionOrFFI
type externalBindings = ReducerInterface_ExpressionValue.externalBindings type expressionValue = ReducerInterface_InternalExpressionValue.expressionValue
type internalCode = ReducerInterface_ExpressionValue.internalCode // 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 checkArity = (lambdaValue: ExpressionValue.lambdaValue, args: list<expressionValue>) => {
let argsLength = Belt.List.length(args) let argsLength = Belt.List.length(args)
@ -27,12 +29,27 @@ let checkIfReduced = (args: list<expressionValue>) =>
args->Belt.List.reduceReverse(Ok(list{}), (rAcc, arg) => args->Belt.List.reduceReverse(Ok(list{}), (rAcc, arg) =>
rAcc->Result.flatMap(acc => rAcc->Result.flatMap(acc =>
switch arg { switch arg {
| EvSymbol(symbol) => ErrorValue.RESymbolNotFound(symbol)->Error | IevSymbol(symbol) => ErrorValue.RESymbolNotFound(symbol)->Error
| _ => list{arg, ...acc}->Ok | _ => 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 = ( let applyParametersToLambda = (
lambdaValue: ExpressionValue.lambdaValue, lambdaValue: ExpressionValue.lambdaValue,
args, args,
@ -41,16 +58,11 @@ let applyParametersToLambda = (
): result<expressionValue, 'e> => { ): result<expressionValue, 'e> => {
checkArity(lambdaValue, args)->Result.flatMap(args => checkArity(lambdaValue, args)->Result.flatMap(args =>
checkIfReduced(args)->Result.flatMap(args => { checkIfReduced(args)->Result.flatMap(args => {
let expr = castInternalCodeToExpression(lambdaValue.body) let exprOrFFI = castInternalCodeToExpression(lambdaValue.body)
let parameterList = lambdaValue.parameters->Belt.List.fromArray switch exprOrFFI {
let zippedParameterList = parameterList->Belt.List.zip(args) | NotFFI(expr) => caseNotFFI(lambdaValue, expr, args, environment, reducer)
let bindings = Belt.List.reduce( | FFI(ffiFn) => caseFFI(ffiFn, args, environment)
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)
}) })
) )
} }

View File

@ -1,5 +1,5 @@
module ExpressionT = Reducer_Expression_T module ExpressionT = Reducer_Expression_T
module ExpressionValue = ReducerInterface.ExpressionValue module ExpressionValue = ReducerInterface_InternalExpressionValue
module ExpressionWithContext = Reducer_ExpressionWithContext module ExpressionWithContext = Reducer_ExpressionWithContext
module Result = Belt.Result module Result = Belt.Result

View File

@ -7,15 +7,15 @@
The act of defining the semantics of a functional language is to write it in terms of Lisp AST. The act of defining the semantics of a functional language is to write it in terms of Lisp AST.
*/ */
module Extra = Reducer_Extra module Extra = Reducer_Extra
module ExpressionValue = ReducerInterface.ExpressionValue module InternalExpressionValue = ReducerInterface_InternalExpressionValue
type expressionValue = ExpressionValue.expressionValue type expressionValue = InternalExpressionValue.expressionValue
type environment = ExpressionValue.environment type environment = ReducerInterface_InternalExpressionValue.environment
type rec expression = type rec expression =
| EList(list<expression>) // A list to map-reduce | EList(list<expression>) // A list to map-reduce
| EValue(expressionValue) // Irreducible built-in value. Reducer should not know the internals. External libraries are responsible | 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 = ( type reducerFn = (
expression, expression,
@ -28,7 +28,7 @@ type reducerFn = (
*/ */
let rec toString = expression => let rec toString = expression =>
switch expression { switch expression {
| EList(list{EValue(EvCall("$$_block_$$")), ...statements}) => | EList(list{EValue(IevCall("$$_block_$$")), ...statements}) =>
`{${Belt.List.map(statements, aValue => toString(aValue)) `{${Belt.List.map(statements, aValue => toString(aValue))
->Extra.List.interperse("; ") ->Extra.List.interperse("; ")
->Belt.List.toArray ->Belt.List.toArray
@ -38,7 +38,7 @@ let rec toString = expression =>
->Extra.List.interperse(" ") ->Extra.List.interperse(" ")
->Belt.List.toArray ->Belt.List.toArray
->Js.String.concatMany("")})` ->Js.String.concatMany("")})`
| EValue(aValue) => ExpressionValue.toString(aValue) | EValue(aValue) => InternalExpressionValue.toString(aValue)
} }
let toStringResult = codeResult => let toStringResult = codeResult =>
@ -65,3 +65,12 @@ let inspectResult = (r: result<expression, Reducer_ErrorValue.errorValue>): resu
Js.log(toStringResult(r)) Js.log(toStringResult(r))
r r
} }
type ffiFn = (
array<expressionValue>,
environment,
) => result<expressionValue, Reducer_ErrorValue.errorValue>
type expressionOrFFI =
| NotFFI(expression)
| FFI(ffiFn)

View File

@ -1,4 +1,4 @@
open ReducerInterface.ExpressionValue open ReducerInterface_InternalExpressionValue
open Reducer_ErrorValue open Reducer_ErrorValue
external castBool: unit => bool = "%identity" 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 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) { switch Js.typeof(jsValue) {
| "boolean" => jsValue->castBool->EvBool->Ok | "boolean" => jsValue->castBool->IevBool->Ok
| "number" => jsValue->castNumber->EvNumber->Ok | "number" => jsValue->castNumber->IevNumber->Ok
| "string" => jsValue->castString->EvString->Ok | "string" => jsValue->castString->IevString->Ok
| other => RETodo(`Unhandled MathJs literal type: ${Js.String.make(other)}`)->Error | other => RETodo(`Unhandled MathJs literal type: ${Js.String.make(other)}`)->Error
} }

View File

@ -1,5 +1,5 @@
module JavaScript = Reducer_Js module JavaScript = Reducer_Js
open ReducerInterface.ExpressionValue open ReducerInterface_InternalExpressionValue
open Reducer_ErrorValue open Reducer_ErrorValue
@module("mathjs") external dummy_: string => unit = "evaluate" @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> => { let eval = (expr: string): result<expressionValue, errorValue> => {
try { try {
let answer = eval__(expr) let answer = eval__(expr)
answer["value"]->JavaScript.Gate.jsToEv answer["value"]->JavaScript.Gate.jsToIev
} catch { } catch {
| Js.Exn.Error(obj) => REJavaScriptExn(Js.Exn.message(obj), Js.Exn.name(obj))->Error | Js.Exn.Error(obj) => REJavaScriptExn(Js.Exn.message(obj), Js.Exn.name(obj))->Error
} }

View File

@ -1,2 +1,4 @@
module ExpressionValue = ReducerInterface_ExpressionValue module ExternalExpressionValue = ReducerInterface_ExpressionValue
module ExternalLibrary = ReducerInterface_ExternalLibrary module ExternalLibrary = ReducerInterface_ExternalLibrary
module InternalExpressionValue = ReducerInterface_InternalExpressionValue
module StdLib = ReducerInterface_StdLib

View File

@ -1,27 +1,27 @@
module EV = ReducerInterface_ExpressionValue module EV = ReducerInterface_InternalExpressionValue
type expressionValue = EV.expressionValue type expressionValue = EV.expressionValue
let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option< let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>, result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
> => { > => {
switch call { switch call {
| ("toString", [EvDate(t)]) => EV.EvString(DateTime.Date.toString(t))->Ok->Some | ("toString", [IevDate(t)]) => EV.IevString(DateTime.Date.toString(t))->Ok->Some
| ("makeDateFromYear", [EvNumber(year)]) => | ("makeDateFromYear", [IevNumber(year)]) =>
switch DateTime.Date.makeFromYear(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 | Error(e) => Reducer_ErrorValue.RETodo(e)->Error->Some
} }
| ("dateFromNumber", [EvNumber(f)]) => EV.EvDate(DateTime.Date.fromFloat(f))->Ok->Some | ("dateFromNumber", [IevNumber(f)]) => EV.IevDate(DateTime.Date.fromFloat(f))->Ok->Some
| ("toNumber", [EvDate(f)]) => EV.EvNumber(DateTime.Date.toFloat(f))->Ok->Some | ("toNumber", [IevDate(f)]) => EV.IevNumber(DateTime.Date.toFloat(f))->Ok->Some
| ("subtract", [EvDate(d1), EvDate(d2)]) => | ("subtract", [IevDate(d1), IevDate(d2)]) =>
switch DateTime.Date.subtract(d1, d2) { switch DateTime.Date.subtract(d1, d2) {
| Ok(d) => EV.EvTimeDuration(d)->Ok | Ok(d) => EV.IevTimeDuration(d)->Ok
| Error(e) => Error(RETodo(e)) | Error(e) => Error(RETodo(e))
}->Some }->Some
| ("subtract", [EvDate(d1), EvTimeDuration(d2)]) => | ("subtract", [IevDate(d1), IevTimeDuration(d2)]) =>
EV.EvDate(DateTime.Date.subtractDuration(d1, d2))->Ok->Some EV.IevDate(DateTime.Date.subtractDuration(d1, d2))->Ok->Some
| ("add", [EvDate(d1), EvTimeDuration(d2)]) => | ("add", [IevDate(d1), IevTimeDuration(d2)]) =>
EV.EvDate(DateTime.Date.addDuration(d1, d2))->Ok->Some EV.IevDate(DateTime.Date.addDuration(d1, d2))->Ok->Some
| _ => None | _ => None
} }
} }

View File

@ -1,33 +1,35 @@
module EV = ReducerInterface_ExpressionValue module EV = ReducerInterface_InternalExpressionValue
type expressionValue = EV.expressionValue type expressionValue = EV.expressionValue
let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option< let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>, result<expressionValue, QuriSquiggleLang.Reducer_ErrorValue.errorValue>,
> => { > => {
switch call { switch call {
| ("toString", [EvTimeDuration(t)]) => EV.EvString(DateTime.Duration.toString(t))->Ok->Some | ("toString", [IevTimeDuration(t)]) => EV.IevString(DateTime.Duration.toString(t))->Ok->Some
| ("minutes", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromMinutes(f))->Ok->Some | ("minutes", [IevNumber(f)]) => EV.IevTimeDuration(DateTime.Duration.fromMinutes(f))->Ok->Some
| ("fromUnit_minutes", [EvNumber(f)]) => | ("fromUnit_minutes", [IevNumber(f)]) =>
EV.EvTimeDuration(DateTime.Duration.fromMinutes(f))->Ok->Some EV.IevTimeDuration(DateTime.Duration.fromMinutes(f))->Ok->Some
| ("hours", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some | ("hours", [IevNumber(f)]) => EV.IevTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some
| ("fromUnit_hours", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some | ("fromUnit_hours", [IevNumber(f)]) =>
| ("days", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some EV.IevTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some
| ("fromUnit_days", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some | ("days", [IevNumber(f)]) => EV.IevTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
| ("years", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some | ("fromUnit_days", [IevNumber(f)]) => EV.IevTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some
| ("fromUnit_years", [EvNumber(f)]) => EV.EvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some | ("years", [IevNumber(f)]) => EV.IevTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
| ("toHours", [EvTimeDuration(f)]) => EV.EvNumber(DateTime.Duration.toHours(f))->Ok->Some | ("fromUnit_years", [IevNumber(f)]) =>
| ("toMinutes", [EvTimeDuration(f)]) => EV.EvNumber(DateTime.Duration.toMinutes(f))->Ok->Some EV.IevTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some
| ("toDays", [EvTimeDuration(f)]) => EV.EvNumber(DateTime.Duration.toDays(f))->Ok->Some | ("toHours", [IevTimeDuration(f)]) => EV.IevNumber(DateTime.Duration.toHours(f))->Ok->Some
| ("toYears", [EvTimeDuration(f)]) => EV.EvNumber(DateTime.Duration.toYears(f))->Ok->Some | ("toMinutes", [IevTimeDuration(f)]) => EV.IevNumber(DateTime.Duration.toMinutes(f))->Ok->Some
| ("add", [EvTimeDuration(d1), EvTimeDuration(d2)]) => | ("toDays", [IevTimeDuration(f)]) => EV.IevNumber(DateTime.Duration.toDays(f))->Ok->Some
EV.EvTimeDuration(DateTime.Duration.add(d1, d2))->Ok->Some | ("toYears", [IevTimeDuration(f)]) => EV.IevNumber(DateTime.Duration.toYears(f))->Ok->Some
| ("subtract", [EvTimeDuration(d1), EvTimeDuration(d2)]) => | ("add", [IevTimeDuration(d1), IevTimeDuration(d2)]) =>
EV.EvTimeDuration(DateTime.Duration.subtract(d1, d2))->Ok->Some EV.IevTimeDuration(DateTime.Duration.add(d1, d2))->Ok->Some
| ("multiply", [EvTimeDuration(d1), EvNumber(d2)]) => | ("subtract", [IevTimeDuration(d1), IevTimeDuration(d2)]) =>
EV.EvTimeDuration(DateTime.Duration.multiply(d1, d2))->Ok->Some EV.IevTimeDuration(DateTime.Duration.subtract(d1, d2))->Ok->Some
| ("divide", [EvTimeDuration(d1), EvNumber(d2)]) => | ("multiply", [IevTimeDuration(d1), IevNumber(d2)]) =>
EV.EvTimeDuration(DateTime.Duration.divide(d1, d2))->Ok->Some EV.IevTimeDuration(DateTime.Duration.multiply(d1, d2))->Ok->Some
| ("divide", [EvTimeDuration(d1), EvTimeDuration(d2)]) => EV.EvNumber(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 | _ => None
} }
} }

View File

@ -68,25 +68,6 @@ and toStringRecord = aRecord => {
`{${pairs}}` `{${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 => { let argsToString = (args: array<expressionValue>): string => {
args->Js.Array2.map(arg => arg->toString)->Js.Array2.toString args->Js.Array2.map(arg => arg->toString)->Js.Array2.toString
} }
@ -99,17 +80,17 @@ let toStringResult = x =>
| Error(m) => `Error(${ErrorValue.errorToString(m)})` | Error(m) => `Error(${ErrorValue.errorToString(m)})`
} }
let toStringResultOkless = (codeResult: result<expressionValue, ErrorValue.errorValue>): string => // let toStringResultOkless = (codeResult: result<expressionValue, ErrorValue.errorValue>): string =>
switch codeResult { // switch codeResult {
| Ok(a) => toString(a) // | Ok(a) => toString(a)
| Error(m) => `Error(${ErrorValue.errorToString(m)})` // | Error(m) => `Error(${ErrorValue.errorToString(m)})`
} // }
let toStringResultRecord = x => // let toStringResultRecord = x =>
switch x { // switch x {
| Ok(a) => `Ok(${toStringRecord(a)})` // | Ok(a) => `Ok(${toStringRecord(a)})`
| Error(m) => `Error(${ErrorValue.errorToString(m)})` // | Error(m) => `Error(${ErrorValue.errorToString(m)})`
} // }
@genType @genType
type environment = DistributionOperation.env type environment = DistributionOperation.env
@ -141,14 +122,14 @@ type functionDefinitionSignature =
let valueToValueType = value => let valueToValueType = value =>
switch value { switch value {
| EvArray(_) => EvtArray | EvArray(_) => EvtArray
| EvArrayString(_) => EvtArray | EvArrayString(_) => EvtArrayString
| EvBool(_) => EvtBool | EvBool(_) => EvtBool
| EvCall(_) => EvtCall | EvCall(_) => EvtCall
| EvDistribution(_) => EvtDistribution | EvDistribution(_) => EvtDistribution
| EvLambda(_) => EvtLambda | EvLambda(_) => EvtLambda
| EvNumber(_) => EvtNumber | EvNumber(_) => EvtNumber
| EvRecord(_) => EvtRecord | EvRecord(_) => EvtRecord
| EvString(_) => EvtArray | EvString(_) => EvtString
| EvSymbol(_) => EvtSymbol | EvSymbol(_) => EvtSymbol
| EvDate(_) => EvtDate | EvDate(_) => EvtDate
| EvTimeDuration(_) => EvtTimeDuration | EvTimeDuration(_) => EvtTimeDuration

View File

@ -1,4 +1,4 @@
module ExpressionValue = ReducerInterface_ExpressionValue module ExpressionValue = ReducerInterface_InternalExpressionValue
type expressionValue = ExpressionValue.expressionValue type expressionValue = ExpressionValue.expressionValue

View File

@ -1,4 +1,4 @@
module ExpressionValue = ReducerInterface_ExpressionValue module ExpressionValue = ReducerInterface_InternalExpressionValue
type expressionValue = ExpressionValue.expressionValue type expressionValue = ExpressionValue.expressionValue
module Helpers = { module Helpers = {
@ -23,9 +23,9 @@ module Helpers = {
DistributionTypes.genericDist, DistributionTypes.genericDist,
)> => )> =>
switch args { switch args {
| [EvDistribution(a), EvDistribution(b)] => Some((a, b)) | [IevDistribution(a), IevDistribution(b)] => Some((a, b))
| [EvNumber(a), EvDistribution(b)] => Some((GenericDist.fromFloat(a), b)) | [IevNumber(a), IevDistribution(b)] => Some((GenericDist.fromFloat(a), b))
| [EvDistribution(a), EvNumber(b)] => Some((a, GenericDist.fromFloat(b))) | [IevDistribution(a), IevNumber(b)] => Some((a, GenericDist.fromFloat(b)))
| _ => None | _ => None
} }
@ -82,7 +82,7 @@ module Helpers = {
let parseNumber = (args: expressionValue): Belt.Result.t<float, string> => let parseNumber = (args: expressionValue): Belt.Result.t<float, string> =>
switch args { switch args {
| EvNumber(x) => Ok(x) | IevNumber(x) => Ok(x)
| _ => Error("Not a number") | _ => Error("Not a number")
} }
@ -91,8 +91,8 @@ module Helpers = {
let parseDist = (args: expressionValue): Belt.Result.t<DistributionTypes.genericDist, string> => let parseDist = (args: expressionValue): Belt.Result.t<DistributionTypes.genericDist, string> =>
switch args { switch args {
| EvDistribution(x) => Ok(x) | IevDistribution(x) => Ok(x)
| EvNumber(x) => Ok(GenericDist.fromFloat(x)) | IevNumber(x) => Ok(GenericDist.fromFloat(x))
| _ => Error("Not a distribution") | _ => Error("Not a distribution")
} }
@ -128,12 +128,12 @@ module Helpers = {
let error = (err: string): DistributionOperation.outputType => let error = (err: string): DistributionOperation.outputType =>
err->DistributionTypes.ArgumentError->GenDistError err->DistributionTypes.ArgumentError->GenDistError
switch args { switch args {
| [EvArray(distributions)] => | [IevArray(distributions)] =>
switch parseDistributionArray(distributions) { switch parseDistributionArray(distributions) {
| Ok(distrs) => mixtureWithDefaultWeights(distrs, ~env) | Ok(distrs) => mixtureWithDefaultWeights(distrs, ~env)
| Error(err) => error(err) | Error(err) => error(err)
} }
| [EvArray(distributions), EvArray(weights)] => | [IevArray(distributions), IevArray(weights)] =>
switch (parseDistributionArray(distributions), parseNumberArray(weights)) { switch (parseDistributionArray(distributions), parseNumberArray(weights)) {
| (Ok(distrs), Ok(wghts)) => mixtureWithGivenWeights(distrs, wghts, ~env) | (Ok(distrs), Ok(wghts)) => mixtureWithGivenWeights(distrs, wghts, ~env)
| (Error(err), Ok(_)) => error(err) | (Error(err), Ok(_)) => error(err)
@ -142,7 +142,7 @@ module Helpers = {
} }
| _ => | _ =>
switch E.A.last(args) { switch E.A.last(args) {
| Some(EvArray(b)) => { | Some(IevArray(b)) => {
let weights = parseNumberArray(b) let weights = parseNumberArray(b)
let distributions = parseDistributionArray( let distributions = parseDistributionArray(
Belt.Array.slice(args, ~offset=0, ~len=E.A.length(args) - 1), Belt.Array.slice(args, ~offset=0, ~len=E.A.length(args) - 1),
@ -152,8 +152,8 @@ module Helpers = {
| Error(err) => error(err) | Error(err) => error(err)
} }
} }
| Some(EvNumber(_)) | Some(IevNumber(_))
| Some(EvDistribution(_)) => | Some(IevDistribution(_)) =>
switch parseDistributionArray(args) { switch parseDistributionArray(args) {
| Ok(distributions) => mixtureWithDefaultWeights(distributions, ~env) | Ok(distributions) => mixtureWithDefaultWeights(distributions, ~env)
| Error(err) => error(err) | Error(err) => error(err)
@ -200,14 +200,14 @@ let dispatchToGenericOutput = (
): option<DistributionOperation.outputType> => { ): option<DistributionOperation.outputType> => {
let (fnName, args) = call let (fnName, args) = call
switch (fnName, args) { switch (fnName, args) {
| ("triangular" as fnName, [EvNumber(f1), EvNumber(f2), EvNumber(f3)]) => | ("triangular" as fnName, [IevNumber(f1), IevNumber(f2), IevNumber(f3)]) =>
SymbolicConstructors.threeFloat(fnName) SymbolicConstructors.threeFloat(fnName)
->E.R.bind(r => r(f1, f2, f3)) ->E.R.bind(r => r(f1, f2, f3))
->SymbolicConstructors.symbolicResultToOutput ->SymbolicConstructors.symbolicResultToOutput
| ("sample", [EvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist, ~env) | ("sample", [IevDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist, ~env)
| ("sampleN", [EvDistribution(dist), EvNumber(n)]) => | ("sampleN", [IevDistribution(dist), IevNumber(n)]) =>
Some(FloatArray(GenericDist.sampleN(dist, Belt.Int.fromFloat(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 { let fn = switch op {
| "mean" => #Mean | "mean" => #Mean
| "stdev" => #Stdev | "stdev" => #Stdev
@ -219,13 +219,13 @@ let dispatchToGenericOutput = (
} }
Helpers.toFloatFn(fn, dist, ~env) Helpers.toFloatFn(fn, dist, ~env)
} }
| ("integralSum", [EvDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist, ~env) | ("integralSum", [IevDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist, ~env)
| ("toString", [EvDistribution(dist)]) => Helpers.toStringFn(ToString, dist, ~env) | ("toString", [IevDistribution(dist)]) => Helpers.toStringFn(ToString, dist, ~env)
| ("toSparkline", [EvDistribution(dist)]) => | ("toSparkline", [IevDistribution(dist)]) =>
Helpers.toStringFn(ToSparkline(MagicNumbers.Environment.sparklineLength), dist, ~env) 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) Helpers.toStringFn(ToSparkline(Belt.Float.toInt(n)), dist, ~env)
| ("exp", [EvDistribution(a)]) => | ("exp", [IevDistribution(a)]) =>
// https://mathjs.org/docs/reference/functions/exp.html // https://mathjs.org/docs/reference/functions/exp.html
Helpers.twoDiststoDistFn( Helpers.twoDiststoDistFn(
Algebraic(AsDefault), Algebraic(AsDefault),
@ -234,51 +234,58 @@ let dispatchToGenericOutput = (
a, a,
~env, ~env,
)->Some )->Some
| ("normalize", [EvDistribution(dist)]) => Helpers.toDistFn(Normalize, dist, ~env) | ("normalize", [IevDistribution(dist)]) => Helpers.toDistFn(Normalize, dist, ~env)
| ("klDivergence", [EvDistribution(prediction), EvDistribution(answer)]) => | ("klDivergence", [IevDistribution(prediction), IevDistribution(answer)]) =>
Some(DistributionOperation.run(FromDist(ToScore(KLDivergence(answer)), prediction), ~env)) 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) Helpers.klDivergenceWithPrior(prediction, answer, prior, env)
| ( | (
"logScoreWithPointAnswer", "logScoreWithPointAnswer",
[EvDistribution(prediction), EvNumber(answer), EvDistribution(prior)], [IevDistribution(prediction), IevNumber(answer), IevDistribution(prior)],
) )
| ( | (
"logScoreWithPointAnswer", "logScoreWithPointAnswer",
[EvDistribution(prediction), EvDistribution(Symbolic(#Float(answer))), EvDistribution(prior)], [
IevDistribution(prediction),
IevDistribution(Symbolic(#Float(answer))),
IevDistribution(prior),
],
) => ) =>
DistributionOperation.run( DistributionOperation.run(
FromDist(ToScore(LogScore(answer, prior->Some)), prediction), FromDist(ToScore(LogScore(answer, prior->Some)), prediction),
~env, ~env,
)->Some )->Some
| ("logScoreWithPointAnswer", [EvDistribution(prediction), EvNumber(answer)]) | ("logScoreWithPointAnswer", [IevDistribution(prediction), IevNumber(answer)])
| ( | (
"logScoreWithPointAnswer", "logScoreWithPointAnswer",
[EvDistribution(prediction), EvDistribution(Symbolic(#Float(answer)))], [IevDistribution(prediction), IevDistribution(Symbolic(#Float(answer)))],
) => ) =>
DistributionOperation.run(FromDist(ToScore(LogScore(answer, None)), prediction), ~env)->Some DistributionOperation.run(FromDist(ToScore(LogScore(answer, None)), prediction), ~env)->Some
| ("isNormalized", [EvDistribution(dist)]) => Helpers.toBoolFn(IsNormalized, dist, ~env) | ("isNormalized", [IevDistribution(dist)]) => Helpers.toBoolFn(IsNormalized, dist, ~env)
| ("toPointSet", [EvDistribution(dist)]) => Helpers.toDistFn(ToPointSet, dist, ~env) | ("toPointSet", [IevDistribution(dist)]) => Helpers.toDistFn(ToPointSet, dist, ~env)
| ("scaleLog", [EvDistribution(dist)]) => | ("scaleLog", [IevDistribution(dist)]) =>
Helpers.toDistFn(Scale(#Logarithm, MagicNumbers.Math.e), dist, ~env) Helpers.toDistFn(Scale(#Logarithm, MagicNumbers.Math.e), dist, ~env)
| ("scaleLog10", [EvDistribution(dist)]) => Helpers.toDistFn(Scale(#Logarithm, 10.0), dist, ~env) | ("scaleLog10", [IevDistribution(dist)]) => Helpers.toDistFn(Scale(#Logarithm, 10.0), dist, ~env)
| ("scaleLog", [EvDistribution(dist), EvNumber(float)]) => | ("scaleLog", [IevDistribution(dist), IevNumber(float)]) =>
Helpers.toDistFn(Scale(#Logarithm, float), dist, ~env) 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) 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) Helpers.toDistFn(Scale(#Power, float), dist, ~env)
| ("scaleExp", [EvDistribution(dist)]) => | ("scaleExp", [IevDistribution(dist)]) =>
Helpers.toDistFn(Scale(#Power, MagicNumbers.Math.e), dist, ~env) Helpers.toDistFn(Scale(#Power, MagicNumbers.Math.e), dist, ~env)
| ("cdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Cdf(float), dist, ~env) | ("cdf", [IevDistribution(dist), IevNumber(float)]) => Helpers.toFloatFn(#Cdf(float), dist, ~env)
| ("pdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Pdf(float), dist, ~env) | ("pdf", [IevDistribution(dist), IevNumber(float)]) => Helpers.toFloatFn(#Pdf(float), dist, ~env)
| ("inv", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Inv(float), dist, ~env) | ("inv", [IevDistribution(dist), IevNumber(float)]) => Helpers.toFloatFn(#Inv(float), dist, ~env)
| ("toSampleSet", [EvDistribution(dist), EvNumber(float)]) => | ("toSampleSet", [IevDistribution(dist), IevNumber(float)]) =>
Helpers.toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist, ~env) Helpers.toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist, ~env)
| ("toSampleSet", [EvDistribution(dist)]) => | ("toSampleSet", [IevDistribution(dist)]) =>
Helpers.toDistFn(ToSampleSet(env.sampleCount), dist, ~env) Helpers.toDistFn(ToSampleSet(env.sampleCount), dist, ~env)
| ("toList", [EvDistribution(SampleSet(dist))]) => Some(FloatArray(SampleSetDist.T.get(dist))) | ("toList", [IevDistribution(SampleSet(dist))]) => Some(FloatArray(SampleSetDist.T.get(dist)))
| ("fromSamples", [EvArray(inputArray)]) => { | ("fromSamples", [IevArray(inputArray)]) => {
let _wrapInputErrors = x => SampleSetDist.NonNumericInput(x) let _wrapInputErrors = x => SampleSetDist.NonNumericInput(x)
let parsedArray = Helpers.parseNumberArray(inputArray)->E.R2.errMap(_wrapInputErrors) let parsedArray = Helpers.parseNumberArray(inputArray)->E.R2.errMap(_wrapInputErrors)
switch parsedArray { switch parsedArray {
@ -286,15 +293,15 @@ let dispatchToGenericOutput = (
| Error(e) => GenDistError(SampleSetError(e)) | Error(e) => GenDistError(SampleSetError(e))
}->Some }->Some
} }
| ("inspect", [EvDistribution(dist)]) => Helpers.toDistFn(Inspect, dist, ~env) | ("inspect", [IevDistribution(dist)]) => Helpers.toDistFn(Inspect, dist, ~env)
| ("truncateLeft", [EvDistribution(dist), EvNumber(float)]) => | ("truncateLeft", [IevDistribution(dist), IevNumber(float)]) =>
Helpers.toDistFn(Truncate(Some(float), None), dist, ~env) 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) 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) Helpers.toDistFn(Truncate(Some(float1), Some(float2)), dist, ~env)
| ("mx" | "mixture", args) => Helpers.mixture(args, ~env)->Some | ("mx" | "mixture", args) => Helpers.mixture(args, ~env)->Some
| ("log", [EvDistribution(a)]) => | ("log", [IevDistribution(a)]) =>
Helpers.twoDiststoDistFn( Helpers.twoDiststoDistFn(
Algebraic(AsDefault), Algebraic(AsDefault),
"log", "log",
@ -302,7 +309,7 @@ let dispatchToGenericOutput = (
GenericDist.fromFloat(MagicNumbers.Math.e), GenericDist.fromFloat(MagicNumbers.Math.e),
~env, ~env,
)->Some )->Some
| ("log10", [EvDistribution(a)]) => | ("log10", [IevDistribution(a)]) =>
Helpers.twoDiststoDistFn( Helpers.twoDiststoDistFn(
Algebraic(AsDefault), Algebraic(AsDefault),
"log", "log",
@ -310,7 +317,7 @@ let dispatchToGenericOutput = (
GenericDist.fromFloat(10.0), GenericDist.fromFloat(10.0),
~env, ~env,
)->Some )->Some
| ("unaryMinus", [EvDistribution(a)]) => | ("unaryMinus", [IevDistribution(a)]) =>
Helpers.twoDiststoDistFn( Helpers.twoDiststoDistFn(
Algebraic(AsDefault), Algebraic(AsDefault),
"multiply", "multiply",
@ -333,7 +340,7 @@ let dispatchToGenericOutput = (
Helpers.catchAndConvertTwoArgsToDists(args)->E.O2.fmap(((fst, snd)) => Helpers.catchAndConvertTwoArgsToDists(args)->E.O2.fmap(((fst, snd)) =>
Helpers.twoDiststoDistFn(Pointwise, arithmetic, fst, snd, ~env) Helpers.twoDiststoDistFn(Pointwise, arithmetic, fst, snd, ~env)
) )
| ("dotExp", [EvDistribution(a)]) => | ("dotExp", [IevDistribution(a)]) =>
Helpers.twoDiststoDistFn( Helpers.twoDiststoDistFn(
Pointwise, Pointwise,
"dotPow", "dotPow",
@ -350,11 +357,12 @@ let genericOutputToReducerValue = (o: DistributionOperation.outputType): result<
Reducer_ErrorValue.errorValue, Reducer_ErrorValue.errorValue,
> => > =>
switch o { switch o {
| Dist(d) => Ok(ReducerInterface_ExpressionValue.EvDistribution(d)) | Dist(d) => Ok(ReducerInterface_InternalExpressionValue.IevDistribution(d))
| Float(d) => Ok(EvNumber(d)) | Float(d) => Ok(IevNumber(d))
| String(d) => Ok(EvString(d)) | String(d) => Ok(IevString(d))
| Bool(d) => Ok(EvBool(d)) | Bool(d) => Ok(IevBool(d))
| FloatArray(d) => Ok(EvArray(d |> E.A.fmap(r => ReducerInterface_ExpressionValue.EvNumber(r)))) | FloatArray(d) =>
Ok(IevArray(d |> E.A.fmap(r => ReducerInterface_InternalExpressionValue.IevNumber(r))))
| GenDistError(err) => Error(REDistributionError(err)) | GenDistError(err) => Error(REDistributionError(err))
} }

View File

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

View File

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

View File

@ -1,4 +1,4 @@
module EV = ReducerInterface_ExpressionValue module EV = ReducerInterface_InternalExpressionValue
type expressionValue = EV.expressionValue type expressionValue = EV.expressionValue
module ScientificUnit = { module ScientificUnit = {
@ -37,9 +37,9 @@ let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option<
| "fromUnit_G" | "fromUnit_G"
| "fromUnit_T" | "fromUnit_T"
| "fromUnit_P") as op, | "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 | _ => None
} }
} }

View File

@ -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->Module.toTypeScriptBindings
let externalStdLib = internalStdLib->Bindings.toRecord

View File

@ -1,8 +1,8 @@
module Bindings = Reducer_Category_Bindings module Bindings = Reducer_Category_Module
module Module = Reducer_Category_Module module Module = Reducer_Category_Module
let m = let m =
Module.emptyModule->Module.defineNumber("pi", Js.Math._PI)->Module.defineNumber("e", Js.Math._E) 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) previousBindings->Bindings.defineModule("Math", m)