public double ExecAst(IAstNode root) { switch (root) { case AstNumberNode numberNode: return(numberNode.Number); case AstVariableNode varNode: if (Constants.TryGetValue(varNode.Id, out var val)) { return(val); } else if (Variables.TryGetValue(varNode.Id, out val)) { return(val); } else { if (Setting.DebugMode) { Sync.Tools.IO.CurrentIO.WriteColor($"[RTPP:Expression]No Variable found (return zero). Variable name: { varNode.Id }", ConsoleColor.Yellow); } return(0); } case AstOpNode opNode: switch (opNode.Op) { case "+": return(ExecAst(opNode.LNode) + ExecAst(opNode.RNode)); case "-": return(ExecAst(opNode.LNode) - ExecAst(opNode.RNode)); case "*": return(ExecAst(opNode.LNode) * ExecAst(opNode.RNode)); case "/": return(ExecAst(opNode.LNode) / ExecAst(opNode.RNode)); case "%": return(ExecAst(opNode.LNode) % ExecAst(opNode.RNode)); case "^": return(Math.Pow(ExecAst(opNode.LNode), ExecAst(opNode.RNode))); case ">": return((ExecAst(opNode.LNode) > ExecAst(opNode.RNode)) ? 1 : 0); case "<": return((ExecAst(opNode.LNode) < ExecAst(opNode.RNode)) ? 1 : 0); case ">=": return((ExecAst(opNode.LNode) >= ExecAst(opNode.RNode)) ? 1 : 0); case "<=": return((ExecAst(opNode.LNode) <= ExecAst(opNode.RNode)) ? 1 : 0); case "==": return(IsNotZero(ExecAst(opNode.LNode) - ExecAst(opNode.RNode)) ? 0 : 1); case "!=": return(IsNotZero(ExecAst(opNode.LNode) - ExecAst(opNode.RNode)) ? 1 : 0); case "!": return(IsNotZero(ExecAst(opNode.LNode)) ? 0 : 1); case "&&": return((IsNotZero(ExecAst(opNode.LNode)) && IsNotZero(ExecAst(opNode.RNode))) ? 1 : 0); case "||": return((IsNotZero(ExecAst(opNode.LNode)) || IsNotZero(ExecAst(opNode.RNode))) ? 1 : 0); } break; case AstFunctionNode funcNode: try { if (funcNode.Id == "set") { AstVariableNode varNode = funcNode.Args[0] as AstVariableNode; string varName = varNode?.Id ?? throw new ExpressionException($"The \"{funcNode.Id}()\" first parameter is the variable name."); double varVal = ExecAst(funcNode.Args[1]); Variables[varName] = varVal; return(0); } else if (funcNode.Id == "if") { IAstNode condNode = funcNode.Args[0]; double condNodeResult = ExecAst(condNode); if (Math.Abs(condNodeResult) <= 1e-5) { //false_expr return(ExecAst(funcNode.Args[2])); } else { //true_expr return(ExecAst(funcNode.Args[1])); } } else if (funcNode.Id == "smooth") { AstVariableNode varNode = funcNode.Args[0] as AstVariableNode; string varName = varNode?.Id ?? throw new ExpressionException($"The \"{funcNode.Id}()\" first parameter is the variable name."); double varVal = ExecAst(funcNode.Args[0]); return(SmoothMath.SmoothVariable(varName, varVal)); } else { if (Functions.TryGetValue(funcNode.Id, out var func)) { return(func(ComputeArgs(funcNode.Args))); } else { throw new ExpressionException($"No function found. Fucntion: {funcNode.Id}"); } } } catch (ArgumentOutOfRangeException) { throw new ExpressionException($"The function is missing a parameter. Fucntion: {funcNode.Id}"); } } return(Double.NaN); }
public double ExecAst(IAstNode root) { switch (root) { case AstNumberNode numberNode: return(numberNode.Number); case AstVariableNode varNode: if (Constants.TryGetValue(varNode.Id, out var val)) { return(val); } else if (Variables.TryGetValue(varNode.Id, out val)) { return(val); } else { Sync.Tools.IO.CurrentIO.WriteColor($"[RTPP:Expression]No Variable found (return zero). Variable name: { varNode.Id }", ConsoleColor.Yellow); return(0); } case AstOpNode opNode: switch (opNode.Op) { case "+": return(ExecAst(opNode.LNode) + ExecAst(opNode.RNode)); case "-": return(ExecAst(opNode.LNode) - ExecAst(opNode.RNode)); case "*": return(ExecAst(opNode.LNode) * ExecAst(opNode.RNode)); case "/": return(ExecAst(opNode.LNode) / ExecAst(opNode.RNode)); case "^": return(Math.Pow(ExecAst(opNode.LNode), ExecAst(opNode.RNode))); } break; case AstFunctionNode funcNode: try { if (funcNode.Id == "set") { AstVariableNode varNode = funcNode.Args[0] as AstVariableNode; string varName = varNode?.Id ?? throw new ExpressionException("The first parameter is the variable name."); double varVal = ExecAst(funcNode.Args[1]); Variables[varName] = varVal; return(0); } else { if (Functions.TryGetValue(funcNode.Id, out var func)) { return(func(ComputeArgs(funcNode.Args))); } else { throw new ExpressionException($"No function found. Fucntion: {funcNode.Id}"); } } } catch (ArgumentOutOfRangeException) { throw new ExpressionException($"The function is missing a parameter. Fucntion: {funcNode.Id}"); } } return(Double.NaN); }