diff --git a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_test.res b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_test.res index 466a8770..b4ede1a4 100644 --- a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_test.res +++ b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_test.res @@ -2,7 +2,6 @@ module ExternalExpressionValue = ReducerInterface_ExternalExpressionValue module Project = ReducerProject module Bindings = Reducer_Bindings -module Continuation = ReducerInterface_Value_Continuation open Jest open Expect diff --git a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_test.res b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_test.res new file mode 100644 index 00000000..07f1e973 --- /dev/null +++ b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_test.res @@ -0,0 +1,96 @@ +@@warning("-44") +module ExternalExpressionValue = ReducerInterface_ExternalExpressionValue +module Project = ReducerProject +module Bindings = Reducer_Bindings + +open Jest +open Expect +open Expect.Operators + +describe("ReducerProject Tutorial", () => { + describe("Single source", () => { + /* +Case "Running a single source". +*/ + test("run", () => { + /* Let's start with running a single source and getting Result as well as the Bindings + First you need to create a project. A project is a collection of sources. + Project takes care of the dependencies between the sources, correct compilation and run order. + You can run any source in the project. It will be compiled and run if it is not already done else already existing results will be presented. + The dependencies will be automatically compiled and run. So you don't need to worry about that in a multi source project. + In summary you issue a run command on the whole project or on a specific source to ensure that there is a result for that source. + */ + let project = Project.createProject() + /* Every source has a name. This is used for debugging, dependencies and error messages. */ + Project.setSource(project, "main", "1 + 2") + /* Let's run "main" source. */ + project->Project.run("main") + /* Now you have a result for "main" source. + Running one by one is necessary for UI to navigate among the sources and to see the results by source. + And you're free to run any source you want. + You will look at the results of this source and you don't want to run the others if not required. + */ + + /* However, you could also run the whole project. + If you have all the sources, you can always run the whole project. + Dependencies and recompiling on demand will be taken care of by the project. + */ + project->Project.runAll + + /* Either with run or runAll you executed the project. + You can get the result of a specific source by calling getResult for that source. + You can get the bindings of a specific source by calling getBindings for that source. + If there is any runtime error, getResult will return the error. + + Note that getResult returns None if the source has not been run. + Getting None means you have forgotten to run the source. + */ + let result = project->Project.getExternalResult("main") + let bindings = project->Project.getExternalBindings("main") + + /* Let's display the result and bindings */ + ( + result->ExternalExpressionValue.toStringOptionResult, + bindings->ExternalExpressionValue.EvModule->ExternalExpressionValue.toString, + )->expect == ("Ok(3)", "@{}") + /* You've got 3 with empty bindings. */ + }) + + test("run summary", () => { + let project = Project.createProject() + Project.setSource(project, "main", "1 + 2") + Project.runAll(project) + let result = Project.getExternalResult(project, "main") + let bindings = Project.getExternalBindings(project, "main") + /* Now you have external bindings and external result. */ + ( + result->ExternalExpressionValue.toStringOptionResult, + bindings->ExternalExpressionValue.EvModule->ExternalExpressionValue.toString, + )->expect == ("Ok(3)", "@{}") + }) + + test("run with an environment", () => { + /* Running the source code like above allows you to set a custom environment */ + let project = Project.createProject() + + /* Optional. Set your custom environment anytime before running */ + Project.setEnvironment(project, ExternalExpressionValue.defaultEnvironment) + + Project.setSource(project, "main", "1 + 2") + Project.runAll(project) + let result = Project.getExternalResult(project, "main") + let _bindings = Project.getExternalBindings(project, "main") + result->ExternalExpressionValue.toStringOptionResult->expect == "Ok(3)" + }) + + test("shortcut", () => { + /* If you are running single source without includes and you don't need a custom environment, you can use the shortcut. */ + /* Examples above was to prepare you for the multi source tutorial. */ + let (result, bindings) = Project.evaluate("1+2") + ( + result->ExternalExpressionValue.toStringResult, + bindings->ExternalExpressionValue.EvModule->ExternalExpressionValue.toString, + )->expect == ("Ok(3)", "@{}") + }) + }) +}) diff --git a/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject.res b/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject.res index 0b9f9385..1bba0aff 100644 --- a/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject.res +++ b/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject.res @@ -202,10 +202,11 @@ module Private = { let project = createProject() setSource(project, "main", sourceCode) runAll(project) - ( - getResult(project, "main")->Belt.Option.getWithDefault(IEvVoid->Ok), - getContinuation(project, "main"), - ) + let those = project->getContinuation("main") + let these = project->getStdLib + let ofUser = Continuation.minus(those, these) + + (getResult(project, "main")->Belt.Option.getWithDefault(IEvVoid->Ok), ofUser) } } @@ -409,6 +410,12 @@ let evaluate = (sourceCode: string): ('r, 'b) => { ) } +@genType +let setEnvironment = ( + this: reducerProject, + environment: ExternalExpressionValue.environment, +): unit => this->T.Private.castToInternalProject->Private.setEnvironment(environment) + @genType let foreignFunctionInterface = ( lambdaValue: ExternalExpressionValue.lambdaValue,