diff --git a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_includes_test.res b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_includes_test.res index d2dbafb3..5f545f9d 100644 --- a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_includes_test.res +++ b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_includes_test.res @@ -27,7 +27,7 @@ x=1`, let mainIncludes = Project.getIncludes(project, "main") switch mainIncludes { | Ok(includes) => expect(includes) == ["common"] - | Error(error) => fail(error->Reducer_ErrorValue.errorToString) + | Error(error) => fail(error.error->Reducer_ErrorValue.errorToString) } }) let internalProject = project->Project.T.Private.castToInternalProject @@ -63,7 +63,7 @@ x=1`, let mainIncludes = Project.getIncludes(project, "main") switch mainIncludes { | Ok(includes) => expect(includes) == ["common", "myModule"] - | Error(error) => fail(error->Reducer_ErrorValue.errorToString) + | Error(error) => fail(error.error->Reducer_ErrorValue.errorToString) } }) @@ -106,7 +106,7 @@ x=1`, let mainIncludes = Project.getIncludes(project, "main") switch mainIncludes { | Ok(includes) => expect(includes) == ["common", "common2", "myModule"] - | Error(error) => fail(error->Reducer_ErrorValue.errorToString) + | Error(error) => fail(error.error->Reducer_ErrorValue.errorToString) } }) let internalProject = project->Project.T.Private.castToInternalProject diff --git a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_test.res b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_test.res index 1dd215b9..f8e48aa5 100644 --- a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_test.res +++ b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_test.res @@ -11,7 +11,7 @@ open Expect.Operators let runFetchResult = (project, sourceId) => { Project.run(project, sourceId) - Project.getResult(project, sourceId)->InternalExpressionValue.toStringResult + Project.getResult(project, sourceId)->InternalExpressionValue.toStringWithSourceResult } let runFetchFlatBindings = (project, sourceId) => { diff --git a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_1_test.res b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_1_test.res index 92a4932f..4e715969 100644 --- a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_1_test.res +++ b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_1_test.res @@ -50,7 +50,7 @@ Case "Running a single source". /* Let's display the result and bindings */ ( - result->InternalExpressionValue.toStringResult, + result->InternalExpressionValue.toStringWithSourceResult, bindings->InternalExpressionValue.toStringBindings, )->expect == ("Ok(3)", "@{}") /* You've got 3 with empty bindings. */ @@ -64,7 +64,7 @@ Case "Running a single source". let bindings = Project.getBindings(project, "main")->Bindings.removeResult /* Now you have external bindings and external result. */ ( - result->InternalExpressionValue.toStringResult, + result->InternalExpressionValue.toStringWithSourceResult, bindings->InternalExpressionValue.IEvBindings->InternalExpressionValue.toString, )->expect == ("Ok(3)", "@{}") }) @@ -80,7 +80,7 @@ Case "Running a single source". Project.runAll(project) let result = Project.getResult(project, "main") let _bindings = Project.getBindings(project, "main") - result->InternalExpressionValue.toStringResult->expect == "Ok(3)" + result->InternalExpressionValue.toStringWithSourceResult->expect == "Ok(3)" }) test("shortcut", () => { @@ -88,7 +88,7 @@ Case "Running a single source". /* Examples above was to prepare you for the multi source tutorial. */ let (result, bindings) = Project.evaluate("1+2") ( - result->InternalExpressionValue.toStringResult, + result->InternalExpressionValue.toStringWithSourceResult, bindings->Bindings.removeResult->InternalExpressionValue.toStringBindings, )->expect == ("Ok(3)", "@{}") }) diff --git a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_2_multisource_test.res b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_2_multisource_test.res index 80c73c9e..85e3b1a8 100644 --- a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_2_multisource_test.res +++ b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_2_multisource_test.res @@ -32,7 +32,7 @@ describe("ReducerProject Tutorial", () => { let bindings3 = Project.getBindings(project, "source3")->Bindings.removeResult ( - result3->InternalExpressionValue.toStringResult, + result3->InternalExpressionValue.toStringWithSourceResult, bindings3->InternalExpressionValue.toStringBindings, )->expect == ("Ok(())", "@{x: 1,y: 2,z: 3}") }) @@ -58,7 +58,7 @@ describe("ReducerProject Tutorial", () => { let bindings3 = Project.getBindings(project, "source3")->Bindings.removeResult ( - result3->InternalExpressionValue.toStringResult, + result3->InternalExpressionValue.toStringWithSourceResult, bindings3->InternalExpressionValue.toStringBindings, )->expect == ("Ok(())", "@{x: 1,y: 2,z: 3}") }) @@ -94,7 +94,7 @@ describe("ReducerProject Tutorial", () => { let bindings3 = Project.getBindings(project, "source3")->Bindings.removeResult ( - result3->InternalExpressionValue.toStringResult, + result3->InternalExpressionValue.toStringWithSourceResult, bindings3->InternalExpressionValue.toStringBindings, )->expect == ("Ok(())", "@{x: 1,y: 2,z: 3}") /* diff --git a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_3_includes_test.res b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_3_includes_test.res index 12c14468..3c4b4403 100644 --- a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_3_includes_test.res +++ b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_3_includes_test.res @@ -38,7 +38,7 @@ Here we will finally proceed to a real life scenario. */ /* Parse includes has set the includes */ switch Project.getIncludes(project, "main") { | Ok(includes) => includes->expect == ["common"] - | Error(err) => err->Reducer_ErrorValue.errorToString->fail + | Error(err) => err.error->Reducer_ErrorValue.errorToString->fail } /* If the includes cannot be parsed then you get a syntax error. Otherwise you get the includes. @@ -87,7 +87,7 @@ Here we will finally proceed to a real life scenario. */ let rIncludes = Project.getIncludes(project, sourceName) switch rIncludes { /* Maybe there is an include syntax error */ - | Error(err) => err->Reducer_ErrorValue.errorToString->Js.Exn.raiseError + | Error(err) => err.error->Reducer_ErrorValue.errorToString->Js.Exn.raiseError | Ok(includes) => Belt.Array.forEach(includes, newIncludeName => { @@ -146,7 +146,7 @@ Here we will finally proceed to a real life scenario. */ /* And see the result and bindings.. */ test("recursive includes", () => { ( - result->InternalExpressionValue.toStringResult, + result->InternalExpressionValue.toStringWithSourceResult, bindings->Bindings.removeResult->InternalExpressionValue.toStringBindings, )->expect == ("Ok(6)", "@{doubleX: 2,x: 1,y: 2,z: 3}") /* Everything as expected */ @@ -172,7 +172,7 @@ Here we will finally proceed to a real life scenario. */ test("getIncludes", () => { switch Project.getIncludes(project, "main") { | Ok(includes) => includes->expect == ["common"] - | Error(err) => err->Reducer_ErrorValue.errorToString->fail + | Error(err) => err.error->Reducer_ErrorValue.errorToString->fail } }) }) diff --git a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_4_injecting_user_values.res b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_4_injecting_user_values.res index 38d655c1..2465caf3 100644 --- a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_4_injecting_user_values.res +++ b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_4_injecting_user_values.res @@ -30,7 +30,7 @@ describe("ReducerProject Tutorial", () => { /* We can now run the project */ Project.runAll(project) let result = Project.getResult(project, "main") - result->InternalExpressionValue.toStringResult->expect == "Ok(6)" + result->InternalExpressionValue.toStringWithSourceResult->expect == "Ok(6)" }) }) diff --git a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_5_calling_functions.res b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_5_calling_functions.res index 7e2471b5..c33ac869 100644 --- a/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_5_calling_functions.res +++ b/packages/squiggle-lang/__tests__/ReducerProject/ReducerProject_tutorial_5_calling_functions.res @@ -32,7 +32,7 @@ describe("ReducerProject Tutorial", () => { test("userResults", () => { let userResultsAsString = Belt.Array.map(userResults, aResult => - aResult->InternalExpressionValue.toStringResult + aResult->InternalExpressionValue.toStringWithSourceResult ) userResultsAsString->expect == ["Ok(2)", "Ok(4)", "Ok(6)", "Ok(8)", "Ok(10)"] }) diff --git a/packages/squiggle-lang/src/js/SqError.ts b/packages/squiggle-lang/src/js/SqError.ts index 317fde4f..159900d0 100644 --- a/packages/squiggle-lang/src/js/SqError.ts +++ b/packages/squiggle-lang/src/js/SqError.ts @@ -1,17 +1,13 @@ import * as RSErrorValue from "../rescript/ForTS/ForTS_Reducer_ErrorValue.gen"; export class SqError { - constructor(private _value: RSErrorValue.reducerErrorValue) {} + constructor(private _value: RSErrorValue.reducerErrorValueWithSource) {} toString() { return RSErrorValue.toString(this._value); } - static createTodoError(v: string) { - return new SqError(RSErrorValue.createTodoError(v)); - } - - static createOtherError(v: string) { - return new SqError(RSErrorValue.createOtherError(v)); + getSource() { + return RSErrorValue.getSource(this._value); } } diff --git a/packages/squiggle-lang/src/js/SqProject.ts b/packages/squiggle-lang/src/js/SqProject.ts index 4c2dea7c..e85d5b32 100644 --- a/packages/squiggle-lang/src/js/SqProject.ts +++ b/packages/squiggle-lang/src/js/SqProject.ts @@ -1,5 +1,5 @@ import * as RSProject from "../rescript/ForTS/ForTS_ReducerProject.gen"; -import { reducerErrorValue } from "../rescript/ForTS/ForTS_Reducer_ErrorValue.gen"; +import { reducerErrorValueWithSource } from "../rescript/ForTS/ForTS_Reducer_ErrorValue.gen"; import { environment } from "../rescript/ForTS/ForTS_Distribution/ForTS_Distribution_Environment.gen"; import { SqError } from "./SqError"; import { SqModule } from "./SqModule"; @@ -50,7 +50,7 @@ export class SqProject { return resultMap2( RSProject.getIncludes(this._value, sourceId), (a) => a, - (v: reducerErrorValue) => new SqError(v) + (v: reducerErrorValueWithSource) => new SqError(v) ); } @@ -104,7 +104,7 @@ export class SqProject { items: [], }) ), - (v: reducerErrorValue) => new SqError(v) + (v: reducerErrorValueWithSource) => new SqError(v) ); } diff --git a/packages/squiggle-lang/src/rescript/ForTS/ForTS_ReducerProject.res b/packages/squiggle-lang/src/rescript/ForTS/ForTS_ReducerProject.res index 18838899..e9a3892e 100644 --- a/packages/squiggle-lang/src/rescript/ForTS/ForTS_ReducerProject.res +++ b/packages/squiggle-lang/src/rescript/ForTS/ForTS_ReducerProject.res @@ -1,6 +1,7 @@ @genType type reducerProject = ReducerProject_T.t //re-export type reducerErrorValue = ForTS_Reducer_ErrorValue.reducerErrorValue //use +type reducerErrorValueWithSource = ForTS_Reducer_ErrorValue.reducerErrorValueWithSource //use type squiggleValue = ForTS_SquiggleValue.squiggleValue //use type squiggleValue_Module = ForTS_SquiggleValue_Module.squiggleValue_Module //use @@ -102,7 +103,7 @@ To set the includes one first has to call "parseIncludes". The parsed includes o @genType let getIncludes = (project: reducerProject, sourceId: string): result< array, - reducerErrorValue, + reducerErrorValueWithSource, > => project->T.Private.castToInternalProject->Private.getIncludes(sourceId) /* Other sources contributing to the global namespace of this source. */ @@ -200,7 +201,7 @@ Get the result after running this source file or the project @genType let getResult = (project: reducerProject, sourceId: string): result< squiggleValue, - reducerErrorValue, + reducerErrorValueWithSource, > => project->T.Private.castToInternalProject->Private.getResult(sourceId) /* @@ -210,7 +211,7 @@ The source has to be include free */ @genType let evaluate = (sourceCode: string): ( - result, + result, squiggleValue_Module, ) => Private.evaluate(sourceCode) diff --git a/packages/squiggle-lang/src/rescript/ForTS/ForTS_Reducer_ErrorValue.res b/packages/squiggle-lang/src/rescript/ForTS/ForTS_Reducer_ErrorValue.res index d4a8059b..ade7a50f 100644 --- a/packages/squiggle-lang/src/rescript/ForTS/ForTS_Reducer_ErrorValue.res +++ b/packages/squiggle-lang/src/rescript/ForTS/ForTS_Reducer_ErrorValue.res @@ -1,12 +1,13 @@ @genType type reducerErrorValue = Reducer_ErrorValue.errorValue //alias +@genType type reducerErrorValueWithSource = Reducer_ErrorValue.errorValueWithSource //alias @genType type syntaxErrorLocation = Reducer_ErrorValue.syntaxErrorLocation //alias @genType -let toString = (e: reducerErrorValue): string => Reducer_ErrorValue.errorToString(e) +let toString = (e: reducerErrorValueWithSource): string => Reducer_ErrorValue.errorToString(e.error) @genType -let getLocation = (e: reducerErrorValue): option => - switch e { +let getLocation = (e: reducerErrorValueWithSource): option => + switch e.error { | RESyntaxError(_, optionalLocation) => optionalLocation | _ => None } @@ -16,3 +17,6 @@ let createTodoError = (v: string) => Reducer_ErrorValue.RETodo(v) @genType let createOtherError = (v: string) => Reducer_ErrorValue.REOther(v) + +@genType +let getErrorSource = (err: reducerErrorValueWithSource) => err.sourceId diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_ErrorValue.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_ErrorValue.res index b6baeaf5..4caa474c 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_ErrorValue.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_ErrorValue.res @@ -81,3 +81,11 @@ let fromException = exn => } let toException = (errorValue: t) => raise(ErrorException(errorValue)) + +@genType.opaque +type errorValueWithSource = {error: errorValue, sourceId: string} + +let errorAddSource = (r: result<'a, errorValue>, sourceId: string): result< + 'a, + errorValueWithSource, +> => r->E.R2.errMap(err => {error: err, sourceId: sourceId}) diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_InternalExpressionValue.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_InternalExpressionValue.res index 5531cbdf..b5130b38 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_InternalExpressionValue.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_InternalExpressionValue.res @@ -131,6 +131,12 @@ let toStringResult = x => | Error(m) => `Error(${ErrorValue.errorToString(m)})` } +let toStringWithSourceResult = (x: result) => + switch x { + | Ok(a) => `Ok(${toString(a)})` + | Error(m) => `Error(${ErrorValue.errorToString(m.error)})` + } + let toStringOptionResult = x => switch x { | Some(a) => toStringResult(a) diff --git a/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject.res b/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject.res index 948c14c3..ea29ce4a 100644 --- a/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject.res +++ b/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject.res @@ -129,7 +129,7 @@ module Private = { let getResult = (project: t, sourceId: string): ProjectItem.T.resultArgumentType => switch getResultOption(project, sourceId) { - | None => RENeedToRun->Error + | None => RENeedToRun->Error->ErrorValue.errorAddSource(sourceId) | Some(result) => result } diff --git a/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject_ProjectItem.res b/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject_ProjectItem.res index 7676ddef..608645d6 100644 --- a/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject_ProjectItem.res +++ b/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject_ProjectItem.res @@ -6,12 +6,14 @@ module ExpressionT = Reducer_Expression_T module InternalExpressionValue = ReducerInterface_InternalExpressionValue module ProjectAccessorsT = ReducerProject_ProjectAccessors_T module ReducerFnT = ReducerProject_ReducerFn_T +module ErrorValue = Reducer_ErrorValue module T = ReducerProject_ProjectItem_T type projectItem = T.projectItem type t = T.t -let emptyItem = T.ProjectItem({ +let emptyItem = (id: string) => T.ProjectItem({ + id: id, source: "", rawParse: None, expression: None, @@ -25,6 +27,7 @@ let emptyItem = T.ProjectItem({ // source -> rawParse -> includes -> expression -> continuation -> result let getSource = (T.ProjectItem(r)): T.sourceType => r.source +let getId = (T.ProjectItem(r)): T.sourceType => r.id let getRawParse = (T.ProjectItem(r)): T.rawParseType => r.rawParse let getExpression = (T.ProjectItem(r)): T.expressionType => r.expression let getContinuation = (T.ProjectItem(r)): T.continuationArgumentType => r.continuation @@ -36,7 +39,7 @@ let getDirectIncludes = (T.ProjectItem(r)): array => r.directIncludes let getIncludesAsVariables = (T.ProjectItem(r)): T.importAsVariablesType => r.includeAsVariables let touchSource = (this: t): t => { - let T.ProjectItem(r) = emptyItem + let T.ProjectItem(r) = emptyItem(getId(this)) T.ProjectItem({ ...r, source: getSource(this), @@ -48,7 +51,7 @@ let touchSource = (this: t): t => { } let touchRawParse = (this: t): t => { - let T.ProjectItem(r) = emptyItem + let T.ProjectItem(r) = emptyItem(getId(this)) T.ProjectItem({ ...r, source: getSource(this), @@ -61,7 +64,7 @@ let touchRawParse = (this: t): t => { } let touchExpression = (this: t): t => { - let T.ProjectItem(r) = emptyItem + let T.ProjectItem(r) = emptyItem(getId(this)) T.ProjectItem({ ...r, source: getSource(this), @@ -104,7 +107,7 @@ let setResult = (T.ProjectItem(r): t, result: T.resultArgumentType): t => T.Proj let cleanResults = touchExpression let clean = (this: t): t => { - let T.ProjectItem(r) = emptyItem + let T.ProjectItem(r) = emptyItem(getId(this)) T.ProjectItem({ ...r, source: getSource(this), @@ -143,7 +146,7 @@ let parseIncludes = (this: t): t => { let T.ProjectItem(r) = this let rRawImportAsVariables = getSource(this)->ReducerProject_ParseIncludes.parseIncludes switch rRawImportAsVariables { - | Error(e) => resetIncludes(this)->setIncludes(Error(e)) + | Error(e) => resetIncludes(this)->setIncludes(Error(e)->ErrorValue.errorAddSource(getId(this))) | Ok(rawImportAsVariables) => { let includes = rawImportAsVariables->Belt.Array.map(((_variable, file)) => file)->Ok let includeAsVariables = @@ -190,14 +193,16 @@ let doBuildResult = ( ): T.resultType => this ->getExpression - ->Belt.Option.map( - Belt.Result.flatMap(_, expression => + ->Belt.Option.map(expressionResult => + expressionResult + ->Belt.Result.flatMap(_, expression => try { Reducer_Expression.reduceExpressionInProject(expression, aContinuation, accessors)->Ok } catch { | exn => Reducer_ErrorValue.fromException(exn)->Error } - ), + ) + ->ErrorValue.errorAddSource(getId(this)) ) let buildResult = (this: t, aContinuation: T.continuation, accessors: ProjectAccessorsT.t): t => { diff --git a/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject_ProjectItem_T.res b/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject_ProjectItem_T.res index caa80da4..2a8336ce 100644 --- a/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject_ProjectItem_T.res +++ b/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject_ProjectItem_T.res @@ -4,6 +4,7 @@ module InternalExpressionValue = ReducerInterface_InternalExpressionValue open Reducer_ErrorValue type sourceArgumentType = string +type idArgumentType = string type sourceType = string type rawParseArgumentType = result type rawParseType = option @@ -15,16 +16,17 @@ type continuationType = option type continuationResultType = option> type bindingsArgumentType = InternalExpressionValue.nameSpace type bindingsType = option -type resultArgumentType = result +type resultArgumentType = result type resultType = option type continuesArgumentType = array type continuesType = array type includesArgumentType = string -type includesType = result, errorValue> +type includesType = result, errorValueWithSource> type importAsVariablesType = array<(string, string)> type projectItem = | ProjectItem({ + id: string, source: sourceType, rawParse: rawParseType, expression: expressionType, diff --git a/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject_T.res b/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject_T.res index e1ec91f4..6ec15cb8 100644 --- a/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject_T.res +++ b/packages/squiggle-lang/src/rescript/ReducerProject/ReducerProject_T.res @@ -33,5 +33,5 @@ module Private = { let getSourceIds = (this: t): array => Belt.Map.String.keysToArray(this["items"]) let getItem = (this: t, sourceId: string) => - Belt.Map.String.getWithDefault(this["items"], sourceId, ProjectItem.emptyItem) + Belt.Map.String.getWithDefault(this["items"], sourceId, ProjectItem.emptyItem(sourceId)) }