/// <summary>
        /// Tests with the first formula
        /// </summary>
        private static void TestExample1(FunctionEvaluation addition, FunctionEvaluation multiplication,
                                         TerminalEvaluation variable)
        {
            Console.WriteLine("ADD([1.2*VAR_1], MULT([-2.9*VAR_0], [0.3*VAR_2]))");
            Console.WriteLine("-------------------------------------------------");

            const int variableCount = 3;
            const int sampleCount   = 5;

            double[][] data = CreateTestData(variableCount, sampleCount);

            INode multNode = new FunctionalNode(multiplication, new List <INode>()
            {
                new TerminalNode(variable, 2, 0.3),
                new TerminalNode(variable, 0, -2.9)
            });
            INode rootNode = new FunctionalNode(addition, new List <INode>()
            {
                multNode,
                new TerminalNode(variable, 1, 1.2)
            });

            for (var sampleIdx = 0; sampleIdx < sampleCount; sampleIdx++)
            {
                double actual   = rootNode.Evaluate(data, sampleIdx);
                double expected = ((1.2 * data[1][sampleIdx]) + (-2.9 * data[0][sampleIdx] * 0.3 * data[2][sampleIdx]));
                Console.WriteLine(
                    $"ADD([1.2*{data[1][sampleIdx]}], "
                    + $"MULT([-2.9*{data[0][sampleIdx]}], [0.3*{data[2][sampleIdx]}])) "
                    + $"= {actual} "
                    + $"= {expected} "
                    + $"= {actual.AssertAlmostEqual(expected)} ");
            }
        }
Example #2
0
            public ISymbolValue VisitMemberSymbol(MemberSymbol mr)
            {
                if (mr.Definition is DVariable)
                {
                    return(new VariableValue(mr));
                }

                if (!ImplicitlyExecute)
                {
                    return(new TypeValue(mr));
                }

                // If we've got a function here, execute it
                if (mr.Definition is DMethod)
                {
                    Dictionary <DVariable, ISymbolValue> targetArgs;
                    if (!FunctionEvaluation.AssignCallArgumentsToIC(mr, executionArguments, ValueProvider, out targetArgs))
                    {
                        return(null);
                    }

                    return(FunctionEvaluation.Execute(mr, targetArgs, ValueProvider));
                }

                // Are there other types to execute/handle?
                return(null);
            }
        /// <summary>
        /// Creates a functional evaluation method
        /// </summary>
        /// <param name="argument">the string representing the method argument</param>
        /// <param name="resultType">the method result type</param>
        /// <param name="code">the source code of the method body</param>
        /// <returns>the create functional evaluation method delegate</returns>
        private static FunctionEvaluation CreateFunctional(string argument, Type resultType, string code)
        {
            CompilationResults compilationResults;
            FunctionEvaluation function = FunctionalBasis.CompileFunction <FunctionEvaluation>(code, argument, resultType, out compilationResults);

            if (compilationResults.HasErrors)
            {
                throw new InvalidProgramException(
                          $"Addition terminal evaluation failes: Error: {compilationResults.ErrorsExplanation}");
            }

            return(function);
        }
        /// <summary>
        /// Tests with the second formula
        /// </summary>
        private static void TestExample2(FunctionEvaluation addition, FunctionEvaluation multiplication,
                                         TerminalEvaluation variable)
        {
            Console.WriteLine("ADD([2*VAR_0], MULT([4*VAR_1], ADD([-2*VAR_2], MULT([4*VAR_3], [-2*VAR_4]))))");
            Console.WriteLine("-------------------------------------------------");

            const int variableCount = 5;
            const int sampleCount   = 5;

            double[][] data = CreateTestData(variableCount, sampleCount);

            INode mult0Node = new FunctionalNode(multiplication, new List <INode>()
            {
                new TerminalNode(variable, 4, -2),
                new TerminalNode(variable, 3, 4)
            });
            INode add1Node = new FunctionalNode(addition, new List <INode>()
            {
                mult0Node,
                new TerminalNode(variable, 2, -2)
            });
            INode mult2Node = new FunctionalNode(multiplication, new List <INode>()
            {
                add1Node,
                new TerminalNode(variable, 1, 4)
            });
            INode rootNode = new FunctionalNode(addition, new List <INode>()
            {
                mult2Node,
                new TerminalNode(variable, 0, 2)
            });

            for (var sampleIdx = 0; sampleIdx < sampleCount; sampleIdx++)
            {
                double actual   = rootNode.Evaluate(data, sampleIdx);
                double expected = ((2 * data[0][sampleIdx]) +
                                   ((4 * data[1][sampleIdx]) *
                                    (((-2) * data[2][sampleIdx]) +
                                     (4 * data[3][sampleIdx] * (-2) * data[4][sampleIdx]))));
                Console.WriteLine(
                    $"ADD([2*{data[0][sampleIdx]}], "
                    + $"MULT([4*{data[1][sampleIdx]}], "
                    + $"ADD([-2*{data[2][sampleIdx]}], "
                    + $"MULT([4*{data[3][sampleIdx]}], [-2*{data[4][sampleIdx]}])))) "
                    + $"= {actual} "
                    + $"= {expected} "
                    + $"= {actual.AssertAlmostEqual(expected)} ");
            }
        }
        static void Main(string[] args)
        {
            // create varaible function
            TerminalEvaluation variable = CreateTerminal(new [] {
                "double[][] data",
                "int varIdx",
                "int sampleIdx",
                "double coefficient"
            }, typeof(double), "return data[varIdx][sampleIdx] * coefficient;");

            // create addition function
            FunctionEvaluation addition = CreateFunctional("double[] data", typeof(double),
                                                           "double result = 0.0; for (int i = 0; i < data.Length; i++) result += data[i]; return result;");

            // create multiplication function
            FunctionEvaluation multiplication = CreateFunctional("double[] data", typeof(double),
                                                                 "double result = 1.0; for (int i = 0; i < data.Length; i++) result *= data[i]; return result;");

            Console.WriteLine("-------------------------------------------------");
            Console.WriteLine("Test functions:");
            Console.WriteLine("-------------------------------------------------");
            double[][] data = CreateTestData(4, 4);
            Console.WriteLine("TestEvaluation(() => addition([1,2,3]))");
            Console.WriteLine("-------------------------------------------------");
            TestEvaluation(() => addition(new double[] { 1, 2, 3 }), 6.0);
            Console.WriteLine("-------------------------------------------------");
            Console.WriteLine("TestEvaluation(() => multiplication([1,2,3]))");
            Console.WriteLine("-------------------------------------------------");
            TestEvaluation(() => multiplication(new double[] { 1, 2, 3 }), 6.0);
            Console.WriteLine("-------------------------------------------------");
            Console.WriteLine("TestEvaluation(() => varaible([1,2,3], 0, 2, 2))");
            Console.WriteLine("-------------------------------------------------");
            TestEvaluation(() => variable(data, 0, 2, 2.0), (data[0][2] * 2.0));
            Console.WriteLine("-------------------------------------------------");
            Console.WriteLine();

            Console.WriteLine("-------------------------------------------------");
            Console.WriteLine("Test evaluation trees:");
            Console.WriteLine("-------------------------------------------------");
            Console.WriteLine("TestExample1()");
            Console.WriteLine("-------------------------------------------------");
            TestExample1(addition, multiplication, variable);
            Console.WriteLine("-------------------------------------------------");
            Console.WriteLine("TestExample2()");
            Console.WriteLine("-------------------------------------------------");
            TestExample2(addition, multiplication, variable);
            Console.WriteLine("-------------------------------------------------");
        }
        /// <summary>
        /// Evaluates the identifier/template instance as usual.
        /// If the id points to a variable, the initializer/dynamic value will be evaluated using its initializer.
        ///
        /// If ImplicitlyExecute is false but value evaluation is switched on, an InternalOverloadValue-object will be returned
        /// that keeps all overloads passed via 'overloads'
        /// </summary>
        ISemantic TryDoCTFEOrGetValueRefs(AbstractType[] overloads, IExpression idOrTemplateInstance, bool ImplicitlyExecute = true, ISymbolValue[] executionArguments = null)
        {
            if (overloads == null || overloads.Length == 0)
            {
                throw new EvaluationException(idOrTemplateInstance, "No symbols found");
            }

            var r  = overloads[0];
            var ex = new EvaluationException(idOrTemplateInstance, "Ambiguous expression", overloads);

            if (r is MemberSymbol)
            {
                var mr = (MemberSymbol)r;

                // If we've got a function here, execute it
                if (mr.Definition is DMethod)
                {
                    if (ImplicitlyExecute)
                    {
                        if (overloads.Length > 1)
                        {
                            throw ex;
                        }
                        return(FunctionEvaluation.Execute((DMethod)mr.Definition, executionArguments, ValueProvider));
                    }

                    return(new InternalOverloadValue(overloads, idOrTemplateInstance));
                }
                else if (mr.Definition is DVariable)
                {
                    if (overloads.Length > 1)
                    {
                        throw ex;
                    }
                    return(new VariableValue((DVariable)mr.Definition, mr.Base, idOrTemplateInstance));
                }
            }
            else if (r is UserDefinedType)
            {
                if (overloads.Length > 1)
                {
                    throw ex;
                }
                return(new TypeValue(r, idOrTemplateInstance));
            }

            return(null);
        }
        AbstractType TryPretendMethodExecution_(MemberSymbol mr, AbstractType[] execargs = null)
        {
            if (!(mr.Definition is DMethod))
            {
                return(mr);
            }

            Dictionary <DVariable, AbstractType> args;

            if (!FunctionEvaluation.AssignCallArgumentsToIC <AbstractType>(mr, execargs, null, out args, ctxt))
            {
                return(null);
            }

            if ((ctxt.Options & ResolutionOptions.DontResolveBaseTypes) != 0)
            {
                return(mr);
            }

            return(mr.Base);
        }
Example #8
0
        /// <summary>
        /// Evaluates the identifier/template instance as usual.
        /// If the id points to a variable, the initializer/dynamic value will be evaluated using its initializer.
        ///
        /// If ImplicitlyExecute is false but value evaluation is switched on, an InternalOverloadValue-object will be returned
        /// that keeps all overloads passed via 'overloads'
        /// </summary>
        ISymbolValue TryDoCTFEOrGetValueRefs(AbstractType[] overloads, IExpression idOrTemplateInstance, bool ImplicitlyExecute = true, ISymbolValue[] executionArguments = null)
        {
            if (overloads == null || overloads.Length == 0)
            {
                EvalError(idOrTemplateInstance, "No symbols found");
                return(null);
            }

            var          r = overloads[0];
            const string ambigousExprMsg = "Ambiguous expression";

            if (r is TemplateParameterSymbol)
            {
                var tps = (TemplateParameterSymbol)r;

                if ((tps.Parameter is TemplateTypeParameter ||
                     tps.Parameter is TemplateAliasParameter))
                {
                    return(new TypeValue(tps.Base ?? tps));
                }
                if (tps.Parameter is TemplateValueParameter)
                {
                    return(tps.ParameterValue);
                }
                if (tps.Parameter is TemplateTupleParameter)
                {
                    return(new TypeValue(tps.Base));
                }
                //TODO: Are there other evaluable template parameters?
            }
            else if (r is UserDefinedType || r is PackageSymbol || r is ModuleSymbol || r is AliasedType)
            {
                if (overloads.Length > 1)
                {
                    EvalError(idOrTemplateInstance, ambigousExprMsg, overloads);
                    return(null);
                }
                return(new TypeValue(r));
            }
            else if (r is MemberSymbol)
            {
                var mr = (MemberSymbol)r;

                // If we've got a function here, execute it
                if (mr.Definition is DMethod)
                {
                    if (ImplicitlyExecute)
                    {
                        Dictionary <DVariable, ISymbolValue> targetArgs = null, newArgs;

                        foreach (var overload in overloads)
                        {
                            if ((mr = overload as MemberSymbol) != null &&
                                mr.Definition is DMethod &&
                                FunctionEvaluation.AssignCallArgumentsToIC((overload as MemberSymbol).Definition as DMethod, executionArguments, ValueProvider, out newArgs))
                            {
                                if (targetArgs == null)
                                {
                                    targetArgs = newArgs;
                                }
                                else
                                {
                                    EvalError(idOrTemplateInstance, ambigousExprMsg, overloads);
                                    return(null);
                                }
                            }
                        }

                        if (targetArgs == null)
                        {
                            EvalError(idOrTemplateInstance, "No matching overload found", overloads);
                            return(null);
                        }

                        return(FunctionEvaluation.Execute(mr, targetArgs, ValueProvider));
                    }

                    return(new InternalOverloadValue(overloads));
                }
                else if (mr.Definition is DVariable)
                {
                    if (overloads.Length > 1)
                    {
                        EvalError(idOrTemplateInstance, ambigousExprMsg, overloads);
                        return(null);
                    }
                    return(new VariableValue(mr));
                }
            }

            EvalError(idOrTemplateInstance, "Could neither execute nor evaluate symbol value", overloads);
            return(null);
        }