diff --git a/packages/squiggle-lang/__tests__/Reducer/Reducer_MathJs/Reducer_MathJsParse_test.res b/packages/squiggle-lang/__tests__/Reducer/Reducer_MathJs/Reducer_MathJsParse_test.res index b085eeb3..b6c8c290 100644 --- a/packages/squiggle-lang/__tests__/Reducer/Reducer_MathJs/Reducer_MathJsParse_test.res +++ b/packages/squiggle-lang/__tests__/Reducer/Reducer_MathJs/Reducer_MathJsParse_test.res @@ -66,4 +66,9 @@ describe("MathJs parse", () => { describe("comments", () => { testDescriptionParse("define", "1 # This is a comment", "1") }) + + describe("ternary operator", () => { + testParse("1 ? 2 : 3", "ternary(1, 2, 3)") + testParse("1 ? 2 : 3 ? 4 : 5", "ternary(1, 2, ternary(3, 4, 5))") + }) }) diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Parse.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Parse.res index 1f5df97d..704d1d38 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Parse.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_MathJs/Reducer_MathJs_Parse.res @@ -9,7 +9,7 @@ type node = {"type": string, "isNode": bool, "comment": string} type arrayNode = {...node, "items": array} type block = {"node": node} type blockNode = {...node, "blocks": array} -//conditionalNode +type conditionalNode = {...node, "condition": node, "trueExpr": node, "falseExpr": node} type constantNode = {...node, "value": unit} type functionAssignmentNode = {...node, "name": string, "params": array, "expr": node} type indexNode = {...node, "dimensions": array} @@ -31,6 +31,7 @@ external castAssignmentNode: node => assignmentNode = "%identity" external castAssignmentNodeWAccessor: node => assignmentNodeWAccessor = "%identity" external castAssignmentNodeWIndex: node => assignmentNodeWIndex = "%identity" external castBlockNode: node => blockNode = "%identity" +external castConditionalNode: node => conditionalNode = "%identity" external castConstantNode: node => constantNode = "%identity" external castFunctionAssignmentNode: node => functionAssignmentNode = "%identity" external castFunctionNode: node => functionNode = "%identity" @@ -58,6 +59,7 @@ type mathJsNode = | MjArrayNode(arrayNode) | MjAssignmentNode(assignmentNode) | MjBlockNode(blockNode) + | MjConditionalNode(conditionalNode) | MjConstantNode(constantNode) | MjFunctionAssignmentNode(functionAssignmentNode) | MjFunctionNode(functionNode) @@ -82,6 +84,7 @@ let castNodeType = (node: node) => { | "ArrayNode" => node->castArrayNode->MjArrayNode->Ok | "AssignmentNode" => node->decideAssignmentNode | "BlockNode" => node->castBlockNode->MjBlockNode->Ok + | "ConditionalNode" => node->castConditionalNode->MjConditionalNode->Ok | "ConstantNode" => node->castConstantNode->MjConstantNode->Ok | "FunctionAssignmentNode" => node->castFunctionAssignmentNode->MjFunctionAssignmentNode->Ok | "FunctionNode" => node->castFunctionNode->MjFunctionNode->Ok @@ -157,6 +160,10 @@ let rec toString = (mathJsNode: mathJsNode): string => { | MjAssignmentNode(aNode) => `${aNode["object"]->toStringSymbolNode} = ${aNode["value"]->toStringMathJsNode}` | MjBlockNode(bNode) => `{${bNode["blocks"]->toStringBlocks}}` + | MjConditionalNode(cNode) => + `ternary(${toStringMathJsNode(cNode["condition"])}, ${toStringMathJsNode( + cNode["trueExpr"], + )}, ${toStringMathJsNode(cNode["falseExpr"])})` | MjConstantNode(cNode) => cNode["value"]->toStringValue | MjFunctionAssignmentNode(faNode) => faNode->toStringFunctionAssignmentNode | MjFunctionNode(fNode) => fNode->toStringFunctionNode 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 ca040190..6355de88 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 @@ -113,6 +113,20 @@ let rec fromInnerNode = (mathJsNode: Parse.node): result aNode["items"]->Belt.List.fromArray->fromNodeList->Result.map(list => ExpressionT.EList(list)) } + let caseConditionalNode = cndNode => { + let rCondition = fromInnerNode(cndNode["condition"]) + let rTrueExpr = fromInnerNode(cndNode["trueExpr"]) + let rFalse = fromInnerNode(cndNode["falseExpr"]) + + rCondition->Result.flatMap(condition => + rTrueExpr->Result.flatMap(trueExpr => + rFalse->Result.flatMap(falseExpr => + ExpressionBuilder.eFunction("$$ternary", list{condition, trueExpr, falseExpr})->Ok + ) + ) + ) + } + let rFinalExpression: result = switch typedMathJsNode { | MjAccessorNode(aNode) => caseAccessorNode(aNode["object"], aNode["index"]) | MjArrayNode(aNode) => caseArrayNode(aNode) @@ -123,6 +137,7 @@ let rec fromInnerNode = (mathJsNode: Parse.node): result rExpr } | MjBlockNode(bNode) => bNode["blocks"]->Js.Array2.map(blockToNode)->caseBlock + | MjConditionalNode(cndNode) => caseConditionalNode(cndNode) | MjConstantNode(cNode) => cNode["value"]->JavaScript.Gate.jsToEv->Result.flatMap(v => v->ExpressionT.EValue->Ok) | MjFunctionAssignmentNode(faNode) => caseFunctionAssignmentNode(faNode)