From 88b6d49ad3b910e12738f5db5d8a32a43165e12d Mon Sep 17 00:00:00 2001 From: Umur Ozkul Date: Sat, 23 Apr 2022 21:13:43 +0200 Subject: [PATCH] function definition parse (tested) --- .../Reducer/Reducer_functionAssignment_test.res | 12 ++++++++++++ .../Reducer_Dispatch_BuiltInMacros.res | 1 + .../Reducer_Expression/Reducer_Expression.res | 3 +++ .../Reducer_Expression/Reducer_Expression_T.res | 3 ++- .../Reducer_MathJs/Reducer_MathJs_ToExpression.res | 14 ++++++++++++++ 5 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 packages/squiggle-lang/__tests__/Reducer/Reducer_functionAssignment_test.res diff --git a/packages/squiggle-lang/__tests__/Reducer/Reducer_functionAssignment_test.res b/packages/squiggle-lang/__tests__/Reducer/Reducer_functionAssignment_test.res new file mode 100644 index 00000000..ebc0896f --- /dev/null +++ b/packages/squiggle-lang/__tests__/Reducer/Reducer_functionAssignment_test.res @@ -0,0 +1,12 @@ +open Jest +open Reducer_TestHelpers + +describe("Parse function assignment", () => { + testParseToBe("f(x)=x", "Ok((:$let :f (:$lambda (x) :x)))") + testParseToBe("f(x)=2*x", "Ok((:$let :f (:$lambda (x) (:multiply 2 :x))))") + //MathJs does not allow blocks in function definitions +}) + +Skip.describe("Evaluate function assignment", () => { + testParseToBe("f(x)=x; f(1)", "Ok(1)") +}) \ No newline at end of file diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Dispatch/Reducer_Dispatch_BuiltInMacros.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Dispatch/Reducer_Dispatch_BuiltInMacros.res index d1219f79..7da85124 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Dispatch/Reducer_Dispatch_BuiltInMacros.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Dispatch/Reducer_Dispatch_BuiltInMacros.res @@ -33,6 +33,7 @@ let dispatchMacroCall = ( } | ExpressionT.EValue(_) => expression->Ok | ExpressionT.EBindings(_) => expression->Ok + | ExpressionT.EParameters(_) => expression->Ok | ExpressionT.EList(list) => { let racc = list->Belt.List.reduceReverse(Ok(list{}), (racc, each: expression) => racc->Result.flatMap(acc => { 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 68881496..30f8d96c 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 @@ -16,6 +16,7 @@ type t = expression let rec toString = expression => switch expression { | T.EBindings(_) => "$$bound" + | T.EParameters(params) => `(${Js.Array2.toString(params->Belt.List.toArray)})` | T.EList(aList) => `(${Belt.List.map(aList, aValue => toString(aValue)) ->Extra.List.interperse(" ") @@ -72,6 +73,7 @@ let rec reduceExpression = (expression: t, bindings: T.bindings): result expression->Ok | T.EBindings(_value) => expression->Ok + | T.EParameters(_value) => expression->Ok | T.EList(list) => { let racc: result, 'e> = list->Belt.List.reduceReverse(Ok(list{}), ( racc, @@ -108,6 +110,7 @@ let rec reduceExpression = (expression: t, bindings: T.bindings): resultResult.flatMap(acc => acc->reduceValueList) } | EBindings(_bindings) => RETodo("Error: Bindings cannot be reduced to values")->Error + | EParameters(_parameters) => RETodo("Error: Lambda Parameters cannot be reduced to values")->Error } let rExpandedExpression: result = expression->seekMacros(bindings) 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 fe938316..5f141195 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 @@ -11,5 +11,6 @@ open ReducerInterface.ExpressionValue type rec expression = | EList(list) // A list to map-reduce | EValue(expressionValue) // Irreducible built-in value. Reducer should not know the internals. External libraries are responsible - | EBindings(bindings) // let/def kind of statements return bindings + | EBindings(bindings) // $let kind of statements return bindings; for internal use only + | EParameters(list) // for $defun; for internal use only and bindings = Belt.Map.String.t diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_ToExpression.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_ToExpression.res index a8b7b39a..2d0bcdd6 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_ToExpression.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_ToExpression.res @@ -99,6 +99,19 @@ let rec fromNode = (mathJsNode: Parse.node): result => }) } + let caseFunctionAssignmentNode = faNode => { + let symbol = faNode["name"]->toEvSymbolValue + let rValueExpression = fromNode(faNode["expr"]) + + rValueExpression->Result.flatMap(valueExpression => { + let lispParams = faNode["params"]->Belt.List.fromArray->ExpressionT.EParameters + let rLambda = passToFunction("$lambda", list{lispParams, valueExpression}->Ok) + rLambda -> Result.flatMap( lambda => { + passToFunction("$let", list{symbol, lambda}->Ok) + }) + }) + } + let caseArrayNode = aNode => { aNode["items"]->Belt.List.fromArray->fromNodeList->Result.map(list => ExpressionT.EList(list)) } @@ -115,6 +128,7 @@ let rec fromNode = (mathJsNode: Parse.node): result => | MjBlockNode(bNode) => bNode["blocks"]->Belt.Array.map(toTagOrNode)->caseTagOrNodes | MjConstantNode(cNode) => cNode["value"]->JavaScript.Gate.jsToEv->Result.flatMap(v => v->ExpressionT.EValue->Ok) + | MjFunctionAssignmentNode(faNode) => caseFunctionAssignmentNode(faNode) | MjFunctionNode(fNode) => fNode->caseFunctionNode | MjIndexNode(iNode) => caseIndexNode(iNode) | MjObjectNode(oNode) => caseObjectNode(oNode)