Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
BinaryScalarOperator.cs
2using System.Threading.Tasks;
7
8namespace Waher.Script.Model
9{
13 public enum UpgradeBehaviour
14 {
18 DifferentTypesOk,
19
23 UpgradeIfPossble,
24
28 SameTypeRequired
29 }
30
34 public abstract class BinaryScalarOperator : BinaryOperator
35 {
45 : base(Left, Right, Start, Length, Expression)
46 {
47 }
48
55 {
56 IElement Left = this.left.Evaluate(Variables);
57 IElement Right = this.right.Evaluate(Variables);
58
59 return this.Evaluate(Left, Right, Variables);
60 }
61
67 public override async Task<IElement> EvaluateAsync(Variables Variables)
68 {
69 if (!this.isAsync)
70 return this.Evaluate(Variables);
71
72 IElement Left = await this.left.EvaluateAsync(Variables);
73 IElement Right = await this.right.EvaluateAsync(Variables);
74
75 return await this.EvaluateAsync(Left, Right, Variables);
76 }
77
86 {
87 if (Left.IsScalar)
88 {
89 if (Right.IsScalar)
90 {
91 ISet LeftSet = Left.AssociatedSet;
92 ISet RightSet = Right.AssociatedSet;
94
95 if (!LeftSet.Equals(RightSet) && (UpgradeBehaviour = this.ScalarUpgradeBehaviour) != UpgradeBehaviour.DifferentTypesOk)
96 {
97 if (!Expression.UpgradeField(ref Left, ref LeftSet, ref Right, ref RightSet))
98 {
99 if (UpgradeBehaviour == UpgradeBehaviour.SameTypeRequired)
100 throw new ScriptRuntimeException("Incompatible operands.", this);
101 }
102 }
103
104 return this.EvaluateScalar(Left, Right, Variables);
105 }
106 else
107 {
109
110 foreach (IElement RightChild in Right.ChildElements)
111 Result.Add(this.Evaluate(Left, RightChild, Variables));
112
113 return Right.Encapsulate(Result, this);
114 }
115 }
116 else
117 {
118 if (Right.IsScalar)
119 {
121
122 foreach (IElement LeftChild in Left.ChildElements)
123 Result.Add(this.Evaluate(LeftChild, Right, Variables));
124
125 return Left.Encapsulate(Result, this);
126 }
127 else
128 {
129 ICollection<IElement> LeftChildren = Left.ChildElements;
130 ICollection<IElement> RightChildren = Right.ChildElements;
131
132 if (LeftChildren.Count == RightChildren.Count)
133 {
135 IEnumerator<IElement> eLeft = LeftChildren.GetEnumerator();
136 IEnumerator<IElement> eRight = RightChildren.GetEnumerator();
137
138 try
139 {
140 while (eLeft.MoveNext() && eRight.MoveNext())
141 Result.Add(this.Evaluate(eLeft.Current, eRight.Current, Variables));
142 }
143 finally
144 {
145 eLeft.Dispose();
146 eRight.Dispose();
147 }
148
149 return Left.Encapsulate(Result, this);
150 }
151 else
152 {
154
155 foreach (IElement LeftChild in LeftChildren)
156 {
158
159 foreach (IElement RightChild in RightChildren)
160 RightResult.Add(this.Evaluate(LeftChild, RightChild, Variables));
161
162 LeftResult.Add(Right.Encapsulate(RightResult, this));
163 }
164
165 return Left.Encapsulate(LeftResult, this);
166 }
167 }
168 }
169 }
170
178 public virtual async Task<IElement> EvaluateAsync(IElement Left, IElement Right, Variables Variables)
179 {
180 if (Left.IsScalar)
181 {
182 if (Right.IsScalar)
183 {
184 ISet LeftSet = Left.AssociatedSet;
185 ISet RightSet = Right.AssociatedSet;
187
188 if (!LeftSet.Equals(RightSet) && (UpgradeBehaviour = this.ScalarUpgradeBehaviour) != UpgradeBehaviour.DifferentTypesOk)
189 {
190 if (!Expression.UpgradeField(ref Left, ref LeftSet, ref Right, ref RightSet))
191 {
192 if (UpgradeBehaviour == UpgradeBehaviour.SameTypeRequired)
193 throw new ScriptRuntimeException("Incompatible operands.", this);
194 }
195 }
196
197 return await this.EvaluateScalarAsync(Left, Right, Variables);
198 }
199 else
200 {
202
203 foreach (IElement RightChild in Right.ChildElements)
204 Result.Add(await this.EvaluateAsync(Left, RightChild, Variables));
205
206 return Right.Encapsulate(Result, this);
207 }
208 }
209 else
210 {
211 if (Right.IsScalar)
212 {
214
215 foreach (IElement LeftChild in Left.ChildElements)
216 Result.Add(await this.EvaluateAsync(LeftChild, Right, Variables));
217
218 return Left.Encapsulate(Result, this);
219 }
220 else
221 {
222 ICollection<IElement> LeftChildren = Left.ChildElements;
223 ICollection<IElement> RightChildren = Right.ChildElements;
224
225 if (LeftChildren.Count == RightChildren.Count)
226 {
228 IEnumerator<IElement> eLeft = LeftChildren.GetEnumerator();
229 IEnumerator<IElement> eRight = RightChildren.GetEnumerator();
230
231 try
232 {
233 while (eLeft.MoveNext() && eRight.MoveNext())
234 Result.Add(await this.EvaluateAsync(eLeft.Current, eRight.Current, Variables));
235 }
236 finally
237 {
238 eLeft.Dispose();
239 eRight.Dispose();
240 }
241
242 return Left.Encapsulate(Result, this);
243 }
244 else
245 {
247
248 foreach (IElement LeftChild in LeftChildren)
249 {
251
252 foreach (IElement RightChild in RightChildren)
253 RightResult.Add(await this.EvaluateAsync(LeftChild, RightChild, Variables));
254
255 LeftResult.Add(Right.Encapsulate(RightResult, this));
256 }
257
258 return Left.Encapsulate(LeftResult, this);
259 }
260 }
261 }
262 }
263
272
280 public virtual Task<IElement> EvaluateScalarAsync(IElement Left, IElement Right, Variables Variables)
281 {
282 return Task.FromResult<IElement>(this.EvaluateScalar(Left, Right, Variables));
283 }
284
288 public virtual UpgradeBehaviour ScalarUpgradeBehaviour => UpgradeBehaviour.SameTypeRequired;
289 }
290}
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 bool UpgradeField(ref IElement E1, ref ISet Set1, ref IElement E2, ref ISet Set2)
Upgrades elements if necessary, to a common field extension, trying to make them compatible....
Definition: Expression.cs:5327
Base class for all binary operators.
ScriptNode right
Right operand.
ScriptNode left
Left operand.
bool isAsync
If subtree is asynchroneous.
Base class for binary scalar operators.
BinaryScalarOperator(ScriptNode Left, ScriptNode Right, int Start, int Length, Expression Expression)
Base class for binary scalar operators.
virtual Task< IElement > EvaluateScalarAsync(IElement Left, IElement Right, Variables Variables)
Evaluates the operator on scalar operands.
virtual async Task< IElement > EvaluateAsync(IElement Left, IElement Right, Variables Variables)
Evaluates the operator.
override IElement Evaluate(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
abstract IElement EvaluateScalar(IElement Left, IElement Right, Variables Variables)
Evaluates the operator on scalar operands.
virtual UpgradeBehaviour ScalarUpgradeBehaviour
How scalar operands of different types are to be treated. By default, scalar operands are required to...
override async Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
virtual IElement Evaluate(IElement Left, IElement Right, Variables Variables)
Evaluates the operator.
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
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 ...
virtual Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection. This method should be ...
Definition: ScriptNode.cs:158
Collection of variables.
Definition: Variables.cs:25
Basic interface for all types of elements.
Definition: IElement.cs:21
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 all types of sets.
Definition: ISet.cs:10
UpgradeBehaviour
How operands are to be handled if not of the same type.