Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
BinaryScalarOperator.cs
1using System.Collections.Generic;
2using System.Threading.Tasks;
6
7namespace Waher.Script.Model
8{
12 public enum UpgradeBehaviour
13 {
17 DifferentTypesOk,
18
22 UpgradeIfPossble,
23
27 SameTypeRequired
28 }
29
33 public abstract class BinaryScalarOperator : BinaryOperator
34 {
44 : base(Left, Right, Start, Length, Expression)
45 {
46 }
47
54 {
55 IElement Left = this.left.Evaluate(Variables);
56 IElement Right = this.right.Evaluate(Variables);
57
58 return this.Evaluate(Left, Right, Variables);
59 }
60
66 public override async Task<IElement> EvaluateAsync(Variables Variables)
67 {
68 if (!this.isAsync)
69 return this.Evaluate(Variables);
70
71 IElement Left = await this.left.EvaluateAsync(Variables);
72 IElement Right = await this.right.EvaluateAsync(Variables);
73
74 return await this.EvaluateAsync(Left, Right, Variables);
75 }
76
85 {
86 if (Left.IsScalar)
87 {
88 if (Right.IsScalar)
89 {
90 ISet LeftSet = Left.AssociatedSet;
91 ISet RightSet = Right.AssociatedSet;
93
94 if (!LeftSet.Equals(RightSet) && (UpgradeBehaviour = this.ScalarUpgradeBehaviour) != UpgradeBehaviour.DifferentTypesOk)
95 {
96 if (!Expression.UpgradeField(ref Left, ref LeftSet, ref Right, ref RightSet))
97 {
98 if (UpgradeBehaviour == UpgradeBehaviour.SameTypeRequired)
99 throw new ScriptRuntimeException("Incompatible operands.", this);
100 }
101 }
102
103 return this.EvaluateScalar(Left, Right, Variables);
104 }
105 else
106 {
107 LinkedList<IElement> Result = new LinkedList<IElement>();
108
109 foreach (IElement RightChild in Right.ChildElements)
110 Result.AddLast(this.Evaluate(Left, RightChild, Variables));
111
112 return Right.Encapsulate(Result, this);
113 }
114 }
115 else
116 {
117 if (Right.IsScalar)
118 {
119 LinkedList<IElement> Result = new LinkedList<IElement>();
120
121 foreach (IElement LeftChild in Left.ChildElements)
122 Result.AddLast(this.Evaluate(LeftChild, Right, Variables));
123
124 return Left.Encapsulate(Result, this);
125 }
126 else
127 {
128 ICollection<IElement> LeftChildren = Left.ChildElements;
129 ICollection<IElement> RightChildren = Right.ChildElements;
130
131 if (LeftChildren.Count == RightChildren.Count)
132 {
133 LinkedList<IElement> Result = new LinkedList<IElement>();
134 IEnumerator<IElement> eLeft = LeftChildren.GetEnumerator();
135 IEnumerator<IElement> eRight = RightChildren.GetEnumerator();
136
137 try
138 {
139 while (eLeft.MoveNext() && eRight.MoveNext())
140 Result.AddLast(this.Evaluate(eLeft.Current, eRight.Current, Variables));
141 }
142 finally
143 {
144 eLeft.Dispose();
145 eRight.Dispose();
146 }
147
148 return Left.Encapsulate(Result, this);
149 }
150 else
151 {
152 LinkedList<IElement> LeftResult = new LinkedList<IElement>();
153
154 foreach (IElement LeftChild in LeftChildren)
155 {
156 LinkedList<IElement> RightResult = new LinkedList<IElement>();
157
158 foreach (IElement RightChild in RightChildren)
159 RightResult.AddLast(this.Evaluate(LeftChild, RightChild, Variables));
160
161 LeftResult.AddLast(Right.Encapsulate(RightResult, this));
162 }
163
164 return Left.Encapsulate(LeftResult, this);
165 }
166 }
167 }
168 }
169
177 public virtual async Task<IElement> EvaluateAsync(IElement Left, IElement Right, Variables Variables)
178 {
179 if (Left.IsScalar)
180 {
181 if (Right.IsScalar)
182 {
183 ISet LeftSet = Left.AssociatedSet;
184 ISet RightSet = Right.AssociatedSet;
186
187 if (!LeftSet.Equals(RightSet) && (UpgradeBehaviour = this.ScalarUpgradeBehaviour) != UpgradeBehaviour.DifferentTypesOk)
188 {
189 if (!Expression.UpgradeField(ref Left, ref LeftSet, ref Right, ref RightSet))
190 {
191 if (UpgradeBehaviour == UpgradeBehaviour.SameTypeRequired)
192 throw new ScriptRuntimeException("Incompatible operands.", this);
193 }
194 }
195
196 return await this.EvaluateScalarAsync(Left, Right, Variables);
197 }
198 else
199 {
200 LinkedList<IElement> Result = new LinkedList<IElement>();
201
202 foreach (IElement RightChild in Right.ChildElements)
203 Result.AddLast(await this.EvaluateAsync(Left, RightChild, Variables));
204
205 return Right.Encapsulate(Result, this);
206 }
207 }
208 else
209 {
210 if (Right.IsScalar)
211 {
212 LinkedList<IElement> Result = new LinkedList<IElement>();
213
214 foreach (IElement LeftChild in Left.ChildElements)
215 Result.AddLast(await this.EvaluateAsync(LeftChild, Right, Variables));
216
217 return Left.Encapsulate(Result, this);
218 }
219 else
220 {
221 ICollection<IElement> LeftChildren = Left.ChildElements;
222 ICollection<IElement> RightChildren = Right.ChildElements;
223
224 if (LeftChildren.Count == RightChildren.Count)
225 {
226 LinkedList<IElement> Result = new LinkedList<IElement>();
227 IEnumerator<IElement> eLeft = LeftChildren.GetEnumerator();
228 IEnumerator<IElement> eRight = RightChildren.GetEnumerator();
229
230 try
231 {
232 while (eLeft.MoveNext() && eRight.MoveNext())
233 Result.AddLast(await this.EvaluateAsync(eLeft.Current, eRight.Current, Variables));
234 }
235 finally
236 {
237 eLeft.Dispose();
238 eRight.Dispose();
239 }
240
241 return Left.Encapsulate(Result, this);
242 }
243 else
244 {
245 LinkedList<IElement> LeftResult = new LinkedList<IElement>();
246
247 foreach (IElement LeftChild in LeftChildren)
248 {
249 LinkedList<IElement> RightResult = new LinkedList<IElement>();
250
251 foreach (IElement RightChild in RightChildren)
252 RightResult.AddLast(await this.EvaluateAsync(LeftChild, RightChild, Variables));
253
254 LeftResult.AddLast(Right.Encapsulate(RightResult, this));
255 }
256
257 return Left.Encapsulate(LeftResult, this);
258 }
259 }
260 }
261 }
262
271
279 public virtual Task<IElement> EvaluateScalarAsync(IElement Left, IElement Right, Variables Variables)
280 {
281 return Task.FromResult<IElement>(this.EvaluateScalar(Left, Right, Variables));
282 }
283
287 public virtual UpgradeBehaviour ScalarUpgradeBehaviour => UpgradeBehaviour.SameTypeRequired;
288 }
289}
Class managing a script expression.
Definition: Expression.cs:39
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:5070
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:20
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 all types of sets.
Definition: ISet.cs:10
UpgradeBehaviour
How operands are to be handled if not of the same type.