function definition parse (tested)
This commit is contained in:
parent
a915e68049
commit
88b6d49ad3
|
@ -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)")
|
||||||
|
})
|
|
@ -33,6 +33,7 @@ let dispatchMacroCall = (
|
||||||
}
|
}
|
||||||
| ExpressionT.EValue(_) => expression->Ok
|
| ExpressionT.EValue(_) => expression->Ok
|
||||||
| ExpressionT.EBindings(_) => expression->Ok
|
| ExpressionT.EBindings(_) => expression->Ok
|
||||||
|
| ExpressionT.EParameters(_) => expression->Ok
|
||||||
| ExpressionT.EList(list) => {
|
| ExpressionT.EList(list) => {
|
||||||
let racc = list->Belt.List.reduceReverse(Ok(list{}), (racc, each: expression) =>
|
let racc = list->Belt.List.reduceReverse(Ok(list{}), (racc, each: expression) =>
|
||||||
racc->Result.flatMap(acc => {
|
racc->Result.flatMap(acc => {
|
||||||
|
|
|
@ -16,6 +16,7 @@ type t = expression
|
||||||
let rec toString = expression =>
|
let rec toString = expression =>
|
||||||
switch expression {
|
switch expression {
|
||||||
| T.EBindings(_) => "$$bound"
|
| T.EBindings(_) => "$$bound"
|
||||||
|
| T.EParameters(params) => `(${Js.Array2.toString(params->Belt.List.toArray)})`
|
||||||
| T.EList(aList) =>
|
| T.EList(aList) =>
|
||||||
`(${Belt.List.map(aList, aValue => toString(aValue))
|
`(${Belt.List.map(aList, aValue => toString(aValue))
|
||||||
->Extra.List.interperse(" ")
|
->Extra.List.interperse(" ")
|
||||||
|
@ -72,6 +73,7 @@ let rec reduceExpression = (expression: t, bindings: T.bindings): result<express
|
||||||
switch expression {
|
switch expression {
|
||||||
| T.EValue(_value) => expression->Ok
|
| T.EValue(_value) => expression->Ok
|
||||||
| T.EBindings(_value) => expression->Ok
|
| T.EBindings(_value) => expression->Ok
|
||||||
|
| T.EParameters(_value) => expression->Ok
|
||||||
| T.EList(list) => {
|
| T.EList(list) => {
|
||||||
let racc: result<list<t>, 'e> = list->Belt.List.reduceReverse(Ok(list{}), (
|
let racc: result<list<t>, 'e> = list->Belt.List.reduceReverse(Ok(list{}), (
|
||||||
racc,
|
racc,
|
||||||
|
@ -108,6 +110,7 @@ let rec reduceExpression = (expression: t, bindings: T.bindings): result<express
|
||||||
racc->Result.flatMap(acc => acc->reduceValueList)
|
racc->Result.flatMap(acc => acc->reduceValueList)
|
||||||
}
|
}
|
||||||
| EBindings(_bindings) => RETodo("Error: Bindings cannot be reduced to values")->Error
|
| 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<t, 'e> = expression->seekMacros(bindings)
|
let rExpandedExpression: result<t, 'e> = expression->seekMacros(bindings)
|
||||||
|
|
|
@ -11,5 +11,6 @@ open ReducerInterface.ExpressionValue
|
||||||
type rec expression =
|
type rec expression =
|
||||||
| EList(list<expression>) // A list to map-reduce
|
| EList(list<expression>) // A list to map-reduce
|
||||||
| EValue(expressionValue) // Irreducible built-in value. Reducer should not know the internals. External libraries are responsible
|
| 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<string>) // for $defun; for internal use only
|
||||||
and bindings = Belt.Map.String.t<expression>
|
and bindings = Belt.Map.String.t<expression>
|
||||||
|
|
|
@ -99,6 +99,19 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> =>
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 => {
|
let caseArrayNode = aNode => {
|
||||||
aNode["items"]->Belt.List.fromArray->fromNodeList->Result.map(list => ExpressionT.EList(list))
|
aNode["items"]->Belt.List.fromArray->fromNodeList->Result.map(list => ExpressionT.EList(list))
|
||||||
}
|
}
|
||||||
|
@ -115,6 +128,7 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> =>
|
||||||
| MjBlockNode(bNode) => bNode["blocks"]->Belt.Array.map(toTagOrNode)->caseTagOrNodes
|
| MjBlockNode(bNode) => bNode["blocks"]->Belt.Array.map(toTagOrNode)->caseTagOrNodes
|
||||||
| MjConstantNode(cNode) =>
|
| MjConstantNode(cNode) =>
|
||||||
cNode["value"]->JavaScript.Gate.jsToEv->Result.flatMap(v => v->ExpressionT.EValue->Ok)
|
cNode["value"]->JavaScript.Gate.jsToEv->Result.flatMap(v => v->ExpressionT.EValue->Ok)
|
||||||
|
| MjFunctionAssignmentNode(faNode) => caseFunctionAssignmentNode(faNode)
|
||||||
| MjFunctionNode(fNode) => fNode->caseFunctionNode
|
| MjFunctionNode(fNode) => fNode->caseFunctionNode
|
||||||
| MjIndexNode(iNode) => caseIndexNode(iNode)
|
| MjIndexNode(iNode) => caseIndexNode(iNode)
|
||||||
| MjObjectNode(oNode) => caseObjectNode(oNode)
|
| MjObjectNode(oNode) => caseObjectNode(oNode)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user