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