2using System.Reflection;
 
    3using System.Collections.Generic;
 
    8using System.Threading.Tasks;
 
   19        private readonly 
string name;
 
   21        private readonly 
int nrParameters;
 
   49        public string Name => this.name;
 
   81            object Object = 
Operand.AssociatedObjectValue;
 
   93                T = Object?.GetType() ?? typeof(
object);
 
   99            Arguments = 
new IElement[this.nrParameters];
 
  100            for (i = 0; i < this.nrParameters; i++)
 
  110                LinkedList<IElement> Elements = 
new LinkedList<IElement>();
 
  115                return Operand.Encapsulate(Elements, 
this);
 
  132            object[] ParameterValues;
 
  135            bool DoExtend = 
false;
 
  138            lock (this.synchObject)
 
  140                if (this.lastType != T)
 
  143                    this.methodType = MethodType.Method;
 
  145                    this.byReference = 
null;
 
  149                if (!(this.method is 
null) && this.methodType == MethodType.Method)
 
  151                    if (this.methodParametersTypes.Length != 
this.nrParameters)
 
  154                        this.methodType = MethodType.Method;
 
  156                        this.byReference = 
null;
 
  160                        for (i = 0; i < this.methodParametersTypes.Length; i++)
 
  162                            PT = this.methodParametersTypes[i].ParameterType;
 
  164                            if (PT.IsByRef && Arguments[i].
TryConvertTo(PT.GetElementType(), out Value))
 
  166                                this.methodArgumentExtensions[i] = 
false;
 
  167                                this.methodArguments[i] = Value;
 
  169                            else if (Arguments[i].TryConvertTo(PT, out Value))
 
  171                                this.methodArgumentExtensions[i] = 
false;
 
  172                                this.methodArguments[i] = Value;
 
  176                                if (Arguments[i].IsScalar || 
Variables is 
null)
 
  179                                this.methodArgumentExtensions[i] = 
true;
 
  180                                this.methodArguments[i] = 
null;
 
  185                        if (i < this.methodParametersTypes.Length)
 
  188                            this.methodType = MethodType.Method;
 
  190                            this.byReference = 
null;
 
  195                if (this.method is 
null)
 
  197                    if (this.methods is 
null)
 
  198                        this.methods = this.GetMethods(T);
 
  200                    List<KeyValuePair<string, int>> ByRef = 
null;
 
  201                    ParameterValues = 
null;
 
  204                    foreach (MethodRec Rec 
in this.methods)
 
  208                        if (Instance is 
null)
 
  210                            if (!Rec.Method.IsStatic)
 
  215                            if (Rec.Method.IsStatic)
 
  219                        if (Rec.MethodType == MethodType.Method)
 
  221                            for (i = 0; i < this.nrParameters; i++)
 
  223                                PT = Rec.Parameters[i].ParameterType;
 
  229                                    if (ParameterValues is 
null)
 
  231                                        Extend = 
new bool[this.nrParameters];
 
  232                                        ParameterValues = 
new object[this.nrParameters];
 
  236                                    ParameterValues[i] = Value;
 
  239                                        ByRef = 
new List<KeyValuePair<string, int>>();
 
  242                                        ByRef.Add(
new KeyValuePair<string, int>(Ref.VariableName, i));
 
  244                                        ByRef.Add(
new KeyValuePair<string, int>(
null, i));
 
  248                                    if (ParameterValues is 
null)
 
  250                                        Extend = 
new bool[this.nrParameters];
 
  251                                        ParameterValues = 
new object[this.nrParameters];
 
  255                                    ParameterValues[i] = Value;
 
  264                                        Extend = 
new bool[this.nrParameters];
 
  265                                        ParameterValues = 
new object[this.nrParameters];
 
  269                                    ParameterValues[i] = 
null;
 
  274                            if (i < this.nrParameters)
 
  281                        this.method = Rec.Method;
 
  282                        this.methodType = Rec.MethodType;
 
  283                        this.methodParametersTypes = Rec.Parameters;
 
  284                        this.methodArguments = ParameterValues;
 
  285                        this.methodArgumentExtensions = Extend;
 
  287                        if (!(ByRef is 
null) && ByRef.Count > 0)
 
  288                            this.byReference = ByRef.ToArray();
 
  290                            this.byReference = 
null;
 
  295                    if (this.method is 
null)
 
  302                if (!(this.byReference is 
null))
 
  303                    throw new ScriptException(
"Canonical extensions of method calls having reference type arguments not supported.");   
 
  305                return await this.EvaluateCanonicalAsync(Instance, this.method, this.methodType, this.methodParametersTypes, 
 
  306                    Arguments, this.methodArguments, this.methodArgumentExtensions, 
Variables);
 
  310                Value = await this.
EvaluateAsync(Instance, this.method, this.methodType, Arguments, this.methodArguments, 
Variables);
 
  315        private async Task<IElement> 
EvaluateAsync(
object Instance, MethodInfo Method, MethodType MethodType,
 
  322                case MethodType.Method:
 
  324                    Value = Method.Invoke(Instance, ArgumentValues);
 
  327                    if (!(this.byReference is 
null))
 
  329                        int i, j, c = this.byReference.Length;
 
  332                        for (i = 0; i < c; i++)
 
  334                            j = this.byReference[i].Value;
 
  335                            if (
string.IsNullOrEmpty(s = this.byReference[i].Key))
 
  344                case MethodType.LambdaProperty:
 
  351                    Value = await LambdaExpression.EvaluateAsync(Arguments, 
Variables);
 
  354                case MethodType.LambdaIndexProperty:
 
  355                    Value = Method.Invoke(Instance, 
new object[] { this.name });
 
  359                    if (LambdaExpression is 
null)
 
  362                    Value = await LambdaExpression.EvaluateAsync(Arguments, 
Variables);
 
  369        private async Task<IElement> EvaluateCanonicalAsync(
object Object, MethodInfo Method, MethodType MethodType,
 
  372            IEnumerator<IElement>[] Enumerators = 
null;
 
  373            ICollection<IElement> Children;
 
  374            IEnumerator<IElement> e;
 
  378            for (i = 0; i < this.nrParameters; i++)
 
  382                    if (Arguments[i].IsScalar)
 
  384                        if (!Arguments[i].TryConvertTo(ParametersTypes[i].ParameterType, out ArgumentValues[i]))
 
  392                            Enumerators = 
new IEnumerator<IElement>[this.nrParameters];
 
  393                            First = Arguments[i];
 
  396                        else if (c != Children.Count)
 
  399                        Enumerators[i] = Children.GetEnumerator();
 
  406                object Value = await this.
EvaluateAsync(Object, Method, MethodType, Arguments, ArgumentValues, 
Variables);
 
  410            LinkedList<IElement> Elements = 
new LinkedList<IElement>();
 
  411            Arguments = (
IElement[])Arguments.Clone();
 
  415                for (i = 0; i < this.nrParameters; i++)
 
  420                    if (!(e = Enumerators[i]).MoveNext())
 
  423                    Arguments[i] = e.Current;
 
  426                if (i < this.nrParameters)
 
  429                Elements.AddLast(await this.EvaluateCanonicalAsync(Object, Method, MethodType, ParametersTypes, Arguments, 
 
  433            for (i = 0; i < this.nrParameters; i++)
 
  436                    Enumerators[i].Dispose();
 
  442        private MethodRec[] GetMethods(Type Type)
 
  444            List<MethodRec> Result = 
new List<MethodRec>();
 
  445            ParameterInfo[] ParameterInfo;
 
  446            IEnumerable<MethodInfo> Methods = Type.GetRuntimeMethods();
 
  448            foreach (MethodInfo MI 
in Methods)
 
  450                if (MI.IsAbstract || !MI.IsPublic || MI.Name != 
this.name)
 
  453                ParameterInfo = MI.GetParameters();
 
  454                if (ParameterInfo.Length != 
this.nrParameters)
 
  457                Result.Add(
new MethodRec()
 
  461                    MethodType = MethodType.Method
 
  465            if (Result.Count == 0)
 
  467                PropertyInfo PI = Type.GetRuntimeProperty(this.name);
 
  468                if (!(PI is 
null) && PI.GetIndexParameters().Length == 0)
 
  472                    else if (!PI.GetMethod.IsPublic)
 
  476                        Result.Add(
new MethodRec()
 
  478                            Method = PI.GetMethod,
 
  480                            MethodType = MethodType.LambdaProperty
 
  486                    Result.Add(
new MethodRec()
 
  488                        Method = PI.GetMethod,
 
  490                        MethodType = MethodType.LambdaIndexProperty
 
  495            return Result.ToArray();
 
  498        private enum MethodType
 
  505        private class MethodRec
 
  507            public MethodInfo Method;
 
  508            public ParameterInfo[] Parameters;
 
  509            public MethodType MethodType;
 
  512        private Type lastType = 
null;
 
  513        private MethodInfo method = 
null;
 
  514        private MethodType methodType = MethodType.Method;
 
  515        private ParameterInfo[] methodParametersTypes = 
null;
 
  516        private MethodRec[] methods = 
null;
 
  517        private KeyValuePair<string, int>[] byReference = 
null;
 
  518        private object[] methodArguments = 
null;
 
  519        private bool[] methodArgumentExtensions = 
null;
 
  520        private readonly 
object synchObject = 
new object();
 
  535                if (!this.parameters.ForAllChildNodes(Callback, State, Order))
 
  541            for (i = 0; i < this.nrParameters; i++)
 
  543                Node = this.parameters[i];
 
  546                    bool b = !Callback(Node, out 
ScriptNode NewNode, State);
 
  547                    if (!(NewNode is 
null))
 
  549                        this.parameters[i] = Node = NewNode;
 
  560                if (!this.parameters.ForAllChildNodes(Callback, State, Order))
 
  571                this.name == O.name &&
 
  572                AreEqual(this.parameters, O.parameters) &&
 
  579            int Result = base.GetHashCode();
 
  581            Result ^= Result << 5 ^ 
GetHashCode(this.parameters);
 
Static class that dynamically manages types and interfaces available in the runtime environment.
static object[] NoParameters
Contains an empty array of parameter values.
Base class for script exceptions.
Script runtime exception.
Class managing a script expression.
static IElement Encapsulate(object Value)
Encapsulates an object.
Base class for all unary operators performing operand null checks.
bool NullCheck
If null check is to be used.
readonly bool nullCheck
If null should be returned if operand is null.
Base class for all nodes in a parsed script tree.
bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, bool DepthFirst)
Calls the callback method for all child nodes.
int Length
Length of expression covered by node.
static bool AreEqual(ScriptNode S1, ScriptNode S2)
Compares if two script nodes are equal.
static async Task< object > WaitPossibleTask(object Result)
Waits for any asynchronous process to terminate.
int Start
Start position in script expression.
void SetParent(ScriptNode Parent)
Sets the parent node. Can only be used when expression is being parsed.
ScriptNode Operand
Operand.
Represents a variable reference.
static readonly ObjectValue Null
Null value.
Named method call operator.
override bool Equals(object obj)
override int GetHashCode()
override bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, SearchMethod Order)
Calls the callback method for all child nodes.
override bool IsAsynchronous
If the node (or its decendants) include asynchronous evaluation. Asynchronous nodes should be evaluat...
override async Task< IElement > EvaluateAsync(IElement Operand, Variables Variables)
Evaluates the node, using the variables provided in the Variables  collection.
ScriptNode[] Parameters
Method arguments.
override IElement Evaluate(IElement Operand, Variables Variables)
Evaluates the node, using the variables provided in the Variables  collection.
async Task< IElement > EvaluateAsync(Type T, object Instance, IElement[] Arguments, Variables Variables)
Executes a code-behind method.
NamedMethodCall(ScriptNode Operand, string Name, ScriptNode[] Parameters, bool NullCheck, int Start, int Length, Expression Expression)
Named method call operator.
static bool TryGetIndexProperty(Type T, bool ForReading, bool ForWriting, out PropertyInfo PropertyInfo, out ParameterInfo[] Parameters)
Tries to get a one-dimensional index property of a Type.
Basic interface for all types of elements.
bool TryConvertTo(Type DesiredType, out object Value)
Converts the value to a .NET type.
object AssociatedObjectValue
Associated object value.
ICollection< IElement > ChildElements
An enumeration of child elements. If the element is a scalar, this property will return null.
IElement Encapsulate(ICollection< IElement > Elements, ScriptNode Node)
Encapsulates a set of elements into a similar structure as that provided by the current element.
bool IsScalar
If the element represents a scalar value.
Base interface for lambda expressions.
delegate bool ScriptNodeEventHandler(ScriptNode Node, out ScriptNode NewNode, object State)
Delegate for ScriptNode callback methods.
SearchMethod
Method to traverse the expression structure