Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
VectorIndex.cs
1using System;
2using System.Collections.Generic;
3using System.Reflection;
4using System.Threading.Tasks;
10
12{
17 {
27 public VectorIndex(ScriptNode Left, ScriptNode Right, bool NullCheck, int Start, int Length, Expression Expression)
28 : base(Left, Right, NullCheck, Start, Length, Expression)
29 {
30 this.isAsync = true;
31 }
32
37 public override bool IsAsynchronous => true;
38
45 {
46 return this.EvaluateAsync(Variables).Result;
47 }
48
54 public override async Task<IElement> EvaluateAsync(Variables Variables)
55 {
56 IElement Left = this.left.Evaluate(Variables);
57 if (this.nullCheck && Left.AssociatedObjectValue is null)
58 return Left;
59
60 IElement Right = this.right.Evaluate(Variables);
61
62 return await EvaluateIndex(Left, Right, this.nullCheck, this);
63 }
64
73 public static async Task<IElement> EvaluateIndex(IElement Vector, IElement Index, bool NullCheck, ScriptNode Node)
74 {
75 if (Vector is IVector V)
76 return EvaluateIndex(V, Index, Node);
77 else if (Vector is ISet S)
78 {
79 int i = (int)Expression.ToDouble(Index.AssociatedObjectValue);
80 if (i < 0)
81 throw new ScriptRuntimeException("Index must be a non-negative number.", Node);
82
83 foreach (IElement E in S.ChildElements)
84 {
85 if (i-- == 0)
86 return E;
87 }
88
89 throw new ScriptRuntimeException("Index out of range.", Node);
90 }
91 else if (Vector.IsScalar)
92 {
93 if (Vector is StringValue s)
94 return EvaluateIndex(s, Index, Node);
95 else
96 {
97 object Object = Vector.AssociatedObjectValue;
98 if (Object is null)
99 {
100 if (NullCheck)
101 return Vector;
102 else
103 throw new ScriptRuntimeException("Vector is null.", Node);
104 }
105
106 Type T = Object.GetType();
107 if (!TryGetIndexProperty(T, true, false, out PropertyInfo ItemProperty, out ParameterInfo[] Parameters))
108 throw new ScriptRuntimeException("The index operator operates on vectors.", Node);
109
110 return await EvaluateIndex(Object, T, ItemProperty, Parameters, Index, Node);
111 }
112 }
113 else
114 {
115 LinkedList<IElement> Elements = new LinkedList<IElement>();
116
117 foreach (IElement E in Vector.ChildElements)
118 Elements.AddLast(await EvaluateIndex(E, Index, NullCheck, Node));
119
120 return Vector.Encapsulate(Elements, Node);
121 }
122 }
123
133 public static bool TryGetIndexProperty(Type T, bool ForReading, bool ForWriting, out PropertyInfo PropertyInfo, out ParameterInfo[] Parameters)
134 {
135 lock (indexProperties)
136 {
137 if (indexProperties.TryGetValue(T, out KeyValuePair<PropertyInfo, ParameterInfo[]> P))
138 {
139 PropertyInfo = P.Key;
140 Parameters = P.Value;
141 return true;
142 }
143
144 foreach (PropertyInfo P2 in T.GetRuntimeProperties())
145 {
146 if (P2.Name != "Item")
147 continue;
148
149 if (ForReading && (!P2.CanRead || !P2.GetMethod.IsPublic))
150 continue;
151
152 if (ForWriting && (!P2.CanWrite || !P2.SetMethod.IsPublic))
153 continue;
154
155 Parameters = P2.GetIndexParameters();
156 if (Parameters is null || Parameters.Length != 1)
157 continue;
158
159 indexProperties[T] = new KeyValuePair<PropertyInfo, ParameterInfo[]>(P2, Parameters);
160 PropertyInfo = P2;
161
162 return true;
163 }
164 }
165
166 PropertyInfo = null;
167 Parameters = null;
168
169 return false;
170 }
171
172 private static readonly Dictionary<Type, KeyValuePair<PropertyInfo, ParameterInfo[]>> indexProperties = new Dictionary<Type, KeyValuePair<PropertyInfo, ParameterInfo[]>>();
173
174 private static async Task<IElement> EvaluateIndex(object Object, Type T, PropertyInfo ItemProperty, ParameterInfo[] Parameters,
175 IElement Index, ScriptNode Node)
176 {
177 if (Index.TryConvertTo(Parameters[0].ParameterType, out object IndexValue))
178 {
179 object Result = await WaitPossibleTask(ItemProperty.GetValue(Object, new object[] { IndexValue }));
180 return Expression.Encapsulate(Result);
181 }
182
183 if (Index.IsScalar)
184 throw new ScriptRuntimeException("Provided index value not compatible with expected index type.", Node);
185
186 LinkedList<IElement> Elements = new LinkedList<IElement>();
187
188 foreach (IElement E in Index.ChildElements)
189 Elements.AddLast(await EvaluateIndex(Object, T, ItemProperty, Parameters, E, Node));
190
191 return Index.Encapsulate(Elements, Node);
192 }
193
194 private static IElement EvaluateIndex(StringValue s, IElement Index, ScriptNode Node)
195 {
196 if (Index.IsScalar)
197 {
198 int i = (int)Expression.ToDouble(Index.AssociatedObjectValue);
199 return new StringValue(new string(s.Value[i], 1), s.CaseInsensitive);
200 }
201 else
202 {
203 LinkedList<IElement> Elements = new LinkedList<IElement>();
204
205 foreach (IElement E in Index.ChildElements)
206 Elements.AddLast(EvaluateIndex(s, E, Node));
207
208 return Index.Encapsulate(Elements, Node);
209 }
210 }
211
219 public static IElement EvaluateIndex(IVector Vector, IElement Index, ScriptNode Node)
220 {
221 if (Index.AssociatedObjectValue is double d)
222 {
223 if (d < 0 || d > int.MaxValue || d != Math.Truncate(d))
224 throw new ScriptRuntimeException("Index must be a non-negative integer.", Node);
225
226 return Vector.GetElement((int)d);
227 }
228
229 if (Index.IsScalar)
230 throw new ScriptRuntimeException("Index must be a non-negative integer.", Node);
231 else
232 {
233 LinkedList<IElement> Elements = new LinkedList<IElement>();
234
235 foreach (IElement E in Index.ChildElements)
236 Elements.AddLast(EvaluateIndex(Vector, E, Node));
237
238 return Index.Encapsulate(Elements, Node);
239 }
240 }
241
242 }
243}
Class managing a script expression.
Definition: Expression.cs:39
static IElement Encapsulate(object Value)
Encapsulates an object.
Definition: Expression.cs:4955
static double ToDouble(object Object)
Converts an object to a double value.
Definition: Expression.cs:4824
ScriptNode right
Right operand.
ScriptNode left
Left operand.
Base class for all unary operators performing operand null checks.
readonly bool nullCheck
If null should be returned if operand is null.
Base class for all nodes in a parsed script tree.
Definition: ScriptNode.cs:69
int Length
Length of expression covered by node.
Definition: ScriptNode.cs:101
static async Task< object > WaitPossibleTask(object Result)
Waits for any asynchronous process to terminate.
Definition: ScriptNode.cs:417
int Start
Start position in script expression.
Definition: ScriptNode.cs:92
abstract IElement Evaluate(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection. This method should be ...
string Value
String value.
Definition: StringValue.cs:46
bool CaseInsensitive
If the string value is case insensitive or not.
Definition: StringValue.cs:55
static async Task< IElement > EvaluateIndex(IElement Vector, IElement Index, bool NullCheck, ScriptNode Node)
Evaluates the vector index operator.
Definition: VectorIndex.cs:73
static IElement EvaluateIndex(IVector Vector, IElement Index, ScriptNode Node)
Evaluates the vector index operator.
Definition: VectorIndex.cs:219
override async Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
Definition: VectorIndex.cs:54
override IElement Evaluate(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
Definition: VectorIndex.cs:44
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.
Definition: VectorIndex.cs:133
VectorIndex(ScriptNode Left, ScriptNode Right, bool NullCheck, int Start, int Length, Expression Expression)
Vector Index operator.
Definition: VectorIndex.cs:27
override bool IsAsynchronous
If the node (or its decendants) include asynchronous evaluation. Asynchronous nodes should be evaluat...
Definition: VectorIndex.cs:37
Collection of variables.
Definition: Variables.cs:25
Basic interface for all types of elements.
Definition: IElement.cs:20
bool TryConvertTo(Type DesiredType, out object Value)
Converts the value to a .NET type.
object AssociatedObjectValue
Associated object value.
Definition: IElement.cs:33
ICollection< IElement > ChildElements
An enumeration of child elements. If the element is a scalar, this property will return null.
Definition: IElement.cs:49
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.
Definition: IElement.cs:41
Basic interface for vectors.
Definition: IVector.cs:9
IElement GetElement(int Index)
Gets an element of the vector.
Basic interface for all types of sets.
Definition: ISet.cs:10