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