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;
3using System.Reflection;
4using System.Threading.Tasks;
11
13{
18 {
28 public VectorIndex(ScriptNode Left, ScriptNode Right, bool NullCheck, int Start, int Length, Expression Expression)
29 : base(Left, Right, NullCheck, Start, Length, Expression)
30 {
31 this.isAsync = true;
32 }
33
38 public override bool IsAsynchronous => true;
39
46 {
47 return this.EvaluateAsync(Variables).Result;
48 }
49
55 public override async Task<IElement> EvaluateAsync(Variables Variables)
56 {
57 IElement Left = this.left.Evaluate(Variables);
58 if (this.nullCheck && Left.AssociatedObjectValue is null)
59 return Left;
60
61 IElement Right = this.right.Evaluate(Variables);
62
63 return await EvaluateIndex(Left, Right, this.nullCheck, this);
64 }
65
74 public static async Task<IElement> EvaluateIndex(IElement Vector, IElement Index, bool NullCheck, ScriptNode Node)
75 {
76 if (Vector is IVector V)
77 return EvaluateIndex(V, Index, Node);
78 else if (Vector is ISet S)
79 {
80 int i = (int)Expression.ToDouble(Index.AssociatedObjectValue);
81 if (i < 0)
82 throw new ScriptRuntimeException("Index must be a non-negative number.", Node);
83
84 foreach (IElement E in S.ChildElements)
85 {
86 if (i-- == 0)
87 return E;
88 }
89
90 throw new ScriptRuntimeException("Index out of range.", Node);
91 }
92 else if (Vector.IsScalar)
93 {
94 if (Vector is StringValue s)
95 return EvaluateIndex(s, Index, Node);
96 else
97 {
98 object Object = Vector.AssociatedObjectValue;
99 if (Object is null)
100 {
101 if (NullCheck)
102 return Vector;
103 else
104 throw new ScriptRuntimeException("Vector is null.", Node);
105 }
106
107 Type T = Object.GetType();
108 if (!TryGetIndexProperty(T, true, false, out PropertyInfo ItemProperty,
109 out ParameterInfo[] Parameters) ||
110 (Parameters?.Length ?? 0) != 1)
111 {
112 throw new ScriptRuntimeException("The index operator operates on vectors.", Node);
113 }
114
115 return await EvaluateIndex(Object, T, ItemProperty, Parameters, Index, Node);
116 }
117 }
118 else
119 {
121
122 foreach (IElement E in Vector.ChildElements)
123 Elements.Add(await EvaluateIndex(E, Index, NullCheck, Node));
124
125 return Vector.Encapsulate(Elements, Node);
126 }
127 }
128
138 public static bool TryGetIndexProperty(Type T, bool ForReading, bool ForWriting,
139 out PropertyInfo PropertyInfo, out ParameterInfo[] Parameters)
140 {
141 lock (indexProperties)
142 {
143 if (indexProperties.TryGetValue(T, out KeyValuePair<PropertyInfo, ParameterInfo[]> P))
144 {
145 PropertyInfo = P.Key;
146 Parameters = P.Value;
147 return true;
148 }
149
150 foreach (PropertyInfo P2 in T.GetRuntimeProperties())
151 {
152 if (P2.Name != "Item")
153 continue;
154
155 if (ForReading && (!P2.CanRead || !P2.GetMethod.IsPublic))
156 continue;
157
158 if (ForWriting && (!P2.CanWrite || !P2.SetMethod.IsPublic))
159 continue;
160
161 Parameters = P2.GetIndexParameters();
162 if (Parameters is null || Parameters.Length != 1)
163 continue;
164
165 indexProperties[T] = new KeyValuePair<PropertyInfo, ParameterInfo[]>(P2, Parameters);
166 PropertyInfo = P2;
167
168 return true;
169 }
170 }
171
172 PropertyInfo = null;
173 Parameters = null;
174
175 return false;
176 }
177
178 private static readonly Dictionary<Type, KeyValuePair<PropertyInfo, ParameterInfo[]>> indexProperties = new Dictionary<Type, KeyValuePair<PropertyInfo, ParameterInfo[]>>();
179
180 internal static async Task<IElement> EvaluateIndex(object Object, Type T, PropertyInfo ItemProperty, ParameterInfo[] Parameters,
181 IElement Index, ScriptNode Node)
182 {
183 if (Index.TryConvertTo(Parameters[0].ParameterType, out object IndexValue))
184 {
185 object Result = await WaitPossibleTask(ItemProperty.GetValue(Object, new object[] { IndexValue }));
186 return Expression.Encapsulate(Result);
187 }
188
189 if (Index.IsScalar)
190 throw new ScriptRuntimeException("Provided index value not compatible with expected index type.", Node);
191
193
194 foreach (IElement E in Index.ChildElements)
195 Elements.Add(await EvaluateIndex(Object, T, ItemProperty, Parameters, E, Node));
196
197 return Index.Encapsulate(Elements, Node);
198 }
199
200 private static IElement EvaluateIndex(StringValue s, IElement Index, ScriptNode Node)
201 {
202 if (Index.IsScalar)
203 {
204 int i = (int)Expression.ToDouble(Index.AssociatedObjectValue);
205 return new StringValue(new string(s.Value[i], 1), s.CaseInsensitive);
206 }
207 else
208 {
210
211 foreach (IElement E in Index.ChildElements)
212 Elements.Add(EvaluateIndex(s, E, Node));
213
214 return Index.Encapsulate(Elements, Node);
215 }
216 }
217
225 public static IElement EvaluateIndex(IVector Vector, IElement Index, ScriptNode Node)
226 {
227 if (Index.AssociatedObjectValue is double d)
228 {
229 if (d < 0 || d > int.MaxValue || d != Math.Truncate(d))
230 throw new ArgumentNonNegativeIntegerScriptException("Index", Node);
231
232 return Vector.GetElement((int)d);
233 }
234
235 if (Index.IsScalar)
236 throw new ArgumentNonNegativeIntegerScriptException("Index", Node);
237 else
238 {
240
241 foreach (IElement E in Index.ChildElements)
242 Elements.Add(EvaluateIndex(Vector, E, Node));
243
244 return Index.Encapsulate(Elements, Node);
245 }
246 }
247
248 }
249}
A chunked list is a linked list of chunks of objects of type T .
Definition: ChunkedList.cs:54
void Add(T Item)
Adds an item to the collection.
Definition: ChunkedList.cs:272
Class managing a script expression.
Definition: Expression.cs:41
static IElement Encapsulate(object Value)
Encapsulates an object.
Definition: Expression.cs:5241
static double ToDouble(object Object)
Converts an object to a double value.
Definition: Expression.cs:5110
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:441
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:47
bool CaseInsensitive
If the string value is case insensitive or not.
Definition: StringValue.cs:56
static async Task< IElement > EvaluateIndex(IElement Vector, IElement Index, bool NullCheck, ScriptNode Node)
Evaluates the vector index operator.
Definition: VectorIndex.cs:74
static IElement EvaluateIndex(IVector Vector, IElement Index, ScriptNode Node)
Evaluates the vector index operator.
Definition: VectorIndex.cs:225
override async Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
Definition: VectorIndex.cs:55
override IElement Evaluate(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
Definition: VectorIndex.cs:45
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:138
VectorIndex(ScriptNode Left, ScriptNode Right, bool NullCheck, int Start, int Length, Expression Expression)
Vector Index operator.
Definition: VectorIndex.cs:28
override bool IsAsynchronous
If the node (or its decendants) include asynchronous evaluation. Asynchronous nodes should be evaluat...
Definition: VectorIndex.cs:38
Collection of variables.
Definition: Variables.cs:25
Basic interface for all types of elements.
Definition: IElement.cs:21
bool TryConvertTo(Type DesiredType, out object Value)
Converts the value to a .NET type.
object AssociatedObjectValue
Associated object value.
Definition: IElement.cs:34
ICollection< IElement > ChildElements
An enumeration of child elements. If the element is a scalar, this property will return null.
Definition: IElement.cs:50
IElement Encapsulate(ChunkedList< 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:42
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