Exemplo n.º 1
0
        public void EvalTestsFunc()
        {
            {       // new June 22 array syntaxer
                Dictionary <string, Object> symbols = new Dictionary <string, object>();

                Eval ev = new Eval(true, true, true, true, true);

                ev.ReturnSymbolValue = (s) =>
                {
                    System.Diagnostics.Debug.WriteLine($"Symbol {s}");
                    if (symbols.ContainsKey(s))
                    {
                        return(symbols[s]);
                    }
                    else
                    {
                        return(new StringParser.ConvertError("No such symbol '" + s + "'"));
                    }
                };

                symbols.Add("Level[0].Rings", 20L);
                symbols.Add("Level[1].Rings", 100L);
                symbols.Add("Value[1]", 1L);
                symbols.Add("index", 1L);

                Object ret = null;

                ret = ev.Evaluate("Level[index].Rings*2");
                Check.That(ret).IsNotNull();
                Check.That(ret).Equals(200);

                ret = ev.Evaluate("Level[0].Rings*2");
                Check.That(ret).IsNotNull();
                Check.That(ret).Equals(40);

                ret = ev.Evaluate("Level[1].Rings*2");
                Check.That(ret).IsNotNull();
                Check.That(ret).Equals(200);


                ret = ev.Evaluate("Level[index-1].Rings*2");
                Check.That(ret).IsNotNull();
                Check.That(ret).Equals(40);

                ret = ev.Evaluate("Level[Value[1]].Rings*2");
                Check.That(ret).IsNotNull();
                Check.That(ret).Equals(200);
            }

            {
                Eval ev = new Eval(true, true, true, true, true);           // test Fakes
                ev.Fake = true;
                ev.ReturnSymbolValue += (s) => {
                    System.Diagnostics.Debug.WriteLine($"Fake Symbol {s}");
                    return(1L);
                };
                var ret = ev.Evaluate("Level[0].Rings*2/fred+jim");
                Check.That(ret).Equals(2);
            }

            {
                Check.That(StringParser.ConvertNumber("0x") == null).IsTrue();

                Object t2 = StringParser.ConvertNumber("0x1a");
                Check.That(t2 != null && (long)t2 == 0x1a).IsTrue();
                Check.That((long)StringParser.ConvertNumber("0xFa1") == 0xfa1).IsTrue();
                Check.That((long)StringParser.ConvertNumber("%0101") == 5).IsTrue();
                Check.That((long)StringParser.ConvertNumber("%01011") == 11).IsTrue();
                Check.That((long)StringParser.ConvertNumber("`1091") == 1091).IsTrue();
                Check.That((long)StringParser.ConvertNumber("012") == 8 * 1 + 2).IsTrue();

                StringParser sp2 = new StringParser("10U20UL30 40LU 50");
                Check.That((long)sp2.ConvertNumber() == 10).IsTrue();
                Check.That((long)sp2.ConvertNumber() == 20).IsTrue();
                Check.That((long)sp2.ConvertNumber() == 30).IsTrue();
                Check.That((long)sp2.ConvertNumber() == 40).IsTrue();
                Check.That((long)sp2.ConvertNumber() == 50).IsTrue();
                Check.That(sp2.IsEOL == true).IsTrue();

                Check.That((double)StringParser.ConvertNumber("1.1", allowfp: true) == 1.1).IsTrue();
                Check.That((double)StringParser.ConvertNumber("1.932", allowfp: true) == 1.932).IsTrue();
                Check.That((double)StringParser.ConvertNumber("1.292A", allowfp: true) == 1.292).IsTrue();
                Check.That((double)StringParser.ConvertNumber("123.456", allowfp: true) == 123.456).IsTrue();
                Check.That((double)StringParser.ConvertNumber("0.456", allowfp: true) == 0.456).IsTrue();
                Check.That((double)StringParser.ConvertNumber(".456", allowfp: true) == 0.456).IsTrue();
                Check.That((double)StringParser.ConvertNumber(".456E2", allowfp: true) == 45.6).IsTrue();
                Check.That(StringParser.ConvertNumber(".456E", allowfp: true) == null).IsTrue();
                Check.That(StringParser.ConvertNumber(".E23", allowfp: true) == null).IsTrue();
                Check.That((double)StringParser.ConvertNumber("1e20", allowfp: true) == 1e20).IsTrue();
                Check.That((double)StringParser.ConvertNumber("1E20", allowfp: true) == 1e20).IsTrue();
                Check.That((double)StringParser.ConvertNumber("1E-20", allowfp: true) == 1e-20).IsTrue();
                Check.That((double)StringParser.ConvertNumber("1E-20.2", allowfp: true) == 1e-20).IsTrue();



                Check.That((string)StringParser.ConvertNumberStringSymbolChar("\"Hello there\"", allowstrings: true) == "Hello there").IsTrue();
                Check.That(((StringParser.ConvertSymbol)StringParser.ConvertNumberStringSymbolChar("_fred", allowstrings: true)).SymbolValue == "_fred").IsTrue();
                Check.That(((StringParser.ConvertSymbol)StringParser.ConvertNumberStringSymbolChar("Fr_ed", allowstrings: true)).SymbolValue == "Fr_ed").IsTrue();

                Check.That((long)StringParser.ConvertNumberStringSymbolChar("1234") == 1234).IsTrue();


                Object t1 = StringParser.ConvertNumberStringSymbolChar("'a'");
                Check.That(t1 != null && (long)t1 == 97).IsTrue();
                Check.That(((StringParser.ConvertError)StringParser.ConvertNumberStringSymbolChar("'a")).ErrorValue == "Incorrectly formatted 'c' expression").IsTrue();
                Check.That(((StringParser.ConvertError)StringParser.ConvertNumberStringSymbolChar("'")).ErrorValue == "Incorrectly formatted 'c' expression").IsTrue();


                // 0
                Check.That((long)Eval.Expr("-1234") == -1234).IsTrue();
                Check.That((double)Eval.Expr("-1234.23", allowfp: true) == -1234.23).IsTrue();
                Check.That((long)Eval.Expr("10") == 10).IsTrue();
                Check.That((long)Eval.Expr("-10") == -10).IsTrue();
                Check.That((double)Eval.Expr("-10.23") == -10.23).IsTrue();

                // 1
                Check.That((long)Eval.Expr("!10") == 0).IsTrue();
                Check.That((long)Eval.Expr("!0") == 1).IsTrue();
                Check.That((long)Eval.Expr("~10") == ~10).IsTrue();
                Check.That((long)Eval.Expr("~0") == ~0).IsTrue();

                //2
                Check.That((long)Eval.Expr(" 10 * 20") == 200).IsTrue();
                Check.That((long)Eval.Expr(" -10 * -20") == 200).IsTrue();
                Check.That((long)Eval.Expr(" 10 * -20") == -200).IsTrue();
                Check.That((long)Eval.Expr(" 10 * -20") == -200).IsTrue();
                Check.That((long)Eval.Expr(" 10 * -20 * 50") == -200 * 50).IsTrue();
                Check.That((long)Eval.Expr(" 10/20") == 0).IsTrue();
                Check.That((double)Eval.Expr(" 10.0/20") == 0.5).IsTrue();
                Check.That((double)Eval.Expr(" -10.0 / 20") == -0.5).IsTrue();
                Check.That((double)Eval.Expr(" -10.0 / 0.01") == -10 / 0.01).IsTrue();
                Check.That((long)Eval.Expr(" 10 % 20") == 10 % 20).IsTrue();
                Check.That((long)Eval.Expr(" 50 % 20") == 50 % 20).IsTrue();

                //3
                Check.That((long)Eval.Expr(" 10 + 20") == 10 + 20).IsTrue();
                Check.That((long)Eval.Expr(" 10 - 20 - 30") == 10 - 20 - 30).IsTrue();
                Check.That((long)Eval.Expr(" 10 - -20") == 30).IsTrue();
                Check.That((double)Eval.Expr(" 10.2 + 20") == 30.2).IsTrue();
                Check.That((double)Eval.Expr(" 10.2 - 10.2") == 0).IsTrue();
                Check.That((double)Eval.Expr(" 5 - 50.5") == 5 - 50.5).IsTrue();
                Check.That((string)Eval.Expr(" \"Hello\" + \"Goodbye\" ") == "HelloGoodbye").IsTrue();
                Check.That(((StringParser.ConvertError)Eval.Expr(" \"Hello\" - \"Goodbye\" ")).ErrorValue.Equals("- is not supported with strings")).IsTrue();
                Check.That(((StringParser.ConvertError)Eval.Expr(" 20 + \"Goodbye\" ")).ErrorValue.Equals("Cannot mix string and number types")).IsTrue();

                //4
                Check.That((long)Eval.Expr(" 10 << 2") == 10 << 2).IsTrue();
                Check.That((long)Eval.Expr(" 1000 >> 2") == 1000 >> 2).IsTrue();
                Check.That(((StringParser.ConvertError)Eval.Expr(" 10.2 << 20")).ErrorValue.Equals("<< and >> requires integer on left side")).IsTrue();
                Check.That(((StringParser.ConvertError)Eval.Expr(" 10 << 20.2")).ErrorValue.Equals("<< and >> requires integer on right side")).IsTrue();
                Check.That((long)Eval.Expr(" 10 - -20") == 30).IsTrue();

                //5
                Check.That((long)Eval.Expr(" 1 > 2 ") == 0).IsTrue();
                Check.That((long)Eval.Expr(" 1 < 2 ") == 1).IsTrue();
                Check.That((long)Eval.Expr(" 1 >= 2 ") == 0).IsTrue();
                Check.That((long)Eval.Expr(" 1 <= 2 ") == 1).IsTrue();
                Check.That((long)Eval.Expr(" 2 >= 2 ") == 1).IsTrue();
                Check.That((long)Eval.Expr(" 3 >= 2 ") == 1).IsTrue();
                Check.That((long)Eval.Expr(" 1.0 > 2 ") == 0).IsTrue();
                Check.That((long)Eval.Expr(" 1.0 < 2 ") == 1).IsTrue();
                Check.That((long)Eval.Expr(" 1.0 >= 2 ") == 0).IsTrue();
                Check.That((long)Eval.Expr(" 1.0 <= 2 ") == 1).IsTrue();
                Check.That((long)Eval.Expr(" 2 >= 2.0 ") == 1).IsTrue();
                Check.That((long)Eval.Expr(" 3 >= 2.0 ") == 1).IsTrue();
                Check.That((long)Eval.Expr(" \"ABC\" > \"AAA\"") == 1).IsTrue();
                Check.That((long)Eval.Expr(" \"AAA\" < \"ABC\"") == 1).IsTrue();
                Check.That((long)Eval.Expr(" \"AAA\" >= \"ABC\"") == 0).IsTrue();
                Check.That((long)Eval.Expr(" \"ABC\" >= \"ABC\"") == 1).IsTrue();

                //6
                Check.That((long)Eval.Expr(" 1 == 2 ") == 0).IsTrue();
                Check.That((long)Eval.Expr(" 2 == 1") == 0).IsTrue();
                Check.That((long)Eval.Expr(" 1 == 1 ") == 1).IsTrue();
                Check.That((long)Eval.Expr(" 1.0 == 1") == 1).IsTrue();
                Check.That((long)Eval.Expr(" 1 == 1.0 ") == 1).IsTrue();
                Check.That((long)Eval.Expr(" \"ABC\" == \"AAA\"") == 0).IsTrue();
                Check.That((long)Eval.Expr(" \"AAA\" != \"ABC\"") == 1).IsTrue();
                Check.That((long)Eval.Expr(" \"AAA\" == \"AAA\"") == 1).IsTrue();
                Check.That((long)Eval.Expr(" \"ABC\" != \"ABC\"") == 0).IsTrue();

                //7
                Check.That((long)Eval.Expr(" 1 & 2 ") == (long)(1 & 2)).IsTrue();
                Check.That((long)Eval.Expr(" 100 & 200 ") == (long)(100 & 200)).IsTrue();
                Check.That(((StringParser.ConvertError)Eval.Expr(" 10.2 & 20")).ErrorValue.Equals("& requires integer on left side")).IsTrue();
                Check.That(((StringParser.ConvertError)Eval.Expr(" 10 & 20.2")).ErrorValue.Equals("& requires integer on right side")).IsTrue();

                //8
                Check.That((long)Eval.Expr(" 1 ^ 2 ") == (long)(1 ^ 2)).IsTrue();
                Check.That((long)Eval.Expr(" 100 ^ 200 ") == (long)(100 ^ 200)).IsTrue();
                Check.That(((StringParser.ConvertError)Eval.Expr(" 10.2 ^ 20")).ErrorValue.Equals("^ requires integer on left side")).IsTrue();
                Check.That(((StringParser.ConvertError)Eval.Expr(" 10 ^ 20.2")).ErrorValue.Equals("^ requires integer on right side")).IsTrue();

                //9
                Check.That((long)Eval.Expr(" 1 | 2 ") == (long)(1 | 2)).IsTrue();
                Check.That((long)Eval.Expr(" 100 | 200 ") == (long)(100 | 200)).IsTrue();
                Check.That(((StringParser.ConvertError)Eval.Expr(" 10.2 | 20")).ErrorValue.Equals("| requires integer on left side")).IsTrue();
                Check.That(((StringParser.ConvertError)Eval.Expr(" 10 | 20.2")).ErrorValue.Equals("| requires integer on right side")).IsTrue();

                //10

                Check.That((long)Eval.Expr(" 1 && 2 ") == 1).IsTrue();
                Check.That((long)Eval.Expr(" 0 && 1 ") == 0).IsTrue();
                Check.That((long)Eval.Expr(" 0 && 0 ") == 0).IsTrue();
                Check.That(((StringParser.ConvertError)Eval.Expr(" 10.0 && 2")).ErrorValue.Equals("&& requires integer on left side")).IsTrue();
                Check.That(((StringParser.ConvertError)Eval.Expr(" 10 && 20.0")).ErrorValue.Equals("&& requires integer on right side")).IsTrue();

                //11

                Check.That((long)Eval.Expr(" 1 || 2 ") == 1).IsTrue();
                Check.That((long)Eval.Expr(" 0 || 1 ") == 1).IsTrue();
                Check.That((long)Eval.Expr(" 0 || 0 ") == 0).IsTrue();
                Check.That(((StringParser.ConvertError)Eval.Expr(" 10.0 || 2")).ErrorValue.Equals("|| requires integer on left side")).IsTrue();
                Check.That(((StringParser.ConvertError)Eval.Expr(" 10 || 20.0")).ErrorValue.Equals("|| requires integer on right side")).IsTrue();

                // Misc

                Check.That(((StringParser.ConvertError)Eval.Expr(" 1 !| 2")).ErrorValue.Equals("Extra characters after expression: !| 2")).IsTrue();
                Check.That(((StringParser.ConvertError)Eval.Expr(" \"string\"", allowstrings: false)).ErrorValue.Equals("Strings not supported")).IsTrue();

                // Brackets

                Check.That((long)Eval.Expr(" 10 * ( 2 + 3 ) ") == 10 * (2 + 3)).IsTrue();
                Check.That(((StringParser.ConvertError)Eval.Expr(" 10 * (2 + 3")).ErrorValue.Equals("Missing ) at end of expression")).IsTrue();
            }

            {
                // Symbols..
                Dictionary <string, Object> symbols = new Dictionary <string, object>();

                Eval ev = new Eval(allowfp: true, allowstrings: true);
                ev.ReturnSymbolValue = (s) =>
                {
                    if (symbols.ContainsKey(s))
                    {
                        return(symbols[s]);
                    }
                    else
                    {
                        return(new StringParser.ConvertError("No such symbol '" + s + "'"));
                    }
                };

                symbols.Add("d20", (double)20.0);
                symbols.Add("d10", (double)10.0);
                symbols.Add("i20", (long)20);
                symbols.Add("i10", (long)10);

                Check.That((long)ev.Evaluate(" i10 + i20 ") == 30).IsTrue();
                Check.That((double)ev.Evaluate(" i10 + d20 ") == 30.0).IsTrue();
                Check.That((double)ev.Evaluate(" d10 + d20 ") == 30.0).IsTrue();
                Check.That(((StringParser.ConvertError)ev.Evaluate(" i20 * i11 ")).ErrorValue.Equals("No such symbol 'i11'")).IsTrue();

                ev.SetSymbolValue = (s, o) =>
                {
                    symbols[s] = o;
                    return(o);
                };

                Check.That((long)ev.Evaluate(" i11 = 20 ") == 20).IsTrue();
                Check.That((long)ev.Evaluate(" i11 ") == 20).IsTrue();
                Check.That((long)ev.Evaluate(" ( i20 + i20 ) * i10 ") == (20 + 20) * 10).IsTrue();
                Check.That(((StringParser.ConvertError)ev.Evaluate(" 20*20 = 20")).ErrorValue.Equals("Lvalue required for = operator")).IsTrue();
                Check.That(((StringParser.ConvertError)ev.Evaluate(" l1 * l1 = 20")).ErrorValue.Equals("No such symbol 'l1'")).IsTrue();
                Check.That(((StringParser.ConvertError)ev.Evaluate(" i20 * 20 = 20")).ErrorValue.Equals("Lvalue required for = operator")).IsTrue();

                ev.ReturnFunctionValue = BaseFunctionsForEval.BaseFunctions;


                Check.That((long)ev.Evaluate(" Abs ( - 20 ) ") == 20).IsTrue();
                Check.That((double)ev.Evaluate(" Abs ( - 20.2 ) ") == 20.2).IsTrue();
                Check.That((double)ev.Evaluate(" Acos ( 1 ) ") == 0).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Asin ( 1 ) ") - 1.57079) < 1E-4).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Atan ( 1 ) ") - 0.78539) < 1E-4).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Ceiling ( 1.99 ) ")) == 2).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Cos ( 1 ) ") - 0.54030) < 1E-4).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Cosh ( 1 ) ") - 1.54308) < 1E-4).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Exp ( 1 ) ") - 2.71828) < 1E-4).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Floor ( 1.99 ) ")) == 1).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Log ( 10 ) ") - 2.3025) < 1E-4).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Log10 ( 10 ) ") - 1) < 1E-4).IsTrue();
                Check.That(Math.Abs((long)ev.Evaluate(" Max ( 1,10 ) ")) == 10).IsTrue();
                Check.That(Math.Abs((long)ev.Evaluate(" Min ( 1,10 ) ")) == 1).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Max ( 1,10.2 ) ")) == 10.2).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Min ( 1.3,10 ) ")) == 1.3).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Pow ( 2,2 ) ") - 4) < 1E-4).IsTrue();
                Check.That(((StringParser.ConvertError)ev.Evaluate(" Pow ( 2 )")).ErrorValue.Equals("Pow() requires 2 parameters minimum")).IsTrue();
                Check.That(((StringParser.ConvertError)ev.Evaluate(" Pow ( 2,3,4 )")).ErrorValue.Equals("Pow() takes 2 parameters maximum")).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Round ( 1.1 ) ") - 1) < 1E-4).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Round ( 1.9 ) ") - 2) < 1E-4).IsTrue();
                Check.That(((StringParser.ConvertError)ev.Evaluate(" Round (1.23456, 3.4)")).ErrorValue.Equals("Round() type mismatch in parameter 2 wanted Integer")).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Round ( 1.123456, 2 ) ") - 1.12) < 1E-4).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Round ( 1.123456, 4 ) ") - 1.1234) < 1E-4).IsTrue();
                Check.That(Math.Abs((long)ev.Evaluate(" Sign ( 1.123456 ) ") - 1) < 1E-4).IsTrue();
                Check.That(Math.Abs((long)ev.Evaluate(" Sign ( -1.123456 ) ") - (-1)) < 1E-4).IsTrue();
                Check.That(Math.Abs((long)ev.Evaluate(" Sign ( 0 ) ") - (0)) < 1E-4).IsTrue();
                Check.That(Math.Abs((long)ev.Evaluate(" Sign ( 1000 ) ") - (1)) < 1E-4).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Sin ( 1 ) ") - 0.84147) < 1E-4).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Sinh ( 1 ) ") - 1.1752) < 1E-4).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Sqrt ( 10 ) ") - 3.16227) < 1E-4).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Tan ( 1 ) ") - 1.5574) < 1E-4).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Tanh ( 1 ) ") - 0.76159) < 1E-4).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Truncate ( 1.222 ) ") - 1) < 1E-4).IsTrue();
                Check.That(Math.Abs((double)ev.Evaluate(" Fp(2) ")) == 2.0).IsTrue();
                Check.That(Math.Abs((long)ev.Evaluate(" Eval(\"2+2\") ")) == 4.0).IsTrue();

                Check.That((string)ev.Evaluate(" ToString(10,\"N1\") ") == "10.0").IsTrue();
                Check.That((string)ev.Evaluate(" ToString(10.2,\"N1\") ") == "10.2").IsTrue();

                Check.That((long)ev.Evaluate(" IsDigit('2')") == 1).IsTrue();
                Check.That((long)ev.Evaluate(" IsDigit('A')") == 0).IsTrue();
                Check.That((long)ev.Evaluate(" IsUpper('A')") == 1).IsTrue();
                Check.That((long)ev.Evaluate(" IsUpper('a')") == 0).IsTrue();
                Check.That((long)ev.Evaluate(" ToUpper('a')") == 65).IsTrue();
                Check.That((long)ev.Evaluate(" ToLower('A')") == 97).IsTrue();
                Check.That((string)ev.Evaluate(" ToLower(\"Hello\")") == "hello").IsTrue();
                Check.That((string)ev.Evaluate(" ToUpper(\"Hello\")") == "HELLO").IsTrue();
                Check.That((string)ev.Evaluate(" Unicode(65)") == "A").IsTrue();
                Check.That((string)ev.Evaluate(" Unicode(329)") == "ʼn").IsTrue();

                Check.That(((StringParser.ConvertError)ev.Evaluate(" fred ( 20 )")).ErrorValue.Equals("fred() not recognised")).IsTrue();
            }

            {
                Eval ev = new Eval(allowfp: true, allowstrings: true);
                StackOfDictionaries <string, Object> symbols = new StackOfDictionaries <string, Object>();
                UserDefinedFunctions userdef = new UserDefinedFunctions(symbols);
                userdef.BaseFunctions = BaseFunctionsForEval.BaseFunctions;

                ev.ReturnSymbolValue = (s) =>
                {
                    if (symbols.ContainsKey(s))
                    {
                        return(symbols[s]);
                    }
                    else
                    {
                        return(new StringParser.ConvertError("No such symbol '" + s + "'"));
                    }
                };

                ev.SetSymbolValue = (s, o) =>
                {
                    symbols[s] = o;
                    return(o);
                };

                ev.ReturnFunctionValue = userdef.Functions;

                userdef.Add("f1", new string[] { }, "10 + 20");

                //  Check.That((long)ev.Evaluate(" 2*f1()+10") == 70).IsTrue();

                userdef.Add("f2", new string[] { "a" }, "a + 20");

                Check.That((long)ev.Evaluate(" 2*f2( 15 )+10") == 2 * (15 + 20) + 10).IsTrue();

                userdef.Add("f3", new string[] { "a", "b", }, "a + b + 20");

                Check.That((long)ev.Evaluate(" 2*f3( 15, 34 )+10") == 2 * (15 + 34 + 20) + 10).IsTrue();

                userdef.Add("f4", new string[] { "a", "b", }, "f2(a) + b + 20");

                Check.That((long)ev.Evaluate(" 2*f4( 15, 34 )+10") == 2 * ((15 + 20) + 34 + 20) + 10).IsTrue();
            }

            System.Diagnostics.Debug.WriteLine("ALL EVAL TESTS FINISHED");
        }