diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 27cfbc62..728a8c1c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -9,8 +9,8 @@ # This also holds true for GitHub teams. # Rescript -*.res @OAGr @quinn-dougherty -*.resi @OAGr @quinn-dougherty +*.res @OAGr +*.resi @OAGr # Typescript *.tsx @Hazelfire @OAGr diff --git a/packages/components/package.json b/packages/components/package.json index 7c64463c..75a189d1 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -5,14 +5,14 @@ "dependencies": { "@headlessui/react": "^1.6.5", "@heroicons/react": "^1.0.6", - "@hookform/resolvers": "^2.9.1", + "@hookform/resolvers": "^2.9.3", "@quri/squiggle-lang": "^0.2.8", "@react-hook/size": "^2.1.2", - "clsx": "^1.1.1", + "clsx": "^1.2.0", "lodash": "^4.17.21", "react": "^18.1.0", "react-ace": "^10.1.0", - "react-hook-form": "^7.32.2", + "react-hook-form": "^7.33.0", "react-use": "^17.4.0", "react-vega": "^7.5.1", "vega": "^5.22.1", diff --git a/packages/components/src/components/SquiggleItem.tsx b/packages/components/src/components/SquiggleItem.tsx index d05d7c1f..48a8a0fb 100644 --- a/packages/components/src/components/SquiggleItem.tsx +++ b/packages/components/src/components/SquiggleItem.tsx @@ -244,7 +244,28 @@ export const SquiggleItem: React.FC = ({ case "module": { return ( - Internal Module +
+ {Object.entries(expression.value) + .filter(([key, r]) => key !== "Math") + .map(([key, r]) => ( +
+
+
{key}:
+
+
+ +
+
+ ))} +
); } diff --git a/packages/squiggle-lang/.gitignore b/packages/squiggle-lang/.gitignore index 1449d5f3..034f263d 100644 --- a/packages/squiggle-lang/.gitignore +++ b/packages/squiggle-lang/.gitignore @@ -22,3 +22,4 @@ _coverage coverage .nyc_output/ src/rescript/Reducer/Reducer_Peggy/Reducer_Peggy_GeneratedParser.js +src/rescript/Reducer/Reducer_Peggy/helpers.js 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..84659ed7 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..8e3d8257 100644 --- a/packages/squiggle-lang/__tests__/Reducer/Reducer_Helpers.res +++ b/packages/squiggle-lang/__tests__/Reducer/Reducer_Helpers.res @@ -1,19 +1,22 @@ -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.t) => { + 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.t): ExternalExpressionValue.t => + 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..ed00e957 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..103609a2 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.t)>, 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.t)>, 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.t)>, expr: T.expression, expectedExpr: string, ) => testMacro_(test, bindArray, expr, expectedExpr) let testMacroEval = ( - bindArray: array<(string, ExpressionValue.expressionValue)>, + bindArray: array<(string, InternalExpressionValue.t)>, expr: T.expression, expectedValue: string, ) => testMacroEval_(test, bindArray, expr, expectedValue) module MySkip = { let testMacro = ( - bindArray: array<(string, ExpressionValue.expressionValue)>, + bindArray: array<(string, InternalExpressionValue.t)>, expr: T.expression, expectedExpr: string, ) => testMacro_(Skip.test, bindArray, expr, expectedExpr) let testMacroEval = ( - bindArray: array<(string, ExpressionValue.expressionValue)>, + bindArray: array<(string, InternalExpressionValue.t)>, 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.t)>, expr: T.expression, expectedExpr: string, ) => testMacro_(Only.test, bindArray, expr, expectedExpr) let testMacroEval = ( - bindArray: array<(string, ExpressionValue.expressionValue)>, + bindArray: array<(string, InternalExpressionValue.t)>, 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 b92eda09..c9501b3b 100644 --- a/packages/squiggle-lang/package.json +++ b/packages/squiggle-lang/package.json @@ -5,8 +5,10 @@ "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:peggy:helpers": "tsc --module commonjs --outDir src/rescript/Reducer/Reducer_Peggy/ src/rescript/Reducer/Reducer_Peggy/helpers.ts", + "build:peggy": "yarn build:peggy:helpers && find . -type f -name *.peggy -exec yarn peggy {} \\;", "build:rescript": "rescript build -with-deps", "build:typescript": "tsc", "bundle": "webpack", @@ -40,7 +42,7 @@ "@stdlib/stats": "^0.0.13", "jstat": "^1.9.5", "lodash": "^4.17.21", - "mathjs": "^10.6.0", + "mathjs": "^10.6.4", "pdfast": "^0.2.0" }, "devDependencies": { @@ -51,7 +53,7 @@ "bisect_ppx": "^2.7.1", "chalk": "^5.0.1", "codecov": "^3.8.3", - "fast-check": "^3.0.0", + "fast-check": "^3.0.1", "gentype": "^4.4.0", "jest": "^27.5.1", "moduleserve": "^0.9.1", diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index 74ca1d1d..6d847307 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -10,7 +10,6 @@ import { evaluatePartialUsingExternalBindings, evaluateUsingOptions, foreignFunctionInterface, - parse as parseRescript, } from "../rescript/TypescriptInterface.gen"; export { makeSampleSetDist, @@ -32,12 +31,14 @@ import { convertRawToTypescript, lambdaValue, } from "./rescript_interop"; -import { Ok, result, resultMap, tag, tagged } from "./types"; +import { result, resultMap, tag, tagged } from "./types"; import { Distribution, shape } from "./distribution"; export { Distribution, resultMap, defaultEnvironment }; export type { result, shape, environment, lambdaValue, squiggleExpression }; +export { parse } from "./parse"; + export let defaultSamplingInputs: environment = { sampleCount: 10000, xyPointLength: 10000, @@ -59,23 +60,6 @@ export function run( return resultMap(res, (x) => createTsExport(x, e)); } -export function parse( - squiggleString: string -): result> { - const maybeExpression = parseRescript(squiggleString); - if (maybeExpression.tag === "Ok") { - return Ok(null); // TODO - return AST - } else { - if ( - typeof maybeExpression.value !== "object" || - maybeExpression.value.tag !== "RESyntaxError" - ) { - throw new Error("Expected syntax error"); - } - return { tag: "Error", value: maybeExpression.value }; - } -} - // Run Partial. A partial is a block of code that doesn't return a value export function runPartial( squiggleString: string, @@ -147,30 +131,13 @@ function createTsExport( // case return tag( "array", - x.value.map((arrayItem): squiggleExpression => { - switch (arrayItem.tag) { - case "EvRecord": - return tag( - "record", - _.mapValues(arrayItem.value, (recordValue: unknown) => - convertRawToTypescript( - recordValue as rescriptExport, - environment - ) - ) - ); - case "EvArray": - let y = arrayItem.value as unknown as rescriptExport[]; - return tag( - "array", - y.map((childArrayItem) => - convertRawToTypescript(childArrayItem, environment) - ) - ); - default: - return createTsExport(arrayItem, environment); - } - }) + x.value.map( + (arrayItem): squiggleExpression => + convertRawToTypescript( + arrayItem as unknown as rescriptExport, + environment + ) + ) ); case "EvArrayString": return tag("arraystring", x.value); diff --git a/packages/squiggle-lang/src/js/parse.ts b/packages/squiggle-lang/src/js/parse.ts new file mode 100644 index 00000000..730bda2e --- /dev/null +++ b/packages/squiggle-lang/src/js/parse.ts @@ -0,0 +1,23 @@ +import { + errorValue, + parse as parseRescript, +} from "../rescript/TypescriptInterface.gen"; +import { result } from "./types"; +import { AnyPeggyNode } from "../rescript/Reducer/Reducer_Peggy/helpers"; + +export function parse( + squiggleString: string +): result> { + const maybeExpression = parseRescript(squiggleString); + if (maybeExpression.tag === "Ok") { + return { tag: "Ok", value: maybeExpression.value as AnyPeggyNode }; + } else { + if ( + typeof maybeExpression.value !== "object" || + maybeExpression.value.tag !== "RESyntaxError" + ) { + throw new Error("Expected syntax error"); + } + return { tag: "Error", value: maybeExpression.value }; + } +} 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..bbca7bc7 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 internalExpressionValue = ReducerInterface_InternalExpressionValue.t /* 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) @@ -41,7 +41,7 @@ and frValueDistOrNumber = FRValueNumber(float) | FRValueDist(DistributionTypes.g type fnDefinition = { name: string, inputs: array, - run: (array, DistributionOperation.env) => result, + run: (array, DistributionOperation.env) => result, } type function = { @@ -73,47 +73,47 @@ module FRType = { | FRTypeAny => `any` } - let rec toFrValue = (r: expressionValue): option => + let rec toFrValue = (r: internalExpressionValue): 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)) | _ => None } - let rec matchWithExpressionValue = (t: t, r: expressionValue): option => + let rec matchWithExpressionValue = (t: t, r: internalExpressionValue): 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> = @@ -125,35 +125,38 @@ module FRType = { | _ => None } - let rec matchReverse = (e: frValue): expressionValue => + let rec matchReverse = (e: frValue): internalExpressionValue => 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) } - let matchWithExpressionValueArray = (inputs: array, args: array): option< - array, - > => { + let matchWithExpressionValueArray = ( + inputs: array, + args: array, + ): option> => { let isSameLength = E.A.length(inputs) == E.A.length(args) if !isSameLength { None @@ -204,14 +207,14 @@ module Matcher = { } module FnDefinition = { - let matchAssumingSameName = (f: fnDefinition, args: array) => { + let matchAssumingSameName = (f: fnDefinition, args: array) => { switch FRType.matchWithExpressionValueArray(f.inputs, args) { | Some(_) => MatchSimple.FullMatch | None => MatchSimple.SameNameDifferentArguments } } - let match = (f: fnDefinition, fnName: string, args: array) => { + let match = (f: fnDefinition, fnName: string, args: array) => { if f.name !== fnName { MatchSimple.DifferentName } else { @@ -224,7 +227,7 @@ module Matcher = { type definitionId = int type match = Match.t, definitionId> - let match = (f: function, fnName: string, args: array): match => { + let match = (f: function, fnName: string, args: array): match => { let matchedDefinition = () => E.A.getIndexBy(f.definitions, r => MatchSimple.isFullMatch(FnDefinition.match(r, fnName, args)) @@ -258,7 +261,7 @@ module Matcher = { } module Registry = { - let _findExactMatches = (r: registry, fnName: string, args: array) => { + let _findExactMatches = (r: registry, fnName: string, args: array) => { let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args))) let fullMatch = functionMatchPairs->E.A.getBy(((_, match)) => Match.isFullMatch(match)) fullMatch->E.O.bind(((fn, match)) => @@ -269,7 +272,7 @@ module Matcher = { ) } - let _findNameMatches = (r: registry, fnName: string, args: array) => { + let _findNameMatches = (r: registry, fnName: string, args: array) => { let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args))) let getNameMatches = functionMatchPairs @@ -288,7 +291,7 @@ module Matcher = { E.A.toNoneIfEmpty(matches) } - let findMatches = (r: registry, fnName: string, args: array) => { + let findMatches = (r: registry, fnName: string, args: array) => { switch _findExactMatches(r, fnName, args) { | Some(r) => Match.FullMatch(r) | None => @@ -316,7 +319,7 @@ module FnDefinition = { t.name ++ `(${inputs})` } - let run = (t: t, args: array, env: DistributionOperation.env) => { + let run = (t: t, args: array, env: DistributionOperation.env) => { let argValues = FRType.matchWithExpressionValueArray(t.inputs, args) switch argValues { | Some(values) => t.run(values, env) @@ -370,7 +373,7 @@ module Registry = { let matchAndRun = ( ~registry: registry, ~fnName: string, - ~args: array, + ~args: array, ~env: DistributionOperation.env, ) => { let matchToDef = m => Matcher.Registry.matchToDef(registry, m) diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Helpers.res index 7d0240eb..46ae18f9 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..56315860 100644 --- a/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/FunctionRegistry_Library.res @@ -9,7 +9,7 @@ module Declaration = { ("inputs", FRTypeArray(FRTypeRecord([("min", FRTypeNumber), ("max", FRTypeNumber)]))), ]) - let fromExpressionValue = (e: frValue): result => { + let fromExpressionValue = (e: frValue): result => { switch FunctionRegistry_Helpers.Prepare.ToValueArray.Record.twoArgs([e]) { | Ok([FRValueLambda(lambda), FRValueArray(inputs)]) => { open FunctionRegistry_Helpers.Prepare @@ -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..bf8c89f9 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_ExternalExpressionValue +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 externalBindings = ReducerInterface_ExpressionValue.externalBindings -type lambdaValue = ExpressionValue.lambdaValue +type expressionValue = ExternalExpressionValue.t +type externalBindings = ReducerInterface_ExternalExpressionValue.externalBindings +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.resi b/packages/squiggle-lang/src/rescript/Reducer/Reducer.resi index d4e40a63..bd0c43fb 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer.resi +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer.resi @@ -2,27 +2,29 @@ module ErrorValue = Reducer_ErrorValue module Expression = Reducer_Expression @genType -type environment = ReducerInterface_ExpressionValue.environment +type environment = ReducerInterface_ExternalExpressionValue.environment @genType type errorValue = Reducer_ErrorValue.errorValue @genType -type expressionValue = ReducerInterface_ExpressionValue.expressionValue +type expressionValue = ReducerInterface_ExternalExpressionValue.t @genType -type externalBindings = ReducerInterface_ExpressionValue.externalBindings +type externalBindings = ReducerInterface_ExternalExpressionValue.externalBindings @genType -type lambdaValue = ReducerInterface_ExpressionValue.lambdaValue +type lambdaValue = ReducerInterface_ExternalExpressionValue.lambdaValue @genType let evaluateUsingOptions: ( - ~environment: option, - ~externalBindings: option, + ~environment: option, + ~externalBindings: option< + QuriSquiggleLang.ReducerInterface_ExternalExpressionValue.externalBindings, + >, string, ) => result @genType let evaluatePartialUsingExternalBindings: ( string, - QuriSquiggleLang.ReducerInterface_ExpressionValue.externalBindings, - QuriSquiggleLang.ReducerInterface_ExpressionValue.environment, + QuriSquiggleLang.ReducerInterface_ExternalExpressionValue.externalBindings, + QuriSquiggleLang.ReducerInterface_ExternalExpressionValue.environment, ) => result @genType let evaluate: string => result @@ -31,9 +33,9 @@ let parse: string => result @genType let foreignFunctionInterface: ( - QuriSquiggleLang.ReducerInterface_ExpressionValue.lambdaValue, - array, - QuriSquiggleLang.ReducerInterface_ExpressionValue.environment, + QuriSquiggleLang.ReducerInterface_ExternalExpressionValue.lambdaValue, + array, + QuriSquiggleLang.ReducerInterface_ExternalExpressionValue.environment, ) => result @genType 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..584f9089 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 fromExpressionValue = (aValue: expressionValue): t => +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): internalExpressionValue => IEvModule(nameSpace) +let fromExpressionValue = (aValue: internalExpressionValue): 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: internalExpressionValue): 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..957b0dc8 --- /dev/null +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Category/Reducer_Category_Module_TypeChecker.res @@ -0,0 +1,16 @@ +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 + } +} 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..6012d179 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,23 +32,29 @@ 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 } - let arrayAtIndex = (aValueArray: array, fIndex: float) => + let arrayAtIndex = (aValueArray: array, fIndex: float) => switch Belt.Array.get(aValueArray, Belt.Int.fromFloat(fIndex)) { | Some(value) => value->Ok | 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,70 +62,37 @@ 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) => { + let inspect = (value: internalExpressionValue) => { Js.log(value->toString) value->Ok } - let inspectLabel = (value: expressionValue, label: string) => { + let inspectLabel = (value: internalExpressionValue, label: string) => { Js.log(`${label}: ${value->toString}`) value->Ok } - let doSetBindings = ( - externalBindings: externalBindings, - symbol: string, - value: expressionValue, - ) => { - Bindings.fromExternalBindings(externalBindings) - ->Belt.Map.String.set(symbol, value) - ->Bindings.toExternalBindings - ->EvRecord - ->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 doSetBindings = (bindings: nameSpace, symbol: string, value: internalExpressionValue) => { + Module.set(bindings, symbol, value)->IEvModule->Ok } let doSetTypeAliasBindings = ( - externalBindings: externalBindings, + bindings: nameSpace, symbol: string, - value: expressionValue, - ) => doSetBindingsInNamespace(externalBindings, symbol, value, Bindings.typeAliasesKey) + value: internalExpressionValue, + ) => Module.setTypeAlias(bindings, symbol, value)->IEvModule->Ok - let doSetTypeOfBindings = ( - externalBindings: externalBindings, - symbol: string, - value: expressionValue, - ) => doSetBindingsInNamespace(externalBindings, symbol, value, Bindings.typeReferencesKey) + let doSetTypeOfBindings = (bindings: nameSpace, symbol: string, value: internalExpressionValue) => + Module.setTypeOf(bindings, symbol, value)->IEvModule->Ok - 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 +100,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 +116,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 +167,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 @@ -328,7 +299,7 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce Reducer uses Result monad while reducing expressions */ let dispatch = (call: functionCall, environment, reducer: ExpressionT.reducerFn): result< - expressionValue, + internalExpressionValue, errorValue, > => try { 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..1467f815 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,19 +3,19 @@ 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 InternalExpressionValue = ReducerInterface_InternalExpressionValue module ExpressionWithContext = Reducer_ExpressionWithContext +module Module = Reducer_Category_Module module Result = Belt.Result open Reducer_Expression_ExpressionBuilder -type environment = ExpressionValue.environment +type environment = InternalExpressionValue.environment type errorValue = ErrorValue.errorValue type expression = ExpressionT.expression -type expressionValue = ExpressionValue.expressionValue type expressionWithContext = ExpressionWithContext.expressionWithContext let dispatchMacroCall = ( @@ -27,13 +27,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 +51,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 +77,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 +123,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 +136,11 @@ let dispatchMacroCall = ( let rCondition = reduceExpression(blockCondition, bindings, environment) rCondition->Result.flatMap(conditionValue => switch conditionValue { - | ExpressionValue.EvBool(false) => { + | InternalExpressionValue.IEvBool(false) => { let ifFalseBlock = eBlock(list{ifFalse}) ExpressionWithContext.withContext(ifFalseBlock, bindings)->Ok } - | ExpressionValue.EvBool(true) => { + | InternalExpressionValue.IEvBool(true) => { let ifTrueBlock = eBlock(list{ifTrue}) ExpressionWithContext.withContext(ifTrueBlock, bindings)->Ok } @@ -158,32 +155,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 dabe3150..e7c82e77 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,20 @@ -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 internalExpressionValue = InternalExpressionValue.t +type externalExpressionValue = ReducerInterface_ExternalExpressionValue.t type t = expression /* @@ -27,7 +27,7 @@ let parse = (peggyCode: string): result => Recursively evaluate/reduce the expression (Lisp AST) */ let rec reduceExpression = (expression: t, bindings: T.bindings, environment: environment): result< - expressionValue, + internalExpressionValue, 'e, > => { // Js.log(`reduce: ${T.toString(expression)} bindings: ${bindings->Bindings.toString}`) @@ -35,7 +35,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) @@ -50,11 +50,11 @@ and reduceExpressionList = ( expressions: list, bindings: T.bindings, environment: environment, -): result => { - let racc: result, 'e> = expressions->Belt.List.reduceReverse(Ok(list{}), ( - racc, - each: expression, - ) => +): result => { + let racc: result< + list, + 'e, + > = expressions->Belt.List.reduceReverse(Ok(list{}), (racc, each: expression) => racc->Result.flatMap(acc => { each ->reduceExpression(bindings, environment) @@ -69,12 +69,12 @@ and reduceExpressionList = ( /* After reducing each level of expression(Lisp AST), we have a value list to evaluate */ -and reduceValueList = (valueList: list, environment): result< - expressionValue, +and reduceValueList = (valueList: list, environment): result< + internalExpressionValue, '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 +84,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,60 +102,55 @@ 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 ) } let evalUsingBindingsExpression_ = (aExpression, bindings, environment): result< - expressionValue, + internalExpressionValue, 'e, > => reduceExpression(aExpression, bindings, environment) let evaluateUsingOptions = ( - ~environment: option, - ~externalBindings: option, + ~environment: option, + ~externalBindings: option, code: string, -): result => { +): result => { let anEnvironment = Belt.Option.getWithDefault( environment, - ReducerInterface_ExpressionValue.defaultEnvironment, + ReducerInterface_ExternalExpressionValue.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 => { + externalBindings: ReducerInterface_ExternalExpressionValue.externalBindings, + environment: ReducerInterface_ExternalExpressionValue.environment, +): result => { let rAnswer = evaluateUsingOptions( ~environment=Some(environment), ~externalBindings=Some(externalBindings), code, ) switch rAnswer { - | Ok(EvRecord(externalBindings)) => Ok(externalBindings) + | Ok(EvModule(externalBindings)) => Ok(externalBindings) | Ok(_) => Error(Reducer_ErrorValue.RESyntaxError(`Partials must end with an assignment or record`, None)) | Error(err) => err->Error 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..1f6b18b7 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,16 +1,16 @@ -module Bindings = Reducer_Expression_Bindings +module BindingsReplacer = Reducer_Expression_BindingsReplacer module ErrorValue = Reducer_ErrorValue module ExpressionT = Reducer_Expression_T -module ExpressionValue = ReducerInterface.ExpressionValue +module InternalExpressionValue = ReducerInterface_InternalExpressionValue module Result = Belt.Result +module Module = Reducer_Category_Module type bindings = ExpressionT.bindings type context = bindings -type environment = ExpressionValue.environment +type environment = InternalExpressionValue.environment type errorValue = Reducer_ErrorValue.errorValue type expression = ExpressionT.expression -type expressionValue = ExpressionValue.expressionValue -type externalBindings = ReducerInterface_ExpressionValue.externalBindings +type internalExpressionValue = InternalExpressionValue.t type reducerFn = ExpressionT.reducerFn type expressionWithContext = @@ -22,7 +22,7 @@ let callReducer = ( bindings: bindings, environment: environment, reducer: reducerFn, -): result => { +): result => { switch expressionWithContext { | ExpressionNoContext(expr) => // Js.log(`callReducer: bindings ${Bindings.toString(bindings)} expr ${ExpressionT.toString(expr)}`) @@ -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 + ->InternalExpressionValue.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_Bindings.res deleted file mode 100644 index c637581f..00000000 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression_Bindings.res +++ /dev/null @@ -1,72 +0,0 @@ -module ErrorValue = Reducer_ErrorValue -module ExpressionT = Reducer_Expression_T -module ExpressionValue = ReducerInterface.ExpressionValue -module Result = Belt.Result -module Bindings = Reducer_Category_Bindings - -type errorValue = Reducer_ErrorValue.errorValue -type expression = ExpressionT.expression -type expressionValue = ExpressionValue.expressionValue -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< - expression, - errorValue, -> => - switch expression { - | ExpressionT.EValue(value) => - replaceSymbolOnValue(bindings, value)->Result.map(evValue => evValue->ExpressionT.EValue) - | ExpressionT.EList(list) => - switch list { - | list{EValue(EvCall(fName)), ..._args} => - switch isMacroName(fName) { - // A macro reduces itself so we dont dive in it - | true => expression->Ok - | false => replaceSymbolsOnExpressionList(bindings, list) - } - | _ => replaceSymbolsOnExpressionList(bindings, list) - } - } - -and replaceSymbolsOnExpressionList = (bindings, list) => { - let racc = list->Belt.List.reduceReverse(Ok(list{}), (racc, each: expression) => - racc->Result.flatMap(acc => { - replaceSymbols(bindings, each)->Result.flatMap(newNode => { - acc->Belt.List.add(newNode)->Ok - }) - }) - ) - racc->Result.map(acc => acc->ExpressionT.EList) -} -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 - | _ => evValue->Ok - } -and checkIfCallable = (evValue: expressionValue) => - switch evValue { - | EvCall(_) | EvLambda(_) => 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_BindingsReplacer.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression_BindingsReplacer.res new file mode 100644 index 00000000..e96ae4a1 --- /dev/null +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression_BindingsReplacer.res @@ -0,0 +1,53 @@ +module ErrorValue = Reducer_ErrorValue +module ExpressionT = Reducer_Expression_T +module InternalExpressionValue = ReducerInterface_InternalExpressionValue +module Result = Belt.Result +module Module = Reducer_Category_Module + +type errorValue = Reducer_ErrorValue.errorValue +type expression = ExpressionT.expression +type internalExpressionValue = InternalExpressionValue.t +type externalBindings = ReducerInterface_ExternalExpressionValue.externalBindings + +let isMacroName = (fName: string): bool => fName->Js.String2.startsWith("$$") + +let rec replaceSymbols = (bindings: ExpressionT.bindings, expression: expression): result< + expression, + errorValue, +> => + switch expression { + | ExpressionT.EValue(value) => + replaceSymbolOnValue(bindings, value)->Result.map(evValue => evValue->ExpressionT.EValue) + | ExpressionT.EList(list) => + switch list { + | list{EValue(IEvCall(fName)), ..._args} => + switch isMacroName(fName) { + // A macro reduces itself so we dont dive in it + | true => expression->Ok + | false => replaceSymbolsOnExpressionList(bindings, list) + } + | _ => replaceSymbolsOnExpressionList(bindings, list) + } + } + +and replaceSymbolsOnExpressionList = (bindings, list) => { + let racc = list->Belt.List.reduceReverse(Ok(list{}), (racc, each: expression) => + racc->Result.flatMap(acc => { + replaceSymbols(bindings, each)->Result.flatMap(newNode => { + acc->Belt.List.add(newNode)->Ok + }) + }) + ) + racc->Result.map(acc => acc->ExpressionT.EList) +} +and replaceSymbolOnValue = (bindings, evValue: internalExpressionValue) => + switch evValue { + | IEvSymbol(symbol) => Module.getWithDefault(bindings, symbol, evValue)->Ok + | IEvCall(symbol) => Module.getWithDefault(bindings, symbol, evValue)->checkIfCallable + | _ => evValue->Ok + } +and checkIfCallable = (evValue: internalExpressionValue) => + switch evValue { + | IEvCall(_) | IEvLambda(_) => evValue->Ok + | _ => ErrorValue.RENotAFunction(InternalExpressionValue.toString(evValue))->Error + } 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..9fd4a34a 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,28 @@ -module BBindings = Reducer_Expression_Bindings +module BBindingsReplacer = Reducer_Expression_BindingsReplacer module BErrorValue = Reducer_ErrorValue module BExpressionT = Reducer_Expression_T -module BExpressionValue = ReducerInterface.ExpressionValue +module BInternalExpressionValue = 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->BInternalExpressionValue.IEvArray->BExpressionT.EValue -let eArrayString = anArray => anArray->BExpressionValue.EvArrayString->BExpressionT.EValue +let eArrayString = anArray => anArray->BInternalExpressionValue.IEvArrayString->BExpressionT.EValue -let eBindings = (anArray: array<(string, BExpressionValue.expressionValue)>) => - anArray->Js.Dict.fromArray->BExpressionValue.EvRecord->BExpressionT.EValue +let eBindings = (anArray: array<(string, BInternalExpressionValue.t)>) => + anArray->BModule.fromArray->BModule.toExpressionValue->BExpressionT.EValue -let eBool = aBool => aBool->BExpressionValue.EvBool->BExpressionT.EValue +let eBool = aBool => aBool->BInternalExpressionValue.IEvBool->BExpressionT.EValue -let eCall = (name: string): expression => name->BExpressionValue.EvCall->BExpressionT.EValue +let eCall = (name: string): expression => + name->BInternalExpressionValue.IEvCall->BExpressionT.EValue let eFunction = (fName: string, lispArgs: list): expression => { let fn = fName->eCall @@ -27,29 +31,41 @@ let eFunction = (fName: string, lispArgs: list): expression => { let eLambda = ( parameters: array, - context: BExpressionValue.externalBindings, + context: BInternalExpressionValue.nameSpace, expr: expression, ) => { - // Js.log(`eLambda context ${BBindings.externalBindingsToString(context)}`) - BExpressionValue.EvLambda({ + BInternalExpressionValue.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 + BInternalExpressionValue.IEvLambda({ + parameters: parameters, + context: context, + body: FFI(ffiFn)->castExpressionToInternalCode, + })->BExpressionT.EValue +} -let eRecord = aRecord => aRecord->BExpressionValue.EvRecord->BExpressionT.EValue +let eNumber = aNumber => aNumber->BInternalExpressionValue.IEvNumber->BExpressionT.EValue -let eString = aString => aString->BExpressionValue.EvString->BExpressionT.EValue +let eRecord = aMap => aMap->BInternalExpressionValue.IEvRecord->BExpressionT.EValue -let eSymbol = (name: string): expression => name->BExpressionValue.EvSymbol->BExpressionT.EValue +let eString = aString => aString->BInternalExpressionValue.IEvString->BExpressionT.EValue + +let eSymbol = (name: string): expression => + name->BInternalExpressionValue.IEvSymbol->BExpressionT.EValue let eList = (list: list): expression => list->BExpressionT.EList let eBlock = (exprs: list): expression => eFunction("$$_block_$$", exprs) +let eModule = (nameSpace: BInternalExpressionValue.nameSpace): expression => + nameSpace->BInternalExpressionValue.IEvModule->BExpressionT.EValue + let eLetStatement = (symbol: string, valueExpression: expression): expression => eFunction("$_let_$", list{eSymbol(symbol), valueExpression}) @@ -65,7 +81,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->BInternalExpressionValue.IEvSymbol->BExpressionT.EValue let eTypeIdentifier = (name: string): expression => - name->BExpressionValue.EvTypeIdentifier->BExpressionT.EValue + name->BInternalExpressionValue.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..28bdbc02 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,19 +1,24 @@ -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 internalExpressionValue = ReducerInterface_InternalExpressionValue.t +// 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 checkArity = ( + lambdaValue: ExpressionValue.lambdaValue, + args: list, +) => { let argsLength = Belt.List.length(args) let parametersLength = Js.Array2.length(lambdaValue.parameters) if argsLength !== parametersLength { @@ -23,34 +28,44 @@ let checkArity = (lambdaValue: ExpressionValue.lambdaValue, args: list) => +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, environment, reducer: ExpressionT.reducerFn, -): result => { +): 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) + } }) ) } @@ -60,10 +75,10 @@ let doLambdaCall = (lambdaValue: ExpressionValue.lambdaValue, args, environment, let foreignFunctionInterface = ( lambdaValue: ExpressionValue.lambdaValue, - argArray: array, + argArray: array, environment: ExpressionValue.environment, reducer: ExpressionT.reducerFn, -): result => { +): result => { let args = argArray->Belt.List.fromArray applyParametersToLambda(lambdaValue, args, environment, reducer) } 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..2598a9ed 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,11 +1,11 @@ module ExpressionT = Reducer_Expression_T -module ExpressionValue = ReducerInterface.ExpressionValue +module InternalExpressionValue = ReducerInterface_InternalExpressionValue module ExpressionWithContext = Reducer_ExpressionWithContext module Result = Belt.Result -type environment = ExpressionValue.environment +type environment = InternalExpressionValue.environment type expression = ExpressionT.expression -type expressionValue = ExpressionValue.expressionValue +type internalExpressionValue = InternalExpressionValue.t type expressionWithContext = ExpressionWithContext.expressionWithContext let expandMacroCall = ( @@ -26,7 +26,7 @@ let doMacroCall = ( bindings: ExpressionT.bindings, environment: environment, reduceExpression: ExpressionT.reducerFn, -): result => +): result => expandMacroCall( macroExpression, bindings, 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..38910da2 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,28 +7,28 @@ 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 internalExpressionValue = InternalExpressionValue.t +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 + | EValue(internalExpressionValue) // Irreducible built-in value. Reducer should not know the internals. External libraries are responsible +and bindings = InternalExpressionValue.nameSpace type reducerFn = ( expression, bindings, environment, -) => result +) => result /* Converts the expression to String */ 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..d7a267e2 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..30cb2014 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" @@ -17,10 +17,10 @@ let eval__: string => 'a = %raw(`function (expr) { return {value: Mathjs.evaluat /* Call MathJs evaluate and return as a variant */ -let eval = (expr: string): result => { +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/Reducer/Reducer_Peggy/Reducer_Peggy_GeneratedParser.peggy b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Peggy/Reducer_Peggy_GeneratedParser.peggy index 8ed0cf52..f7489c26 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Peggy/Reducer_Peggy_GeneratedParser.peggy +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Peggy/Reducer_Peggy_GeneratedParser.peggy @@ -1,74 +1,7 @@ // Try in https://peggyjs.org/online {{ - var toFunction = { - '-': 'subtract', - '->': 'pipe', - '!=': 'unequal', - '.-': 'dotSubtract', - '.*': 'dotMultiply', - './': 'dotDivide', - '.^': 'dotPow', - '.+': 'dotAdd', - '*': 'multiply', - '/': 'divide', - '&&': 'and', - '^': 'pow', // or xor - '+': 'add', - '<': 'smaller', - '<=': 'smallerEq', - '==': 'equal', - '>': 'larger', - '>=': 'largerEq', - '||': 'or', - 'to': 'credibleIntervalToDistribution', - } - - var unaryToFunction = { - '-': 'unaryMinus', - '!': 'not', - '.-': 'unaryDotMinus', - } - - var postOperatorToFunction = { - '.': '$_atIndex_$', - '()': '$$_applyAll_$$', - '[]': '$_atIndex_$', - } - - function makeFunctionCall(fn, args) { - if (fn === '$$_applyAll_$$') { - // Any list of values is applied from left to right anyway. - // Like in Haskell and Lisp. - // So we remove the redundant $$_applyAll_$$. - if (args[0].type === "Identifier") {args[0].type = "CallIdentifier"} - return nodeExpression(args) - } else { - return nodeExpression([nodeCallIndentifier(fn), ...args]) - } - } - - function apply(fn, arg) { return makeFunctionCall(fn, [arg]); } - function constructArray(elems) { return apply('$_constructArray_$', nodeExpression(elems)); } - function constructRecord(elems) { return apply('$_constructRecord_$', nodeExpression(elems)); } - - function nodeBlock(statements) {return{type: 'Block', statements: statements}} - function nodeBoolean(value) {return {type: 'Boolean', value: value}} - function nodeCallIndentifier(value) {return {type: 'CallIdentifier', value: value}} - function nodeExpression(args) {return {type: 'Expression', nodes: args}} - function nodeFloat(value) {return {type: 'Float', value: value}} - function nodeIdentifier(value) {return {type: 'Identifier', value: value}} - function nodeInteger(value) {return {type: 'Integer', value: value}} - function nodeKeyValue(key, value) { - if (key.type === 'Identifier') {key.type = 'String'} - return {type: 'KeyValue', key: key, value: value}} - function nodeLambda(args, body) {return {type: 'Lambda', args: args, body: body}} - function nodeLetStatment(variable, value) {return {type: 'LetStatement', variable: variable, value: value}} - function nodeModuleIdentifier(value) {return {type: 'ModuleIdentifier', value: value}} - function nodeString(value) {return {type: 'String', value: value}} - function nodeTernary(condition, trueExpression, falseExpression) {return {type: 'Ternary', condition: condition, trueExpression: trueExpression, falseExpression: falseExpression}} - - function nodeTypeIdentifier(typeValue) {return {type: 'TypeIdentifier', value: typeValue}} + const h = require('./helpers'); }} start @@ -80,21 +13,21 @@ zeroOMoreArgumentsBlockOrExpression = innerBlockOrExpression / lambda outerBlock = statements:array_statements finalExpression: (statementSeparator @expression)? { if (finalExpression != null) { statements.push(finalExpression) } - return nodeBlock(statements) } + return h.nodeBlock(statements) } / finalExpression: expression - { return nodeBlock([finalExpression])} + { return h.nodeBlock([finalExpression])} innerBlockOrExpression = quotedInnerBlock / finalExpression: expression - { return nodeBlock([finalExpression])} + { return h.nodeBlock([finalExpression])} quotedInnerBlock = '{' _nl statements:array_statements finalExpression: (statementSeparator @expression) _nl '}' { statements.push(finalExpression) - return nodeBlock(statements) } + return h.nodeBlock(statements) } / '{' _nl finalExpression: expression _nl '}' - { return nodeBlock([finalExpression]) } + { return h.nodeBlock([finalExpression]) } array_statements = head:statement tail:(statementSeparator @array_statements ) @@ -109,12 +42,12 @@ statement letStatement = variable:identifier _ assignmentOp _nl value:zeroOMoreArgumentsBlockOrExpression - { return nodeLetStatment(variable, value) } + { return h.nodeLetStatement(variable, value) } defunStatement = variable:identifier '(' _nl args:array_parameters _nl ')' _ assignmentOp _nl body:innerBlockOrExpression - { var value = nodeLambda(args, body) - return nodeLetStatment(variable, value) } + { var value = h.nodeLambda(args, body) + return h.nodeLetStatement(variable, value) } assignmentOp "assignment" = '=' @@ -128,16 +61,16 @@ ifthenelse = 'if' __nl condition:logicalAdditive __nl 'then' __nl trueExpression:innerBlockOrExpression __nl 'else' __nl falseExpression:(ifthenelse/innerBlockOrExpression) - { return nodeTernary(condition, trueExpression, falseExpression) } + { return h.nodeTernary(condition, trueExpression, falseExpression) } ternary = condition:logicalAdditive _ '?' _nl trueExpression:logicalAdditive _ ':' _nl falseExpression:(ternary/logicalAdditive) - { return nodeTernary(condition, trueExpression, falseExpression) } + { return h.nodeTernary(condition, trueExpression, falseExpression) } logicalAdditive = head:logicalMultiplicative tail:(_ operator:logicalAdditiveOp _nl arg:logicalMultiplicative {return {operator: operator, right: arg}})* { return tail.reduce(function(result, element) { - return makeFunctionCall(toFunction[element.operator], [result, element.right]) + return h.makeFunctionCall(h.toFunction[element.operator], [result, element.right]) }, head)} logicalAdditiveOp "operator" = '||' @@ -146,21 +79,21 @@ logicalAdditive logicalMultiplicative = head:equality tail:(_ operator:logicalMultiplicativeOp _nl arg:equality {return {operator: operator, right: arg}})* { return tail.reduce(function(result, element) { - return makeFunctionCall(toFunction[element.operator], [result, element.right]) + return h.makeFunctionCall(h.toFunction[element.operator], [result, element.right]) }, head)} logicalMultiplicativeOp "operator" = '&&' equality = left:relational _ operator:equalityOp _nl right:relational - { return makeFunctionCall(toFunction[operator], [left, right])} + { return h.makeFunctionCall(h.toFunction[operator], [left, right])} / relational equalityOp "operator" = '=='/'!=' relational = left:additive _ operator:relationalOp _nl right:additive - { return makeFunctionCall(toFunction[operator], [left, right])} + { return h.makeFunctionCall(h.toFunction[operator], [left, right])} / additive relationalOp "operator" = '<='/'<'/'>='/'>' @@ -168,7 +101,7 @@ relational additive = head:multiplicative tail:(_ operator:additiveOp _nl arg:multiplicative {return {operator: operator, right: arg}})* { return tail.reduce(function(result, element) { - return makeFunctionCall(toFunction[element.operator], [result, element.right]) + return h.makeFunctionCall(h.toFunction[element.operator], [result, element.right]) }, head)} additiveOp "operator" = '+' / '-' / '.+' / '.-' @@ -176,7 +109,7 @@ additive multiplicative = head:power tail:(_ operator:multiplicativeOp _nl arg:power {return {operator: operator, right: arg}})* { return tail.reduce(function(result, element) { - return makeFunctionCall(toFunction[element.operator], [result, element.right]) + return h.makeFunctionCall(h.toFunction[element.operator], [result, element.right]) }, head)} multiplicativeOp "operator" = '*' / '/' / '.*' / './' @@ -184,7 +117,7 @@ multiplicative power = head:credibleInterval tail:(_ operator:powerOp _nl arg:credibleInterval {return {operator: operator, right: arg}})* { return tail.reduce(function(result, element) { - return makeFunctionCall(toFunction[element.operator], [result, element.right]) + return h.makeFunctionCall(h.toFunction[element.operator], [result, element.right]) }, head)} powerOp "operator" = '^' / '.^' @@ -192,7 +125,7 @@ power credibleInterval = head:chainFunctionCall tail:(__ operator:credibleIntervalOp __nl arg:chainFunctionCall {return {operator: operator, right: arg}})* { return tail.reduce(function(result, element) { - return makeFunctionCall(toFunction[element.operator], [result, element.right]) + return h.makeFunctionCall(h.toFunction[element.operator], [result, element.right]) }, head)} credibleIntervalOp "operator" = 'to' @@ -200,7 +133,7 @@ credibleInterval chainFunctionCall = head:unary tail:(_ ('->'/'|>') _nl chained:chainedFunction {return chained})* { return tail.reduce(function(result, element) { - return makeFunctionCall(element.fnName, [result, ...element.args]) + return h.makeFunctionCall(element.fnName, [result, ...element.args]) }, head)} chainedFunction @@ -215,7 +148,7 @@ chainFunctionCall unary = unaryOperator:unaryOperator _nl right:(unary/postOperator) - { return apply(unaryToFunction[unaryOperator], right)} + { return h.apply(h.unaryToFunction[unaryOperator], right)} / postOperator unaryOperator "unary operator" @@ -230,12 +163,12 @@ indexedValue collectionElement = head:atom &('['/'('/'.') tail:( - _ '[' _nl arg:expression _nl ']' {return {fn: postOperatorToFunction['[]'], args: [arg]}} - / _ '(' _nl args:array_functionArguments _nl ')' {return {fn: postOperatorToFunction['()'], args: args}} - / '.' arg:$dollarIdentifier {return {fn: postOperatorToFunction['[]'], args: [nodeString(arg)]}} + _ '[' _nl arg:expression _nl ']' {return {fn: h.postOperatorToFunction['[]'], args: [arg]}} + / _ '(' _nl args:array_functionArguments _nl ')' {return {fn: h.postOperatorToFunction['()'], args: args}} + / '.' arg:$dollarIdentifier {return {fn: h.postOperatorToFunction['[]'], args: [h.nodeString(arg)]}} )* { return tail.reduce(function(result, element) { - return makeFunctionCall(element.fn, [result, ...element.args]) + return h.makeFunctionCall(element.fn, [result, ...element.args]) }, head)} array_functionArguments @@ -261,49 +194,49 @@ dollarIdentifierWithModule 'identifier' final:$dollarIdentifier { tail.push(final); return tail.reduce(function(result, element) { - return makeFunctionCall(postOperatorToFunction['[]'], [result, nodeString(element)]) + return h.makeFunctionCall(h.postOperatorToFunction['[]'], [result, h.nodeString(element)]) }, head)} identifier 'identifier' - = ([_a-z]+[_a-z0-9]i*) {return nodeIdentifier(text())} + = ([_a-z]+[_a-z0-9]i*) {return h.nodeIdentifier(text(), location())} unitIdentifier 'identifier' - = ([_a-zA-Z]+[_a-z0-9]i*) {return nodeIdentifier(text())} + = ([_a-zA-Z]+[_a-z0-9]i*) {return h.nodeIdentifier(text(), location())} dollarIdentifier '$identifier' - = ([\$_a-z]+[\$_a-z0-9]i*) {return nodeIdentifier(text())} + = ([\$_a-z]+[\$_a-z0-9]i*) {return h.nodeIdentifier(text(), location())} moduleIdentifier 'identifier' - = ([A-Z]+[_a-z0-9]i*) {return nodeModuleIdentifier(text())} + = ([A-Z]+[_a-z0-9]i*) {return h.nodeModuleIdentifier(text())} string 'string' - = characters:("'" @([^'])* "'") {return nodeString(characters.join(''))} - / characters:('"' @([^"])* '"') {return nodeString(characters.join(''))} + = characters:("'" @([^'])* "'") {return h.nodeString(characters.join(''))} + / characters:('"' @([^"])* '"') {return h.nodeString(characters.join(''))} number = number:(float / integer) unit:unitIdentifier? { if (unit === null) { return number } else - { return apply('fromUnit_'+unit.value, number) + { return h.apply('fromUnit_'+unit.value, number) } } integer 'integer' = d+ !"\." ![e]i - { return nodeInteger(parseInt(text()))} + { return h.nodeInteger(parseInt(text()))} float 'float' = $(((d+ "\." d*) / ("\." d+)) floatExponent? / d+ floatExponent) - { return nodeFloat(parseFloat(text()))} + { return h.nodeFloat(parseFloat(text()))} floatExponent = [e]i '-'? d+ d = [0-9] boolean 'boolean' = ('true'/'false') - { return nodeBoolean(text() === 'true')} + { return h.nodeBoolean(text() === 'true')} valueConstructor = recordConstructor @@ -314,15 +247,15 @@ valueConstructor lambda = '{' _nl '|' _nl args:array_parameters _nl '|' _nl statements:array_statements finalExpression: (statementSeparator @expression) _nl '}' { statements.push(finalExpression) - return nodeLambda(args, nodeBlock(statements)) } + return h.nodeLambda(args, h.nodeBlock(statements)) } / '{' _nl '|' _nl args:array_parameters _nl '|' _nl finalExpression: expression _nl '}' - { return nodeLambda(args, nodeBlock([finalExpression])) } + { return h.nodeLambda(args, h.nodeBlock([finalExpression])) } arrayConstructor 'array' = '[' _nl ']' - { return constructArray([]); } + { return h.constructArray([]); } / '[' _nl args:array_elements _nl ']' - { return constructArray(args); } + { return h.constructArray(args); } array_elements = head:expression tail:(_ ',' _nl @expression)* @@ -330,7 +263,7 @@ arrayConstructor 'array' recordConstructor 'record' = '{' _nl args:array_recordArguments _nl '}' - { return constructRecord(args); } + { return h.constructRecord(args); } array_recordArguments = head:keyValuePair tail:(_ ',' _nl @keyValuePair)* @@ -338,7 +271,7 @@ recordConstructor 'record' keyValuePair = key:expression _ ':' _nl value:expression - { return nodeKeyValue(key, value)} + { return h.nodeKeyValue(key, value)} // Separators @@ -377,30 +310,30 @@ statementSeparator 'statement separator' noArguments = ('(' _nl ')' )? typeIdentifier 'type identifier' - = ([a-z]+[_a-z0-9]i*) {return nodeTypeIdentifier(text())} + = ([a-z]+[_a-z0-9]i*) {return h.nodeTypeIdentifier(text())} typeConstructorIdentifier 'type constructor identifier' - = ([A-Z]+[_a-z0-9]i*) {return nodeTypeIdentifier(text())} + = ([A-Z]+[_a-z0-9]i*) {return h.nodeTypeIdentifier(text())} typeExpression = typePostModifierExpression typePostModifierExpression = head:typeOr tail:(_ '$' _nl @typeModifier)* { return tail.reduce((result, element) => { - return makeFunctionCall('$_typeModifier_'+element.modifier.value+'_$', [result, ...element.args]) + return h.makeFunctionCall('$_typeModifier_'+element.modifier.value+'_$', [result, ...element.args]) }, head) } typeOr = head:typeFunction tail:(_ '|' _nl @typeFunction)* - { return tail.length === 0 ? head : apply('$_typeOr_$', constructArray([head, ...tail])); } + { return tail.length === 0 ? head : h.apply('$_typeOr_$', h.constructArray([head, ...tail])); } typeFunction = head:typeModifierExpression tail:(_ '=>' _nl @typeModifierExpression)* - { return tail.length === 0 ? head : apply( '$_typeFunction_$', constructArray([head, ...tail])); } + { return tail.length === 0 ? head : h.apply( '$_typeFunction_$', h.constructArray([head, ...tail])); } typeModifierExpression = head:basicType tail:(_ '<-' _nl @typeModifier)* { return tail.reduce((result, element) => { - return makeFunctionCall('$_typeModifier_'+element.modifier.value+'_$', [result, ...element.args]) + return h.makeFunctionCall('$_typeModifier_'+element.modifier.value+'_$', [result, ...element.args]) }, head) } @@ -413,10 +346,10 @@ typeModifierExpression = head:basicType tail:(_ '<-' _nl @typeModifier)* basicType = typeConstructor / typeArray / typeRecord / typeInParanthesis / typeIdentifier typeArray = '[' _nl elem:typeExpression _nl ']' - {return apply('$_typeArray_$', elem)} + {return h.apply('$_typeArray_$', elem)} typeRecord = '{' _nl elems:array_typeRecordArguments _nl '}' - { return apply('$_typeRecord_$', constructRecord(elems)); } + { return h.apply('$_typeRecord_$', h.constructRecord(elems)); } array_typeRecordArguments = head:typeKeyValuePair tail:(_ ',' _nl @typeKeyValuePair)* @@ -424,22 +357,22 @@ typeRecord = '{' _nl elems:array_typeRecordArguments _nl '}' typeKeyValuePair = key:identifier _ ':' _nl value:typeExpression - { return nodeKeyValue(key, value)} + { return h.nodeKeyValue(key, value)} typeConstructor = constructor:typeConstructorIdentifier _ '(' _nl args:array_types _nl ')' - { return makeFunctionCall('$_typeConstructor_$', [constructor, constructArray(args)]); } + { return h.makeFunctionCall('$_typeConstructor_$', [constructor, h.constructArray(args)]); } / constructor:typeConstructorIdentifier _ noArguments - { return makeFunctionCall('$_typeConstructor_$', [constructor, constructArray([])]); } + { return h.makeFunctionCall('$_typeConstructor_$', [constructor, h.constructArray([])]); } array_types = head:typeExpression tail:(_ ',' _nl @typeExpression)* { return [head, ...tail]; } typeStatement = typeAliasStatement / typeOfStatement typeAliasStatement = 'type' __nl typeIdentifier:typeIdentifier _nl '=' _nl typeExpression:typeExpression - { return makeFunctionCall('$_typeAlias_$', [typeIdentifier, typeExpression])} + { return h.makeFunctionCall('$_typeAlias_$', [typeIdentifier, typeExpression])} typeOfStatement = identifier:identifier _ ':' _nl typeExpression:typeExpression - { return makeFunctionCall('$_typeOf_$', [identifier, typeExpression])} + { return h.makeFunctionCall('$_typeOf_$', [identifier, typeExpression])} typeInParanthesis = '(' _nl typeExpression:typeExpression _nl ')' {return typeExpression} @@ -447,4 +380,4 @@ typeInParanthesis = '(' _nl typeExpression:typeExpression _nl ')' {return typeEx // TODO: Example of foo = {a: 2, b: 5}; type fooKeys = string $ memberOf(foo->keys) // TODO: Example of memberOf( [1,2,3] ) // TODO: Example of $ -// TODO: Cons(a, list) | EmptyList \ No newline at end of file +// TODO: Cons(a, list) | EmptyList diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Peggy/helpers.ts b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Peggy/helpers.ts new file mode 100644 index 00000000..57b85f9e --- /dev/null +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Peggy/helpers.ts @@ -0,0 +1,215 @@ +import { LocationRange } from "peggy"; + +export const toFunction = { + "-": "subtract", + "->": "pipe", + "!=": "unequal", + ".-": "dotSubtract", + ".*": "dotMultiply", + "./": "dotDivide", + ".^": "dotPow", + ".+": "dotAdd", + "*": "multiply", + "/": "divide", + "&&": "and", + "^": "pow", // or xor + "+": "add", + "<": "smaller", + "<=": "smallerEq", + "==": "equal", + ">": "larger", + ">=": "largerEq", + "||": "or", + to: "credibleIntervalToDistribution", +}; + +export const unaryToFunction = { + "-": "unaryMinus", + "!": "not", + ".-": "unaryDotMinus", +}; + +export const postOperatorToFunction = { + ".": "$_atIndex_$", + "()": "$$_applyAll_$$", + "[]": "$_atIndex_$", +}; + +type NodeBlock = { + type: "Block"; + statements: AnyPeggyNode[]; +}; + +type NodeExpression = { + type: "Expression"; + nodes: AnyPeggyNode[]; +}; + +type NodeFloat = { + type: "Float"; + value: number; +}; + +type NodeInteger = { + type: "Integer"; + value: number; +}; + +type NodeIdentifier = { + type: "Identifier"; + value: string; + location: LocationRange; +}; + +type NodeCallIdentifier = { + type: "CallIdentifier"; + value: string; +}; + +type NodeLetStatement = { + type: "LetStatement"; + variable: NodeIdentifier; + value: AnyPeggyNode; +}; + +type NodeLambda = { + type: "Lambda"; + args: AnyPeggyNode[]; + body: AnyPeggyNode; +}; + +type NodeTernary = { + type: "Ternary"; + condition: AnyPeggyNode; + trueExpression: AnyPeggyNode; + falseExpression: AnyPeggyNode; +}; + +type NodeKeyValue = { + type: "KeyValue"; + key: AnyPeggyNode; + value: AnyPeggyNode; +}; + +type NodeString = { + type: "String"; + value: string; + location?: LocationRange; +}; + +type NodeBoolean = { + type: "Boolean"; + value: boolean; +}; + +export type AnyPeggyNode = + | NodeBlock + | NodeExpression + | NodeFloat + | NodeInteger + | NodeIdentifier + | NodeCallIdentifier + | NodeLetStatement + | NodeLambda + | NodeTernary + | NodeKeyValue + | NodeString + | NodeBoolean; + +export function makeFunctionCall(fn: string, args: AnyPeggyNode[]) { + if (fn === "$$_applyAll_$$") { + // Any list of values is applied from left to right anyway. + // Like in Haskell and Lisp. + // So we remove the redundant $$_applyAll_$$. + if (args[0].type === "Identifier") { + args[0] = { + ...args[0], + type: "CallIdentifier", + }; + } + return nodeExpression(args); + } else { + return nodeExpression([nodeCallIndentifier(fn), ...args]); + } +} + +export function apply(fn: string, arg: AnyPeggyNode) { + return makeFunctionCall(fn, [arg]); +} +export function constructArray(elems: AnyPeggyNode[]) { + return apply("$_constructArray_$", nodeExpression(elems)); +} +export function constructRecord(elems: AnyPeggyNode[]) { + return apply("$_constructRecord_$", nodeExpression(elems)); +} + +export function nodeBlock(statements: AnyPeggyNode[]): NodeBlock { + return { type: "Block", statements }; +} +export function nodeBoolean(value: boolean): NodeBoolean { + return { type: "Boolean", value }; +} +export function nodeCallIndentifier(value: string): NodeCallIdentifier { + return { type: "CallIdentifier", value }; +} +export function nodeExpression(args: AnyPeggyNode[]): NodeExpression { + return { type: "Expression", nodes: args }; +} +export function nodeFloat(value: number): NodeFloat { + return { type: "Float", value }; +} +export function nodeIdentifier( + value: string, + location: LocationRange +): NodeIdentifier { + return { type: "Identifier", value, location }; +} +export function nodeInteger(value: number): NodeInteger { + return { type: "Integer", value }; +} +export function nodeKeyValue( + key: AnyPeggyNode, + value: AnyPeggyNode +): NodeKeyValue { + if (key.type === "Identifier") { + key = { + ...key, + type: "String", + }; + } + return { type: "KeyValue", key, value }; +} +export function nodeLambda( + args: AnyPeggyNode[], + body: AnyPeggyNode +): NodeLambda { + return { type: "Lambda", args, body }; +} +export function nodeLetStatement( + variable: NodeIdentifier, + value: AnyPeggyNode +): NodeLetStatement { + return { type: "LetStatement", variable, value }; +} +export function nodeModuleIdentifier(value: string) { + return { type: "ModuleIdentifier", value }; +} +export function nodeString(value: string): NodeString { + return { type: "String", value }; +} +export function nodeTernary( + condition: AnyPeggyNode, + trueExpression: AnyPeggyNode, + falseExpression: AnyPeggyNode +): NodeTernary { + return { + type: "Ternary", + condition, + trueExpression, + falseExpression, + }; +} + +export function nodeTypeIdentifier(typeValue: string) { + return { type: "TypeIdentifier", value: typeValue }; +} diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface.res index 9c87f57e..ef27130b 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_ExternalExpressionValue 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..e84c26f4 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 -type expressionValue = EV.expressionValue +module IEV = ReducerInterface_InternalExpressionValue +type internalExpressionValue = IEV.t -let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option< - result, +let dispatch = (call: IEV.functionCall, _: DistributionOperation.env): option< + result, > => { switch call { - | ("toString", [EvDate(t)]) => EV.EvString(DateTime.Date.toString(t))->Ok->Some - | ("makeDateFromYear", [EvNumber(year)]) => + | ("toString", [IEvDate(t)]) => IEV.IEvString(DateTime.Date.toString(t))->Ok->Some + | ("makeDateFromYear", [IEvNumber(year)]) => switch DateTime.Date.makeFromYear(year) { - | Ok(t) => EV.EvDate(t)->Ok->Some + | Ok(t) => IEV.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)]) => IEV.IEvDate(DateTime.Date.fromFloat(f))->Ok->Some + | ("toNumber", [IEvDate(f)]) => IEV.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) => IEV.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)]) => + IEV.IEvDate(DateTime.Date.subtractDuration(d1, d2))->Ok->Some + | ("add", [IEvDate(d1), IEvTimeDuration(d2)]) => + IEV.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..838e4375 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_Duration.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_Duration.res @@ -1,33 +1,36 @@ -module EV = ReducerInterface_ExpressionValue -type expressionValue = EV.expressionValue +module IEV = ReducerInterface_InternalExpressionValue +type internalExpressionValue = IEV.t -let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option< - result, +let dispatch = (call: IEV.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)]) => IEV.IEvString(DateTime.Duration.toString(t))->Ok->Some + | ("minutes", [IEvNumber(f)]) => IEV.IEvTimeDuration(DateTime.Duration.fromMinutes(f))->Ok->Some + | ("fromUnit_minutes", [IEvNumber(f)]) => + IEV.IEvTimeDuration(DateTime.Duration.fromMinutes(f))->Ok->Some + | ("hours", [IEvNumber(f)]) => IEV.IEvTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some + | ("fromUnit_hours", [IEvNumber(f)]) => + IEV.IEvTimeDuration(DateTime.Duration.fromHours(f))->Ok->Some + | ("days", [IEvNumber(f)]) => IEV.IEvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some + | ("fromUnit_days", [IEvNumber(f)]) => + IEV.IEvTimeDuration(DateTime.Duration.fromDays(f))->Ok->Some + | ("years", [IEvNumber(f)]) => IEV.IEvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some + | ("fromUnit_years", [IEvNumber(f)]) => + IEV.IEvTimeDuration(DateTime.Duration.fromYears(f))->Ok->Some + | ("toHours", [IEvTimeDuration(f)]) => IEV.IEvNumber(DateTime.Duration.toHours(f))->Ok->Some + | ("toMinutes", [IEvTimeDuration(f)]) => IEV.IEvNumber(DateTime.Duration.toMinutes(f))->Ok->Some + | ("toDays", [IEvTimeDuration(f)]) => IEV.IEvNumber(DateTime.Duration.toDays(f))->Ok->Some + | ("toYears", [IEvTimeDuration(f)]) => IEV.IEvNumber(DateTime.Duration.toYears(f))->Ok->Some + | ("add", [IEvTimeDuration(d1), IEvTimeDuration(d2)]) => + IEV.IEvTimeDuration(DateTime.Duration.add(d1, d2))->Ok->Some + | ("subtract", [IEvTimeDuration(d1), IEvTimeDuration(d2)]) => + IEV.IEvTimeDuration(DateTime.Duration.subtract(d1, d2))->Ok->Some + | ("multiply", [IEvTimeDuration(d1), IEvNumber(d2)]) => + IEV.IEvTimeDuration(DateTime.Duration.multiply(d1, d2))->Ok->Some + | ("divide", [IEvTimeDuration(d1), IEvNumber(d2)]) => + IEV.IEvTimeDuration(DateTime.Duration.divide(d1, d2))->Ok->Some + | ("divide", [IEvTimeDuration(d1), IEvTimeDuration(d2)]) => IEV.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_ExternalExpressionValue.res similarity index 74% rename from packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_ExpressionValue.res rename to packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_ExternalExpressionValue.res index 1313207a..bd5d8a35 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_ExpressionValue.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_ExternalExpressionValue.res @@ -8,8 +8,8 @@ module ErrorValue = Reducer_ErrorValue type internalCode = Object @genType -type rec expressionValue = - | EvArray(array) +type rec externalExpressionValue = + | EvArray(array) | EvArrayString(array) | EvBool(bool) | EvCall(string) // External function call @@ -24,7 +24,7 @@ type rec expressionValue = | EvDeclaration(lambdaDeclaration) | EvTypeIdentifier(string) | EvModule(record) -and record = Js.Dict.t +and record = Js.Dict.t and externalBindings = record and lambdaValue = { parameters: array, @@ -33,7 +33,10 @@ and lambdaValue = { } and lambdaDeclaration = Declaration.declaration -type functionCall = (string, array) +@genType +type t = externalExpressionValue + +type functionCall = (string, array) let rec toString = aValue => switch aValue { @@ -68,26 +71,7 @@ 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 => { +let argsToString = (args: array): string => { args->Js.Array2.map(arg => arg->toString)->Js.Array2.toString } @@ -99,18 +83,6 @@ 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 toStringResultRecord = x => - switch x { - | Ok(a) => `Ok(${toStringRecord(a)})` - | Error(m) => `Error(${ErrorValue.errorToString(m)})` - } - @genType type environment = DistributionOperation.env @@ -141,14 +113,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..3e6172c9 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_ExternalLibrary.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_ExternalLibrary.res @@ -1,6 +1,6 @@ -module ExpressionValue = ReducerInterface_ExpressionValue +module InternalExpressionValue = ReducerInterface_InternalExpressionValue -type expressionValue = ExpressionValue.expressionValue +type internalExpressionValue = InternalExpressionValue.t // module Sample = { // // In real life real libraries should be somewhere else @@ -17,14 +17,14 @@ type expressionValue = ExpressionValue.expressionValue // I expect that it's important to build this first, so it doesn't get recalculated for each tryRegistry() call. let registry = FunctionRegistry_Library.registry -let tryRegistry = ((fnName, args): ExpressionValue.functionCall, env) => { +let tryRegistry = ((fnName, args): InternalExpressionValue.functionCall, env) => { FunctionRegistry_Core.Registry.matchAndRun(~registry, ~fnName, ~args, ~env)->E.O2.fmap( E.R2.errMap(_, s => Reducer_ErrorValue.RETodo(s)), ) } -let dispatch = (call: ExpressionValue.functionCall, environment, chain): result< - expressionValue, +let dispatch = (call: InternalExpressionValue.functionCall, environment, chain): result< + internalExpressionValue, 'e, > => { E.A.O.firstSomeFn([ diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res index 762f4125..6ca0a440 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res @@ -1,5 +1,5 @@ -module ExpressionValue = ReducerInterface_ExpressionValue -type expressionValue = ExpressionValue.expressionValue +module IEV = ReducerInterface_InternalExpressionValue +type internalExpressionValue = IEV.t module Helpers = { let arithmeticMap = r => @@ -18,14 +18,14 @@ module Helpers = { | _ => #Multiply } - let catchAndConvertTwoArgsToDists = (args: array): option<( + let catchAndConvertTwoArgsToDists = (args: array): option<( DistributionTypes.genericDist, 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 } @@ -80,23 +80,28 @@ module Helpers = { )->DistributionOperation.run(~env) } - let parseNumber = (args: expressionValue): Belt.Result.t => + let parseNumber = (args: internalExpressionValue): Belt.Result.t => switch args { - | EvNumber(x) => Ok(x) + | IEvNumber(x) => Ok(x) | _ => Error("Not a number") } - let parseNumberArray = (ags: array): Belt.Result.t, string> => - E.A.fmap(parseNumber, ags) |> E.A.R.firstErrorOrOpen + let parseNumberArray = (ags: array): Belt.Result.t< + array, + string, + > => E.A.fmap(parseNumber, ags) |> E.A.R.firstErrorOrOpen - let parseDist = (args: expressionValue): Belt.Result.t => + let parseDist = (args: internalExpressionValue): Belt.Result.t< + DistributionTypes.genericDist, + string, + > => switch args { - | EvDistribution(x) => Ok(x) - | EvNumber(x) => Ok(GenericDist.fromFloat(x)) + | IEvDistribution(x) => Ok(x) + | IEvNumber(x) => Ok(GenericDist.fromFloat(x)) | _ => Error("Not a distribution") } - let parseDistributionArray = (ags: array): Belt.Result.t< + let parseDistributionArray = (ags: array): Belt.Result.t< array, string, > => E.A.fmap(parseDist, ags) |> E.A.R.firstErrorOrOpen @@ -122,18 +127,18 @@ module Helpers = { } let mixture = ( - args: array, + args: array, ~env: DistributionOperation.env, ): DistributionOperation.outputType => { 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 +147,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 +157,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) @@ -194,20 +199,19 @@ module SymbolicConstructors = { } } -let dispatchToGenericOutput = ( - call: ExpressionValue.functionCall, - env: DistributionOperation.env, -): option => { +let dispatchToGenericOutput = (call: IEV.functionCall, env: DistributionOperation.env): option< + DistributionOperation.outputType, +> => { let (fnName, args) = call switch (fnName, args) { - | ("triangular" as fnName, [EvNumber(f1), EvNumber(f2), EvNumber(f3)]) => + | ("triangular" as fnName, [IEvNumber(f1), IEvNumber(f2), IEvNumber(f3)]) => SymbolicConstructors.threeFloat(fnName) ->E.R.bind(r => r(f1, f2, f3)) ->SymbolicConstructors.symbolicResultToOutput - | ("sample", [EvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist, ~env) - | ("sampleN", [EvDistribution(dist), EvNumber(n)]) => + | ("sample", [IEvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist, ~env) + | ("sampleN", [IEvDistribution(dist), IEvNumber(n)]) => Some(FloatArray(GenericDist.sampleN(dist, Belt.Int.fromFloat(n)))) - | (("mean" | "stdev" | "variance" | "min" | "max" | "mode") as op, [EvDistribution(dist)]) => { + | (("mean" | "stdev" | "variance" | "min" | "max" | "mode") as op, [IEvDistribution(dist)]) => { let fn = switch op { | "mean" => #Mean | "stdev" => #Stdev @@ -219,13 +223,13 @@ let dispatchToGenericOutput = ( } Helpers.toFloatFn(fn, dist, ~env) } - | ("integralSum", [EvDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist, ~env) - | ("toString", [EvDistribution(dist)]) => Helpers.toStringFn(ToString, dist, ~env) - | ("sparkline", [EvDistribution(dist)]) => + | ("integralSum", [IEvDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist, ~env) + | ("toString", [IEvDistribution(dist)]) => Helpers.toStringFn(ToString, dist, ~env) + | ("sparkline", [IEvDistribution(dist)]) => Helpers.toStringFn(ToSparkline(MagicNumbers.Environment.sparklineLength), dist, ~env) - | ("sparkline", [EvDistribution(dist), EvNumber(n)]) => + | ("sparkline", [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,55 +238,62 @@ 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) - | ("scaleMultiply", [EvDistribution(dist), EvNumber(float)]) => + | ("scaleMultiply", [IEvDistribution(dist), IEvNumber(float)]) => Helpers.toDistFn(Scale(#Multiply, float), 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) - | ("quantile", [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) + | ("quantile", [IEvDistribution(dist), IEvNumber(float)]) => Helpers.toFloatFn(#Inv(float), dist, ~env) - | ("toSampleSet", [EvDistribution(dist), EvNumber(float)]) => + | ("toSampleSet", [IEvDistribution(dist), IEvNumber(float)]) => Helpers.toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist, ~env) - | ("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 { @@ -290,15 +301,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", @@ -306,7 +317,7 @@ let dispatchToGenericOutput = ( GenericDist.fromFloat(MagicNumbers.Math.e), ~env, )->Some - | ("log10", [EvDistribution(a)]) => + | ("log10", [IEvDistribution(a)]) => Helpers.twoDiststoDistFn( Algebraic(AsDefault), "log", @@ -314,7 +325,7 @@ let dispatchToGenericOutput = ( GenericDist.fromFloat(10.0), ~env, )->Some - | ("unaryMinus", [EvDistribution(a)]) => + | ("unaryMinus", [IEvDistribution(a)]) => Helpers.twoDiststoDistFn( Algebraic(AsDefault), "multiply", @@ -337,7 +348,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,17 +361,18 @@ let dispatchToGenericOutput = ( } let genericOutputToReducerValue = (o: DistributionOperation.outputType): result< - expressionValue, + internalExpressionValue, 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)) } -let dispatch = (call: ExpressionValue.functionCall, environment) => +let dispatch = (call: IEV.functionCall, environment) => dispatchToGenericOutput(call, environment)->E.O2.fmap(genericOutputToReducerValue) diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.resi b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.resi index 7f26a610..6cccdf17 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.resi +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.resi @@ -1,4 +1,4 @@ let dispatch: ( - ReducerInterface_ExpressionValue.functionCall, - ReducerInterface_ExpressionValue.environment, -) => option> + ReducerInterface_InternalExpressionValue.functionCall, + ReducerInterface_ExternalExpressionValue.environment, +) => option> 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..30de55dd --- /dev/null +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_InternalExpressionValue.res @@ -0,0 +1,259 @@ +module ErrorValue = Reducer_ErrorValue +module ExternalExpressionValue = ReducerInterface_ExternalExpressionValue +module Extra_Array = Reducer_Extra_Array +type internalCode = ExternalExpressionValue.internalCode +type environment = ExternalExpressionValue.environment + +let defaultEnvironment = ExternalExpressionValue.defaultEnvironment + +type rec t = + | 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) + | 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 lambdaValue = { + parameters: array, + context: nameSpace, + body: internalCode, +} +and lambdaDeclaration = Declaration.declaration + +type internalExpressionValue = t + +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 internalExpressionValueType = + | EvtArray + | EvtArrayString + | EvtBool + | EvtCall + | EvtDistribution + | EvtLambda + | EvtNumber + | EvtRecord + | EvtString + | EvtSymbol + | EvtDate + | EvtTimeDuration + | EvtDeclaration + | EvtTypeIdentifier + | EvtModule + +type functionCallSignature = CallSignature(string, array) +type functionDefinitionSignature = + FunctionDefinitionSignature(functionCallSignature, internalExpressionValueType) + +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: internalExpressionValueType): 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: t): ExternalExpressionValue.t => { + 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_ExternalExpressionValue.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.t): t => { + 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_ExternalExpressionValue.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..900e6a2f 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_Number.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_Number.res @@ -1,5 +1,5 @@ -module EV = ReducerInterface_ExpressionValue -type expressionValue = EV.expressionValue +module IEV = ReducerInterface_InternalExpressionValue +type internalExpressionValue = IEV.t module ScientificUnit = { let nameToMultiplier = str => @@ -24,8 +24,8 @@ module ScientificUnit = { } } -let dispatch = (call: EV.functionCall, _: DistributionOperation.env): option< - result, +let dispatch = (call: IEV.functionCall, _: DistributionOperation.env): option< + result, > => { switch call { | ( @@ -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 => IEV.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..b714790a 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_StdLib.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_StdLib.res @@ -1,6 +1,6 @@ -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 0e07337c..ba049bea 100644 --- a/packages/squiggle-lang/src/rescript/SquiggleLibrary/SquiggleLibrary_Math.res +++ b/packages/squiggle-lang/src/rescript/SquiggleLibrary/SquiggleLibrary_Math.res @@ -1,4 +1,4 @@ -module Bindings = Reducer_Category_Bindings +module Bindings = Reducer_Category_Module module Module = Reducer_Category_Module let availableNumbers: array<(string, float)> = [ @@ -14,10 +14,10 @@ let availableNumbers: array<(string, float)> = [ ("tau", 6.283185307179586), ] -let mathBindings: Bindings.ExpressionT.bindings = +let mathBindings: Bindings.t = availableNumbers - ->E.A2.fmap(((name, v)) => (name, ReducerInterface_ExpressionValue.EvNumber(v))) - ->Belt.Map.String.fromArray + ->E.A2.fmap(((name, v)) => (name, ReducerInterface_InternalExpressionValue.IEvNumber(v))) + ->Bindings.fromArray let makeBindings = (previousBindings: Bindings.t): Bindings.t => previousBindings->Bindings.defineModule("Math", mathBindings) diff --git a/packages/squiggle-lang/src/rescript/TypescriptInterface.res b/packages/squiggle-lang/src/rescript/TypescriptInterface.res index 5bc913d8..3d2ce160 100644 --- a/packages/squiggle-lang/src/rescript/TypescriptInterface.res +++ b/packages/squiggle-lang/src/rescript/TypescriptInterface.res @@ -50,10 +50,10 @@ let evaluatePartialUsingExternalBindings = Reducer.evaluatePartialUsingExternalB type externalBindings = Reducer.externalBindings @genType -type expressionValue = ReducerInterface_ExpressionValue.expressionValue +type expressionValue = ReducerInterface_ExternalExpressionValue.t @genType -type recordEV = ReducerInterface_ExpressionValue.record +type recordEV = ReducerInterface_ExternalExpressionValue.record @genType type errorValue = Reducer_ErrorValue.errorValue @@ -77,19 +77,19 @@ let errorValueToString = Reducer_ErrorValue.errorToString let distributionErrorToString = DistributionTypes.Error.toString @genType -type lambdaValue = ReducerInterface_ExpressionValue.lambdaValue +type lambdaValue = ReducerInterface_ExternalExpressionValue.lambdaValue @genType -type lambdaDeclaration = ReducerInterface_ExpressionValue.lambdaDeclaration +type lambdaDeclaration = ReducerInterface_ExternalExpressionValue.lambdaDeclaration @genType let defaultSamplingEnv = DistributionOperation.defaultEnv @genType -type environment = ReducerInterface_ExpressionValue.environment +type environment = ReducerInterface_ExternalExpressionValue.environment @genType -let defaultEnvironment = ReducerInterface_ExpressionValue.defaultEnvironment +let defaultEnvironment = ReducerInterface_ExternalExpressionValue.defaultEnvironment @genType let foreignFunctionInterface = Reducer.foreignFunctionInterface diff --git a/packages/vscode-ext/client/src/extension.ts b/packages/vscode-ext/client/src/extension.ts index 6ba040a4..ee8af595 100644 --- a/packages/vscode-ext/client/src/extension.ts +++ b/packages/vscode-ext/client/src/extension.ts @@ -4,6 +4,7 @@ import * as vscode from "vscode"; import { startClient, stopClient } from "./client"; import { SquiggleEditorProvider } from "./editor"; +import { registerSemanticHighlight } from "./highlight"; import { registerPreviewCommand } from "./preview"; // this method is called when your extension is activated @@ -13,6 +14,8 @@ export function activate(context: vscode.ExtensionContext) { registerPreviewCommand(context); + registerSemanticHighlight(); + startClient(context); } diff --git a/packages/vscode-ext/client/src/highlight.ts b/packages/vscode-ext/client/src/highlight.ts new file mode 100644 index 00000000..39acc262 --- /dev/null +++ b/packages/vscode-ext/client/src/highlight.ts @@ -0,0 +1,96 @@ +import * as vscode from "vscode"; + +import { parse } from "@quri/squiggle-lang"; +import { AnyPeggyNode } from "@quri/squiggle-lang/dist/src/rescript/Reducer/Reducer_Peggy/helpers"; + +const tokenTypes = ["enum", "function", "variable", "property"]; +const tokenModifiers = ["declaration", "documentation"]; +const legend = new vscode.SemanticTokensLegend(tokenTypes, tokenModifiers); + +const convertRange = ( + range: Extract["location"] +) => + new vscode.Range( + new vscode.Position(range.start.line - 1, range.start.column - 1), + new vscode.Position(range.end.line - 1, range.end.column - 1) + ); + +const populateTokensBuilder = ( + tokensBuilder: vscode.SemanticTokensBuilder, + node: AnyPeggyNode + // bindings: { [key: string]: boolean } +) => { + switch (node.type) { + case "Expression": + for (const child of node.nodes) { + populateTokensBuilder(tokensBuilder, child); + } + break; + case "Block": + for (const child of node.statements) { + populateTokensBuilder(tokensBuilder, child); + } + break; + case "LetStatement": + tokensBuilder.push( + convertRange(node.variable.location), + node.value.type === "Lambda" ? "function" : "variable", + ["declaration"] + ); + populateTokensBuilder(tokensBuilder, node.value); + break; + case "Lambda": + for (const arg of node.args) { + populateTokensBuilder(tokensBuilder, arg); + } + populateTokensBuilder(tokensBuilder, node.body); + break; + case "Ternary": + populateTokensBuilder(tokensBuilder, node.condition); + populateTokensBuilder(tokensBuilder, node.trueExpression); + populateTokensBuilder(tokensBuilder, node.falseExpression); + break; + case "KeyValue": + if (node.key.type === "String" && node.key.location) { + tokensBuilder.push(convertRange(node.key.location), "property", [ + "declaration", + ]); + } else { + populateTokensBuilder(tokensBuilder, node.key); + } + populateTokensBuilder(tokensBuilder, node.value); + break; + case "Identifier": + tokensBuilder.push(convertRange(node.location), "variable"); + break; + } +}; + +export const registerSemanticHighlight = () => { + const provider: vscode.DocumentSemanticTokensProvider = { + provideDocumentSemanticTokens( + document: vscode.TextDocument + ): vscode.ProviderResult { + const parseResult = parse(document.getText()); + + const tokensBuilder = new vscode.SemanticTokensBuilder(legend); + if (parseResult.tag === "Ok") { + populateTokensBuilder( + tokensBuilder, + parseResult.value + // {} + ); + } + + return tokensBuilder.build(); + }, + }; + + const selector = { language: "squiggle", scheme: "file" }; + + vscode.languages.registerDocumentSemanticTokensProvider( + selector, + provider, + legend + ); +}; diff --git a/packages/vscode-ext/package.json b/packages/vscode-ext/package.json index effdb398..a14f7acb 100644 --- a/packages/vscode-ext/package.json +++ b/packages/vscode-ext/package.json @@ -139,8 +139,8 @@ "@types/glob": "^7.2.0", "@types/node": "18.x", "@types/vscode": "^1.68.0", - "@typescript-eslint/eslint-plugin": "^5.27.0", - "@typescript-eslint/parser": "^5.27.0", + "@typescript-eslint/eslint-plugin": "^5.30.4", + "@typescript-eslint/parser": "^5.30.4", "eslint": "^8.18.0", "glob": "^8.0.3", "js-yaml": "^4.1.0", diff --git a/packages/vscode-ext/server/src/server.ts b/packages/vscode-ext/server/src/server.ts index dd22a0ff..84637a7d 100644 --- a/packages/vscode-ext/server/src/server.ts +++ b/packages/vscode-ext/server/src/server.ts @@ -13,6 +13,10 @@ import { parse } from "@quri/squiggle-lang"; import { TextDocument } from "vscode-languageserver-textdocument"; +// Documentation: +// - https://code.visualstudio.com/api/language-extensions/language-server-extension-guide +// - https://microsoft.github.io/language-server-protocol/specifications/specification-current + // Create a connection for the server, using Node's IPC as a transport. // Also include all preview / proposed LSP features. let connection = createConnection(ProposedFeatures.all); @@ -23,17 +27,7 @@ documents.onDidChangeContent((change) => { validateSquiggleDocument(change.document); }); -let hasDiagnosticRelatedInformationCapability = false; - connection.onInitialize((params: InitializeParams) => { - const capabilities = params.capabilities; - - hasDiagnosticRelatedInformationCapability = !!( - capabilities.textDocument && - capabilities.textDocument.publishDiagnostics && - capabilities.textDocument.publishDiagnostics.relatedInformation - ); - const result: InitializeResult = { capabilities: { textDocumentSync: TextDocumentSyncKind.Incremental, diff --git a/packages/website/package.json b/packages/website/package.json index cd76fbb7..5369fa96 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -16,10 +16,10 @@ "@docusaurus/preset-classic": "2.0.0-beta.21", "@quri/squiggle-components": "^0.2.20", "base64-js": "^1.5.1", - "clsx": "^1.1.1", + "clsx": "^1.2.0", "hast-util-is-element": "2.1.2", "pako": "^2.0.4", - "prism-react-renderer": "^1.3.3", + "prism-react-renderer": "^1.3.5", "react": "^18.1.0", "react-dom": "^18.2.0", "rehype-katex": "^5", diff --git a/yarn.lock b/yarn.lock index ebeba49e..13393e64 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1239,10 +1239,10 @@ core-js-pure "^3.20.2" regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": - version "7.18.3" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.3.tgz#c7b654b57f6f63cf7f8b418ac9ca04408c4579f4" - integrity sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug== +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.6", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.6.tgz#6a1ef59f838debd670421f8c7f2cbb8da9751580" + integrity sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ== dependencies: regenerator-runtime "^0.13.4" @@ -1852,10 +1852,10 @@ resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-1.0.6.tgz#35dd26987228b39ef2316db3b1245c42eb19e324" integrity sha512-JJCXydOFWMDpCP4q13iEplA503MQO3xLoZiKum+955ZCtHINWnx26CUxVxxFQu/uLb4LW3ge15ZpzIkXKkJ8oQ== -"@hookform/resolvers@^2.9.1": - version "2.9.1" - resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.9.1.tgz#59121e38d8fc95d2fd1f41c9631393cd21e10b65" - integrity sha512-80lyFFcExEB7A09PFnl8k7A3obQyDF6MyO/FThtwetk+MTedYMs08Aqf7mgWnOawFGyz5QF+TZXJSYiIZW2tEg== +"@hookform/resolvers@^2.9.3": + version "2.9.3" + resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.9.3.tgz#13f6934cfe705e24fac094da377e0621adcfc424" + integrity sha512-Eqc/qgjq0VX/TU0a5D2O+yR/kAKflnjaVlYFC1wI2qBm/sgjKTXxv27ijLwHUoHPIF+MUkB/VuQqHJ5DcmbCww== "@humanwhocodes/config-array@^0.9.2": version "0.9.5" @@ -4532,14 +4532,14 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^5.27.0", "@typescript-eslint/eslint-plugin@^5.5.0": - version "5.29.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.29.0.tgz#c67794d2b0fd0b4a47f50266088acdc52a08aab6" - integrity sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w== +"@typescript-eslint/eslint-plugin@^5.30.4", "@typescript-eslint/eslint-plugin@^5.5.0": + version "5.30.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.4.tgz#a46c8c0ab755a936cb63786a6222876ce51675e4" + integrity sha512-xjujQISAIa4HAaos8fcMZXmqkuZqMx6icdxkI88jMM/eNe4J8AuTLYnLK+zdm0mBYLyctdFf//UE4/xFCcQzYQ== dependencies: - "@typescript-eslint/scope-manager" "5.29.0" - "@typescript-eslint/type-utils" "5.29.0" - "@typescript-eslint/utils" "5.29.0" + "@typescript-eslint/scope-manager" "5.30.4" + "@typescript-eslint/type-utils" "5.30.4" + "@typescript-eslint/utils" "5.30.4" debug "^4.3.4" functional-red-black-tree "^1.0.1" ignore "^5.2.0" @@ -4554,14 +4554,14 @@ dependencies: "@typescript-eslint/utils" "5.29.0" -"@typescript-eslint/parser@^5.27.0", "@typescript-eslint/parser@^5.5.0": - version "5.29.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.29.0.tgz#41314b195b34d44ff38220caa55f3f93cfca43cf" - integrity sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw== +"@typescript-eslint/parser@^5.30.4", "@typescript-eslint/parser@^5.5.0": + version "5.30.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.30.4.tgz#659411e8700b22c8d5400798ef24838425bf4567" + integrity sha512-/ge1HtU63wVoED4VnlU2o+FPFmi017bPYpeSrCmd8Ycsti4VSxXrmcpXXm7JpI4GT0Aa7qviabv1PEp6L5bboQ== dependencies: - "@typescript-eslint/scope-manager" "5.29.0" - "@typescript-eslint/types" "5.29.0" - "@typescript-eslint/typescript-estree" "5.29.0" + "@typescript-eslint/scope-manager" "5.30.4" + "@typescript-eslint/types" "5.30.4" + "@typescript-eslint/typescript-estree" "5.30.4" debug "^4.3.4" "@typescript-eslint/scope-manager@5.29.0": @@ -4572,12 +4572,20 @@ "@typescript-eslint/types" "5.29.0" "@typescript-eslint/visitor-keys" "5.29.0" -"@typescript-eslint/type-utils@5.29.0": - version "5.29.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz#241918001d164044020b37d26d5b9f4e37cc3d5d" - integrity sha512-JK6bAaaiJozbox3K220VRfCzLa9n0ib/J+FHIwnaV3Enw/TO267qe0pM1b1QrrEuy6xun374XEAsRlA86JJnyg== +"@typescript-eslint/scope-manager@5.30.4": + version "5.30.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.30.4.tgz#8140efd2bc12d41d74e8af23872a89f3edbe552e" + integrity sha512-DNzlQwGSiGefz71JwaHrpcaAX3zYkEcy8uVuan3YMKOa6qeW/y+7SaD8KIsIAruASwq6P+U4BjWBWtM2O+mwBQ== dependencies: - "@typescript-eslint/utils" "5.29.0" + "@typescript-eslint/types" "5.30.4" + "@typescript-eslint/visitor-keys" "5.30.4" + +"@typescript-eslint/type-utils@5.30.4": + version "5.30.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.30.4.tgz#00ff19073cd01f7d27e9af49ce08d6a69f1e4f01" + integrity sha512-55cf1dZviwwv+unDB+mF8vZkfta5muTK6bppPvenWWCD7slZZ0DEsXUjZerqy7Rq8s3J4SXdg4rMIY8ngCtTmA== + dependencies: + "@typescript-eslint/utils" "5.30.4" debug "^4.3.4" tsutils "^3.21.0" @@ -4586,6 +4594,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.29.0.tgz#7861d3d288c031703b2d97bc113696b4d8c19aab" integrity sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg== +"@typescript-eslint/types@5.30.4": + version "5.30.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.30.4.tgz#3bc99eca8ba3fcfd6a21480e216b09dab81c3999" + integrity sha512-NTEvqc+Vvu8Q6JeAKryHk2eqLKqsr2St3xhIjhOjQv5wQUBhaTuix4WOSacqj0ONWfKVU12Eug3LEAB95GBkMA== + "@typescript-eslint/typescript-estree@5.29.0": version "5.29.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz#e83d19aa7fd2e74616aab2f25dfbe4de4f0b5577" @@ -4599,7 +4612,20 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.29.0", "@typescript-eslint/utils@^5.13.0": +"@typescript-eslint/typescript-estree@5.30.4": + version "5.30.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.4.tgz#ac4be8a2f8fb1f1c3b346d5992a36163121ddb3f" + integrity sha512-V4VnEs6/J9/nNizaA12IeU4SAeEYaiKr7XndLNfV5+3zZSB4hIu6EhHJixTKhvIqA+EEHgBl6re8pivBMLLO1w== + dependencies: + "@typescript-eslint/types" "5.30.4" + "@typescript-eslint/visitor-keys" "5.30.4" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.29.0": version "5.29.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.29.0.tgz#775046effd5019667bd086bcf326acbe32cd0082" integrity sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A== @@ -4611,6 +4637,18 @@ eslint-scope "^5.1.1" eslint-utils "^3.0.0" +"@typescript-eslint/utils@5.30.4", "@typescript-eslint/utils@^5.13.0": + version "5.30.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.30.4.tgz#07a2b7ce80b2527ea506829f190591b76c70ba9f" + integrity sha512-a+GQrJzOUhn4WT1mUumXDyam+22Oo4c5K/jnZ+6r/4WTQF3q8e4CsC9PLHb4SnOClzOqo/5GLZWvkE1aa5UGKQ== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.30.4" + "@typescript-eslint/types" "5.30.4" + "@typescript-eslint/typescript-estree" "5.30.4" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + "@typescript-eslint/visitor-keys@5.29.0": version "5.29.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz#7a4749fa7ef5160c44a451bf060ac1dc6dfb77ee" @@ -4619,6 +4657,14 @@ "@typescript-eslint/types" "5.29.0" eslint-visitor-keys "^3.3.0" +"@typescript-eslint/visitor-keys@5.30.4": + version "5.30.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.4.tgz#b4969df1a440cc999d4bb7f7b7932dce05537089" + integrity sha512-ulKGse3mruSc8x6l8ORSc6+1ORyJzKmZeIaRTu/WpaF/jx3vHvEn5XZUKF9XaVg2710mFmTAUlLcLYLPp/Zf/Q== + dependencies: + "@typescript-eslint/types" "5.30.4" + eslint-visitor-keys "^3.3.0" + "@webassemblyjs/ast@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" @@ -6580,10 +6626,10 @@ clone@~2.1.2: resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== -clsx@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" - integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== +clsx@^1.1.1, clsx@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.0.tgz#b0e415ea7537dbac01b169c5cec1caeb11d86566" + integrity sha512-EPRP7XJsM1y0iCU3Z7C7jFKdQboXSeHgEfzQUTlz7m5NP3hDrlz48aUsmNGp4pC+JOW9WA3vIRqlYuo/bl4Drw== co@^4.6.0: version "4.6.0" @@ -8713,10 +8759,10 @@ fast-check@^2.17.0: dependencies: pure-rand "^5.0.1" -fast-check@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-3.0.0.tgz#6ea28d584e9ffebd7ecd0f06c163cd6af593ecfd" - integrity sha512-uujtrFJEQQqnIMO52ARwzPcuV4omiL1OJBUBLE9WnNFeu0A97sREXDOmCIHY+Z6KLVcemUf09rWr0q0Xy/Y/Ew== +fast-check@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-3.0.1.tgz#b9e7b57c4643a4e62893aca85e21c270591d0eac" + integrity sha512-AriFDYpYVOBynpPZq/quxSLumFOo2hPB2H5Nz2vc1QlNfjOaA62zX8USNXcOY5nwKHEq7lZ84dG9M1W+LAND1g== dependencies: pure-rand "^5.0.1" @@ -11914,12 +11960,12 @@ markdown-it@^8.3.1: mdurl "^1.0.1" uc.micro "^1.0.5" -mathjs@^10.6.0: - version "10.6.1" - resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-10.6.1.tgz#95b34178eed65cbf7a63d35c468ad3ac912f7ddf" - integrity sha512-8iZp6uUKKBoCFoUHze9ydsrSji9/IOEzMhwURyoQXaLL1+ILEZnraw4KzZnUBt/XN6lPJPV+7JO94oil3AmosQ== +mathjs@^10.6.4: + version "10.6.4" + resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-10.6.4.tgz#1b87a1268781d64f0c8b4e5e1b36cf7ecf58bb05" + integrity sha512-omQyvRE1jIy+3k2qsqkWASOcd45aZguXZDckr3HtnTYyXk5+2xpVfC3kATgbO2Srjxlqww3TVdhD0oUdZ/hiFA== dependencies: - "@babel/runtime" "^7.18.3" + "@babel/runtime" "^7.18.6" complex.js "^2.1.1" decimal.js "^10.3.1" escape-latex "^1.2.0" @@ -14092,10 +14138,10 @@ pretty-time@^1.1.0: resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e" integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA== -prism-react-renderer@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.3.3.tgz#9b5a4211a6756eee3c96fee9a05733abc0b0805c" - integrity sha512-Viur/7tBTCH2HmYzwCHmt2rEFn+rdIWNIINXyg0StiISbDiIhHKhrFuEK8eMkKgvsIYSjgGqy/hNyucHp6FpoQ== +prism-react-renderer@^1.3.3, prism-react-renderer@^1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.3.5.tgz#786bb69aa6f73c32ba1ee813fbe17a0115435085" + integrity sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg== prismjs@^1.27.0, prismjs@^1.28.0: version "1.28.0" @@ -14523,10 +14569,10 @@ react-helmet-async@*, react-helmet-async@^1.3.0: react-fast-compare "^3.2.0" shallowequal "^1.1.0" -react-hook-form@^7.32.2: - version "7.32.2" - resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.32.2.tgz#58ec2ab0239ce97969baa2faa03ced13fae913ac" - integrity sha512-F1A6n762xaRhvtQH5SkQQhMr19cCkHZYesTcKJJeNmrphiZp/cYFTIzC05FnQry0SspM54oPJ9tXFXlzya8VNQ== +react-hook-form@^7.33.0: + version "7.33.0" + resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.33.0.tgz#44a87ddd630f00ebeb0f15aa978f69ca74b8a77b" + integrity sha512-h8XoeUHQs1Snx1s/sSvM+eVTSKkWQt8TcrbL+3/Rt5gugxpy4ueL5ZZkubffyNpUyyTz0qM0kwOi2c+JgGTjLA== react-inspector@^5.1.0: version "5.1.1"