Add a source annotation to error objects
This commit is contained in:
		
							parent
							
								
									9ddd1bfae0
								
							
						
					
					
						commit
						e2e30641b3
					
				|  | @ -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 | ||||
|  |  | |||
|  | @ -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) => { | ||||
|  |  | |||
|  | @ -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)", "@{}") | ||||
|     }) | ||||
|  |  | |||
|  | @ -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}") | ||||
|       /* | ||||
|  |  | |||
|  | @ -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 | ||||
|       } | ||||
|     }) | ||||
|   }) | ||||
|  |  | |||
|  | @ -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)" | ||||
|   }) | ||||
| }) | ||||
| 
 | ||||
|  |  | |||
|  | @ -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)"] | ||||
|   }) | ||||
|  |  | |||
|  | @ -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); | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -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) | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<string>, | ||||
|   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<squiggleValue, reducerErrorValue>, | ||||
|   result<squiggleValue, reducerErrorValueWithSource>, | ||||
|   squiggleValue_Module, | ||||
| ) => Private.evaluate(sourceCode) | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<syntaxErrorLocation> => | ||||
|   switch e { | ||||
| let getLocation = (e: reducerErrorValueWithSource): option<syntaxErrorLocation> => | ||||
|   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 | ||||
|  |  | |||
|  | @ -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}) | ||||
|  |  | |||
|  | @ -131,6 +131,12 @@ let toStringResult = x => | |||
|   | Error(m) => `Error(${ErrorValue.errorToString(m)})` | ||||
|   } | ||||
| 
 | ||||
| let toStringWithSourceResult = (x: result<t, ErrorValue.errorValueWithSource>) => | ||||
|   switch x { | ||||
|   | Ok(a) => `Ok(${toString(a)})` | ||||
|   | Error(m) => `Error(${ErrorValue.errorToString(m.error)})` | ||||
|   } | ||||
| 
 | ||||
| let toStringOptionResult = x => | ||||
|   switch x { | ||||
|   | Some(a) => toStringResult(a) | ||||
|  |  | |||
|  | @ -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 | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<string> => 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 => { | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ module InternalExpressionValue = ReducerInterface_InternalExpressionValue | |||
| open Reducer_ErrorValue | ||||
| 
 | ||||
| type sourceArgumentType = string | ||||
| type idArgumentType = string | ||||
| type sourceType = string | ||||
| type rawParseArgumentType = result<Parse.node, errorValue> | ||||
| type rawParseType = option<rawParseArgumentType> | ||||
|  | @ -15,16 +16,17 @@ type continuationType = option<continuationArgumentType> | |||
| type continuationResultType = option<result<continuationArgumentType, errorValue>> | ||||
| type bindingsArgumentType = InternalExpressionValue.nameSpace | ||||
| type bindingsType = option<bindingsArgumentType> | ||||
| type resultArgumentType = result<InternalExpressionValue.t, errorValue> | ||||
| type resultArgumentType = result<InternalExpressionValue.t, errorValueWithSource> | ||||
| type resultType = option<resultArgumentType> | ||||
| type continuesArgumentType = array<string> | ||||
| type continuesType = array<string> | ||||
| type includesArgumentType = string | ||||
| type includesType = result<array<string>, errorValue> | ||||
| type includesType = result<array<string>, errorValueWithSource> | ||||
| type importAsVariablesType = array<(string, string)> | ||||
| 
 | ||||
| type projectItem = | ||||
|   | ProjectItem({ | ||||
|       id: string, | ||||
|       source: sourceType, | ||||
|       rawParse: rawParseType, | ||||
|       expression: expressionType, | ||||
|  |  | |||
|  | @ -33,5 +33,5 @@ module Private = { | |||
|   let getSourceIds = (this: t): array<string> => 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)) | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user