From 84a0d83efb926d5f78f8bd75b5e45f2ada627130 Mon Sep 17 00:00:00 2001 From: Vyacheslav Matyukhin Date: Wed, 22 Jun 2022 00:34:35 +0300 Subject: [PATCH] store location on RESyntaxError; export parse() function --- packages/squiggle-lang/src/js/index.ts | 20 ++++++++++++++++++- .../rescript/Reducer/Reducer_ErrorValue.res | 7 +++++-- .../Reducer_Expression/Reducer_Expression.res | 2 +- .../Reducer_Peggy/Reducer_Peggy_Parse.res | 6 +++++- .../src/rescript/TypescriptInterface.res | 3 +++ 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts index 592de8e3..74ca1d1d 100644 --- a/packages/squiggle-lang/src/js/index.ts +++ b/packages/squiggle-lang/src/js/index.ts @@ -10,6 +10,7 @@ import { evaluatePartialUsingExternalBindings, evaluateUsingOptions, foreignFunctionInterface, + parse as parseRescript, } from "../rescript/TypescriptInterface.gen"; export { makeSampleSetDist, @@ -31,7 +32,7 @@ import { convertRawToTypescript, lambdaValue, } from "./rescript_interop"; -import { result, resultMap, tag, tagged } from "./types"; +import { Ok, result, resultMap, tag, tagged } from "./types"; import { Distribution, shape } from "./distribution"; export { Distribution, resultMap, defaultEnvironment }; @@ -58,6 +59,23 @@ export function run( return resultMap(res, (x) => createTsExport(x, e)); } +export function parse( + squiggleString: string +): result> { + const maybeExpression = parseRescript(squiggleString); + if (maybeExpression.tag === "Ok") { + return Ok(null); // TODO - return AST + } else { + if ( + typeof maybeExpression.value !== "object" || + maybeExpression.value.tag !== "RESyntaxError" + ) { + throw new Error("Expected syntax error"); + } + return { tag: "Error", value: maybeExpression.value }; + } +} + // Run Partial. A partial is a block of code that doesn't return a value export function runPartial( squiggleString: string, diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_ErrorValue.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_ErrorValue.res index 721fbc40..beaee7f7 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_ErrorValue.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_ErrorValue.res @@ -1,3 +1,6 @@ +@gentype.import("peggy") @genType.as("LocationRange") +type location + @genType type errorValue = | REArityError(option, int, int) //TODO: Binding a lambda to a variable should record the variable name in lambda for error reporting @@ -14,7 +17,7 @@ type errorValue = | REOperationError(Operation.operationError) | RERecordPropertyNotFound(string, string) | RESymbolNotFound(string) - | RESyntaxError(string) + | RESyntaxError(string, option) | RETodo(string) // To do | REUnitNotFound(string) @@ -50,7 +53,7 @@ let errorToString = err => | RENotAFunction(valueString) => `${valueString} is not a function` | RERecordPropertyNotFound(msg, index) => `${msg}: ${index}` | RESymbolNotFound(symbolName) => `${symbolName} is not defined` - | RESyntaxError(desc) => `Syntax Error: ${desc}` + | RESyntaxError(desc, _) => `Syntax Error: ${desc}` | RETodo(msg) => `TODO: ${msg}` | REExpectedType(typeName) => `Expected type: ${typeName}` | REUnitNotFound(unitName) => `Unit not found: ${unitName}` diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression.res index 6b4168c3..dabe3150 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Expression/Reducer_Expression.res @@ -157,7 +157,7 @@ let evaluatePartialUsingExternalBindings = ( switch rAnswer { | Ok(EvRecord(externalBindings)) => Ok(externalBindings) | Ok(_) => - Error(Reducer_ErrorValue.RESyntaxError(`Partials must end with an assignment or record`)) + Error(Reducer_ErrorValue.RESyntaxError(`Partials must end with an assignment or record`, None)) | Error(err) => err->Error } } diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Peggy/Reducer_Peggy_Parse.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Peggy/Reducer_Peggy_Parse.res index 5bdcda14..1a37ccc0 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Peggy/Reducer_Peggy_Parse.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Peggy/Reducer_Peggy_Parse.res @@ -5,11 +5,15 @@ type node = {"type": string} @module("./Reducer_Peggy_GeneratedParser.js") external parse__: string => node = "parse" +let syntaxErrorToLocation: Js.Exn.t => Reducer_ErrorValue.location = error => %raw(`error.location`) + +@genType let parse = (expr: string): result => try { Ok(parse__(expr)) } catch { - | Js.Exn.Error(obj) => REJavaScriptExn(Js.Exn.message(obj), Js.Exn.name(obj))->Error + | Js.Exn.Error(obj) => + RESyntaxError(Belt.Option.getExn(Js.Exn.message(obj)), syntaxErrorToLocation(obj)->Some)->Error } type nodeBlock = {...node, "statements": array} diff --git a/packages/squiggle-lang/src/rescript/TypescriptInterface.res b/packages/squiggle-lang/src/rescript/TypescriptInterface.res index 932edaa1..5bc913d8 100644 --- a/packages/squiggle-lang/src/rescript/TypescriptInterface.res +++ b/packages/squiggle-lang/src/rescript/TypescriptInterface.res @@ -40,6 +40,9 @@ let evaluate = Reducer.evaluate @genType let evaluateUsingOptions = Reducer.evaluateUsingOptions +@genType +let parse = Reducer_Peggy_Parse.parse + @genType let evaluatePartialUsingExternalBindings = Reducer.evaluatePartialUsingExternalBindings