issue 234
Define partial code
This commit is contained in:
parent
3f95ca455b
commit
7ab69a1708
|
@ -119,6 +119,10 @@ describe("eval", () => {
|
||||||
list{("x", ExpressionValue.EvNumber(1.))}->Js.Dict.fromList,
|
list{("x", ExpressionValue.EvNumber(1.))}->Js.Dict.fromList,
|
||||||
"Error(JS Exception: Error: Undefined symbol x)",
|
"Error(JS Exception: Error: Undefined symbol x)",
|
||||||
)
|
)
|
||||||
|
testEvalToBe(
|
||||||
|
"x=1; y=1",
|
||||||
|
"???",
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,9 @@ let parse_ = (expr: string, parser, converter): result<t, errorValue> =>
|
||||||
let parse = (mathJsCode: string): result<t, errorValue> =>
|
let parse = (mathJsCode: string): result<t, errorValue> =>
|
||||||
mathJsCode->parse_(MathJs.Parse.parse, MathJs.ToExpression.fromNode)
|
mathJsCode->parse_(MathJs.Parse.parse, MathJs.ToExpression.fromNode)
|
||||||
|
|
||||||
|
let parsePartial = (mathJsCode: string): result<t, errorValue> =>
|
||||||
|
mathJsCode->parse_(MathJs.Parse.parse, MathJs.ToExpression.fromPartialNode)
|
||||||
|
|
||||||
let defaultBindings: T.bindings = Belt.Map.String.empty
|
let defaultBindings: T.bindings = Belt.Map.String.empty
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -115,15 +118,18 @@ let evalWBindingsExpression_ = (aExpression, bindings): result<expressionValue,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Evaluates MathJs code via Reducer using bindings and answers the result
|
Evaluates MathJs code via Reducer using bindings and answers the result
|
||||||
|
When bindings are used, the code is a partial code as if it is cut from a larger code.
|
||||||
*/
|
*/
|
||||||
let evalWBindings_ = (codeText: string, bindings: T.bindings) => {
|
let evalWBindings_ = (codeText: string, bindings: T.bindings) => {
|
||||||
parse(codeText)->Result.flatMap(code => code->evalWBindingsExpression_(bindings))
|
parsePartial(codeText)->Result.flatMap(expression => expression->evalWBindingsExpression_(bindings))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Evaluates MathJs code via Reducer and answers the result
|
Evaluates MathJs code and bindings via Reducer and answers the result
|
||||||
*/
|
*/
|
||||||
let eval = (code: string) => evalWBindings_(code, defaultBindings)
|
let eval = (codeText: string) => {
|
||||||
|
parse(codeText)->Result.flatMap(expression => expression->evalWBindingsExpression_(defaultBindings))
|
||||||
|
}
|
||||||
|
|
||||||
type externalBindings = Js.Dict.t<expressionValue>
|
type externalBindings = Js.Dict.t<expressionValue>
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,22 @@ type expression = ExpressionT.expression
|
||||||
type expressionValue = ExpressionValue.expressionValue
|
type expressionValue = ExpressionValue.expressionValue
|
||||||
type errorValue = ErrorValue.errorValue
|
type errorValue = ErrorValue.errorValue
|
||||||
|
|
||||||
|
let passToFunction = (fName: string, rLispArgs): result<expression, errorValue> => {
|
||||||
|
let toEvCallValue = (name: string): expression => name->ExpressionValue.EvCall->ExpressionT.EValue
|
||||||
|
|
||||||
|
let fn = fName->toEvCallValue
|
||||||
|
rLispArgs->Result.flatMap(lispArgs => list{fn, ...lispArgs}->ExpressionT.EList->Ok)
|
||||||
|
}
|
||||||
|
|
||||||
|
type blockTag =
|
||||||
|
| ImportVariablesStatement
|
||||||
|
| ExportVariablesExpression
|
||||||
|
type tagOrNode =
|
||||||
|
| BlockTag(blockTag)
|
||||||
|
| BlockNode(Parse.node)
|
||||||
|
|
||||||
|
let toTagOrNode = block => BlockNode(block["node"])
|
||||||
|
|
||||||
let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> =>
|
let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> =>
|
||||||
Parse.castNodeType(mathJsNode)->Result.flatMap(typedMathJsNode => {
|
Parse.castNodeType(mathJsNode)->Result.flatMap(typedMathJsNode => {
|
||||||
let fromNodeList = (nodeList: list<Parse.node>): result<list<expression>, 'e> =>
|
let fromNodeList = (nodeList: list<Parse.node>): result<list<expression>, 'e> =>
|
||||||
|
@ -18,16 +34,9 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> =>
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
let toEvCallValue = (name: string): expression =>
|
|
||||||
name->ExpressionValue.EvCall->ExpressionT.EValue
|
|
||||||
let toEvSymbolValue = (name: string): expression =>
|
let toEvSymbolValue = (name: string): expression =>
|
||||||
name->ExpressionValue.EvSymbol->ExpressionT.EValue
|
name->ExpressionValue.EvSymbol->ExpressionT.EValue
|
||||||
|
|
||||||
let passToFunction = (fName: string, rLispArgs): result<expression, errorValue> => {
|
|
||||||
let fn = fName->toEvCallValue
|
|
||||||
rLispArgs->Result.flatMap(lispArgs => list{fn, ...lispArgs}->ExpressionT.EList->Ok)
|
|
||||||
}
|
|
||||||
|
|
||||||
let caseFunctionNode = fNode => {
|
let caseFunctionNode = fNode => {
|
||||||
let lispArgs = fNode["args"]->Belt.List.fromArray->fromNodeList
|
let lispArgs = fNode["args"]->Belt.List.fromArray->fromNodeList
|
||||||
passToFunction(fNode->Parse.nameOfFunctionNode, lispArgs)
|
passToFunction(fNode->Parse.nameOfFunctionNode, lispArgs)
|
||||||
|
@ -94,27 +103,6 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> =>
|
||||||
aNode["items"]->Belt.List.fromArray->fromNodeList->Result.map(list => ExpressionT.EList(list))
|
aNode["items"]->Belt.List.fromArray->fromNodeList->Result.map(list => ExpressionT.EList(list))
|
||||||
}
|
}
|
||||||
|
|
||||||
let caseBlockNode = (bNode): result<expression, errorValue> => {
|
|
||||||
let blocks = bNode["blocks"]
|
|
||||||
let initialBindings = passToFunction("$$bindings", list{}->Ok)
|
|
||||||
let lastIndex = Belt.Array.length(blocks) - 1
|
|
||||||
blocks->Belt.Array.reduceWithIndex(initialBindings, (rPreviousBindings, block, i) => {
|
|
||||||
rPreviousBindings->Result.flatMap(previousBindings => {
|
|
||||||
let node = block["node"]
|
|
||||||
let rStatement: result<expression, errorValue> = node->fromNode
|
|
||||||
let bindName = if i == lastIndex {
|
|
||||||
"$$bindExpression"
|
|
||||||
} else {
|
|
||||||
"$$bindStatement"
|
|
||||||
}
|
|
||||||
rStatement->Result.flatMap((statement: expression) => {
|
|
||||||
let lispArgs = list{previousBindings, statement}->Ok
|
|
||||||
passToFunction(bindName, lispArgs)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let rFinalExpression: result<expression, errorValue> = switch typedMathJsNode {
|
let rFinalExpression: result<expression, errorValue> = switch typedMathJsNode {
|
||||||
| MjAccessorNode(aNode) => caseAccessorNode(aNode["object"], aNode["index"])
|
| MjAccessorNode(aNode) => caseAccessorNode(aNode["object"], aNode["index"])
|
||||||
| MjArrayNode(aNode) => caseArrayNode(aNode)
|
| MjArrayNode(aNode) => caseArrayNode(aNode)
|
||||||
|
@ -124,8 +112,7 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> =>
|
||||||
let rExpr: result<expression, errorValue> = expr->Ok
|
let rExpr: result<expression, errorValue> = expr->Ok
|
||||||
rExpr
|
rExpr
|
||||||
}
|
}
|
||||||
| MjBlockNode(bNode) => caseBlockNode(bNode)
|
| MjBlockNode(bNode) => bNode["blocks"]->Belt.Array.map(toTagOrNode)->caseTagOrNodes
|
||||||
// | MjBlockNode(bNode) => "statement"->toEvSymbolValue->Ok
|
|
||||||
| 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)
|
||||||
| MjFunctionNode(fNode) => fNode->caseFunctionNode
|
| MjFunctionNode(fNode) => fNode->caseFunctionNode
|
||||||
|
@ -136,3 +123,58 @@ let rec fromNode = (mathJsNode: Parse.node): result<expression, errorValue> =>
|
||||||
}
|
}
|
||||||
rFinalExpression
|
rFinalExpression
|
||||||
})
|
})
|
||||||
|
and caseTagOrNodes = (tagOrNodes): result<expression, errorValue> => {
|
||||||
|
let initialBindings = passToFunction("$$bindings", list{}->Ok)
|
||||||
|
let lastIndex = Belt.Array.length(tagOrNodes) - 1
|
||||||
|
tagOrNodes->Belt.Array.reduceWithIndex(initialBindings, (rPreviousBindings, tagOrNode, i) => {
|
||||||
|
rPreviousBindings->Result.flatMap(previousBindings => {
|
||||||
|
let rStatement: result<expression, errorValue> = switch tagOrNode {
|
||||||
|
| BlockNode(node) => fromNode(node)
|
||||||
|
| BlockTag(tag) => switch tag {
|
||||||
|
| ImportVariablesStatement =>
|
||||||
|
passToFunction("$$importVariablesStatement", list{}->Ok)
|
||||||
|
| ExportVariablesExpression =>
|
||||||
|
passToFunction("$$exportVariablesExpression", list{}->Ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let bindName = if i == lastIndex {
|
||||||
|
"$$bindExpression"
|
||||||
|
} else {
|
||||||
|
"$$bindStatement"
|
||||||
|
}
|
||||||
|
|
||||||
|
rStatement->Result.flatMap((statement: expression) => {
|
||||||
|
let lispArgs = list{previousBindings, statement}->Ok
|
||||||
|
passToFunction(bindName, lispArgs)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let fromPartialNode = (mathJsNode: Parse.node): result<expression, errorValue> => {
|
||||||
|
Parse.castNodeType(mathJsNode)->Result.flatMap(typedMathJsNode => {
|
||||||
|
let casePartialBlockNode = (bNode: Parse.blockNode) => {
|
||||||
|
let blocksOrTags = bNode["blocks"]->Belt.Array.map(toTagOrNode)
|
||||||
|
let completed = Js.Array2.concatMany(
|
||||||
|
[BlockTag(ImportVariablesStatement)],
|
||||||
|
[blocksOrTags, [BlockTag(ExportVariablesExpression)]],
|
||||||
|
)
|
||||||
|
completed->caseTagOrNodes
|
||||||
|
}
|
||||||
|
|
||||||
|
let casePartialExpression = (node: Parse.node) => {
|
||||||
|
let completed = Js.Array2.concatMany(
|
||||||
|
[BlockTag(ImportVariablesStatement)],
|
||||||
|
[[BlockNode(node)], [BlockTag(ExportVariablesExpression)]],
|
||||||
|
)
|
||||||
|
completed->caseTagOrNodes
|
||||||
|
}
|
||||||
|
|
||||||
|
let rFinalExpression: result<expression, errorValue> = switch typedMathJsNode {
|
||||||
|
| MjBlockNode(bNode) => casePartialBlockNode(bNode)
|
||||||
|
| _ => casePartialExpression(mathJsNode)
|
||||||
|
}
|
||||||
|
rFinalExpression
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user