diff --git a/packages/squiggle-lang/__tests__/Reducer/Reducer_Module/Reducer_Module_defineFFI_test.res b/packages/squiggle-lang/__tests__/Reducer/Reducer_Module/Reducer_Module_test.res similarity index 83% rename from packages/squiggle-lang/__tests__/Reducer/Reducer_Module/Reducer_Module_defineFFI_test.res rename to packages/squiggle-lang/__tests__/Reducer/Reducer_Module/Reducer_Module_test.res index a06c7a57..69fca252 100644 --- a/packages/squiggle-lang/__tests__/Reducer/Reducer_Module/Reducer_Module_defineFFI_test.res +++ b/packages/squiggle-lang/__tests__/Reducer/Reducer_Module/Reducer_Module_test.res @@ -22,6 +22,13 @@ module FooImplementation = { let makeFoo = (a: string, b: string, _environment): string => `I am ${a}-foo and I am ${b}-foo` let makeBar = (a: float, b: float, _environment): string => `I am ${a->Js.Float.toString}-bar and I am ${b->Js.Float.toString}-bar` + // You can also define functions that has their internal errors + let makeReturningError = (_a: float, _b: float, _environment): result => + if false { + 0.->Ok + } else { + ErrorValue.RETodo("test error")->Error + } } // There is a potential for type modules to define lift functions @@ -38,6 +45,17 @@ module FooFFI = { | [IEvNumber(a), IEvNumber(b)] => FooImplementation.makeBar(a, b, environment)->IEvString->Some | _ => None } + let makeReturningError: ExpressionT.optionFfiFnReturningResult = ( + args: array, + environment, + ) => + switch args { + | [IEvNumber(a), IEvNumber(b)] => + FooImplementation.makeReturningError(a, b, environment) + ->Belt.Result.map(v => v->InternalExpressionValue.IEvNumber) + ->Some + | _ => None + } } let fooModule: Module.t = @@ -47,6 +65,7 @@ let fooModule: Module.t = ->Module.defineBool("fooBool", FooImplementation.fooBool) ->Module.defineFunction("makeFoo", FooFFI.makeFoo) ->Module.defineFunction("makeBar", FooFFI.makeBar) + ->Module.defineFunctionReturningResult("makeReturningError", FooFFI.makeReturningError) let makeBindings = (prevBindings: Bindings.t): Bindings.t => prevBindings->Module.defineModule("Foo", fooModule) diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression_T.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression_T.res index dee70c88..bf4d0170 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression_T.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression_T.res @@ -72,6 +72,10 @@ type ffiFn = ( ) => result type optionFfiFn = (array, environment) => option +type optionFfiFnReturningResult = ( + array, + environment, +) => option> type expressionOrFFI = | NotFFI(expression) diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Module/Reducer_Module.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Module/Reducer_Module.res index 62f9d8c7..34c304f9 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Module/Reducer_Module.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Module/Reducer_Module.res @@ -126,6 +126,17 @@ let functionNotFoundErrorFFIFn = (functionName: string): ExpressionT.ffiFn => { } } +let convertOptionToFfiFnReturningResult = ( + myFunctionName: string, + myFunction: ExpressionT.optionFfiFnReturningResult, +): ExpressionT.ffiFn => { + (args: array, environment) => { + myFunction(args, environment)->Belt.Option.getWithDefault( + functionNotFoundErrorFFIFn(myFunctionName)(args, environment), + ) + } +} + let convertOptionToFfiFn = ( myFunctionName: string, myFunction: ExpressionT.optionFfiFn, @@ -159,4 +170,15 @@ let defineFunction = (nameSpace: t, identifier: string, value: ExpressionT.optio nameSpace->define(identifier, convertOptionToFfiFn(identifier, value)->eLambdaFFIValue) } -let emptyStdLib: t = emptyModule->defineBool("stdlib", true) +let defineFunctionReturningResult = ( + nameSpace: t, + identifier: string, + value: ExpressionT.optionFfiFnReturningResult, +): t => { + nameSpace->define( + identifier, + convertOptionToFfiFnReturningResult(identifier, value)->eLambdaFFIValue, + ) +} + +let emptyStdLib: t = emptyModule->defineBool("_standardLibrary", true)