Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
ImplicitSet.cs
1using System;
3using System.Text;
4using System.Threading.Tasks;
11
13{
17 public class ImplicitSet : Set
18 {
19 private readonly ScriptNode pattern;
20 private readonly ISet superSet;
21 private readonly ScriptNode[] otherConditions;
22 private readonly In[] setConditions;
23 private readonly Variables variables = null;
24 private FiniteSet finiteSet = null;
25 private readonly bool doubleColon;
26
36 public ImplicitSet(ScriptNode Pattern, ISet SuperSet, In[] SetConditions, ScriptNode[] OtherConditions,
37 Variables Variables, bool DoubleColon)
38 {
39 this.pattern = Pattern;
40 this.superSet = SuperSet;
41 this.doubleColon = DoubleColon;
42 this.setConditions = SetConditions;
43 this.otherConditions = OtherConditions;
44
45 this.variables = new Variables();
46 Variables.CopyTo(this.variables);
47 }
48
54 public override bool Contains(IElement Element)
55 {
56 if (!(this.finiteSet is null))
57 return this.finiteSet.Contains(Element);
58 else
59 {
60 if (!(this.superSet is null) && !this.superSet.Contains(Element))
61 return false;
62
63 Dictionary<string, IElement> Variables = new Dictionary<string, IElement>();
64
65 switch (this.pattern.PatternMatch(Element, Variables))
66 {
67 case PatternMatchResult.Match:
68 this.variables.Push();
69 try
70 {
71
72 foreach (KeyValuePair<string, IElement> P in Variables)
73 this.variables[P.Key] = P.Value;
74
75 return SatisfiesConditions(this.setConditions, this.otherConditions, this.variables);
76 }
77 finally
78 {
79 this.variables.Pop();
80 }
81
82 case PatternMatchResult.NoMatch:
83 return false;
84
85 case PatternMatchResult.Unknown:
86 default:
87 throw new ScriptRuntimeException("Unable to compute pattern match.", this.pattern);
88 }
89 }
90 }
91
92 private static bool SatisfiesConditions(ScriptNode[] SetConditions, ScriptNode[] OtherConditions, Variables Variables)
93 {
94 if (!(SetConditions is null))
95 {
96 foreach (ScriptNode Condition in SetConditions)
97 {
98 if (!SatisfiesCondition(Condition, Variables))
99 return false;
100 }
101 }
102
103 if (!(OtherConditions is null))
104 {
105 foreach (ScriptNode Condition in OtherConditions)
106 {
107 if (!SatisfiesCondition(Condition, Variables))
108 return false;
109 }
110 }
111
112 return true;
113 }
114
115 private static async Task<bool> SatisfiesConditionsAsync(ScriptNode[] SetConditions, ScriptNode[] OtherConditions, Variables Variables)
116 {
117 if (!(SetConditions is null))
118 {
119 foreach (ScriptNode Condition in SetConditions)
120 {
121 if (!await SatisfiesConditionAsync(Condition, Variables))
122 return false;
123 }
124 }
125
126 if (!(OtherConditions is null))
127 {
128 foreach (ScriptNode Condition in OtherConditions)
129 {
130 if (!await SatisfiesConditionAsync(Condition, Variables))
131 return false;
132 }
133 }
134
135 return true;
136 }
137 private static bool SatisfiesCondition(ScriptNode Condition, Variables Variables)
138 {
139 IElement Result = Condition.Evaluate(Variables);
140 object Obj = Result.AssociatedObjectValue;
141
142 if (Obj is bool b)
143 return b;
144 else if (Expression.TryConvert(Obj, out b))
145 return b;
146 else
147 return false;
148 }
149
150 private static async Task<bool> SatisfiesConditionAsync(ScriptNode Condition, Variables Variables)
151 {
152 IElement Result = await Condition.EvaluateAsync(Variables);
153 object Obj = Result.AssociatedObjectValue;
154
155 if (Obj is bool b)
156 return b;
157 else if (Expression.TryConvert(Obj, out b))
158 return b;
159 else
160 return false;
161 }
165 public override ICollection<IElement> ChildElements
166 {
167 get
168 {
169 if (!(this.finiteSet is null))
170 return this.finiteSet.ChildElements;
171
172 if (!this.CalcSubset())
173 throw new ScriptException("Unable to calculate enumerable set.");
174
175 return this.finiteSet.ChildElements;
176 }
177 }
178
182 public override int? Size
183 {
184 get
185 {
186 if (!(this.finiteSet is null))
187 return this.finiteSet.Size;
188
189 if (!this.CalcSubset())
190 return null;
191
192 return this.finiteSet.Size;
193 }
194 }
195
196 private bool CalcSubset()
197 {
198 IEnumerable<IElement> Elements;
199
200 if (!(this.superSet is null) && this.superSet.Size.HasValue)
201 Elements = CalculateElements(this.pattern, this.superSet.ChildElements, this.setConditions, this.otherConditions, this.variables);
202 else
203 Elements = CalculateElements(this.pattern, null, this.setConditions, this.otherConditions, this.variables);
204
205 if (Elements is null)
206 return false;
207 else
208 {
209 this.finiteSet = new FiniteSet(Elements);
210 return true;
211 }
212 }
213
223 public static IEnumerable<IElement> CalculateElements(ScriptNode Pattern, IEnumerable<IElement> SuperSetElements,
224 In[] SetConditions, ScriptNode[] OtherConditions, Variables Variables)
225 {
226 if (!(SuperSetElements is null))
227 {
228 Dictionary<string, IElement> LocalVariables = new Dictionary<string, IElement>();
230
231 Variables.Push();
232 try
233 {
234 foreach (IElement Element in SuperSetElements)
235 {
236 LocalVariables.Clear();
237 switch (Pattern.PatternMatch(Element, LocalVariables))
238 {
239 case PatternMatchResult.Match:
240 foreach (KeyValuePair<string, IElement> P in LocalVariables)
241 Variables[P.Key] = P.Value;
242
243 try
244 {
245 if (!SatisfiesConditions(SetConditions, OtherConditions, Variables))
246 continue;
247 }
248 catch (Exception)
249 {
250 continue;
251 }
252
253 break;
254
255 case PatternMatchResult.NoMatch:
256 continue;
257
258 case PatternMatchResult.Unknown:
259 default:
260 return null;
261 }
262
263 Items.Add(Element);
264 }
265 }
266 finally
267 {
268 Variables.Pop();
269 }
270
271 return Items;
272 }
273 else if (SuperSetElements is null && !(SetConditions is null))
274 {
275 int i, c = SetConditions.Length;
276 IEnumerator<IElement>[] Enumerators = new IEnumerator<IElement>[c];
277 string[][] AffectedVariables = new string[c][];
278 bool Pushed = false;
279
280 try
281 {
282 for (i = 0; i < c; i++)
283 {
284 IEnumerable<IElement> Members = GetSetMembers(SetConditions[i].RightOperand.Evaluate(Variables));
285 if (Members is null)
286 return null;
287
288 Enumerators[i] = Members.GetEnumerator();
289 if (!Enumerators[i].MoveNext())
290 return null;
291 }
292
293 Variables.Push();
294 Pushed = true;
295
297 Dictionary<string, IElement> LocalVariables = new Dictionary<string, IElement>();
298 IEnumerator<IElement> e;
299 bool Collision = false;
300 bool Match;
301 int j = c - 1;
302
303 do
304 {
305 if (Collision)
306 LocalVariables.Clear();
307 else
308 {
309 for (i = 0; i <= j; i++)
310 {
311 if (!(AffectedVariables[i] is null))
312 {
313 foreach (string s in AffectedVariables[i])
314 LocalVariables.Remove(s);
315 }
316 }
317 }
318
319 Match = true;
320
321 for (i = 0; Match && (i <= j || (Collision && i < c)); i++)
322 {
323 e = Enumerators[i];
324
325 if (AffectedVariables[i] is null)
326 {
327 Dictionary<string, IElement> v = new Dictionary<string, IElement>();
328
329 switch (SetConditions[i].LeftOperand.PatternMatch(e.Current, v))
330 {
331 case PatternMatchResult.Match:
332 string[] v2 = new string[v.Count];
333 v.Keys.CopyTo(v2, 0);
334 AffectedVariables[i] = v2;
335
336 foreach (KeyValuePair<string, IElement> P in v)
337 {
338 if (LocalVariables.TryGetValue(P.Key, out IElement E))
339 {
340 Collision = true;
341
342 if (!e.Current.Equals(E))
343 Match = false;
344 }
345 else
346 LocalVariables[P.Key] = P.Value;
347 }
348 break;
349
350 case PatternMatchResult.NoMatch:
351 Match = false;
352 break;
353
354 case PatternMatchResult.Unknown:
355 default:
356 return null;
357 }
358 }
359 else
360 {
361 switch (SetConditions[i].LeftOperand.PatternMatch(e.Current, LocalVariables))
362 {
363 case PatternMatchResult.Match:
364 break;
365
366 case PatternMatchResult.NoMatch:
367 Match = false;
368 break;
369
370 case PatternMatchResult.Unknown:
371 default:
372 return null;
373 }
374 }
375 }
376
377 if (Match)
378 {
379 foreach (KeyValuePair<string, IElement> P in LocalVariables)
380 Variables[P.Key] = P.Value;
381
382 if (SatisfiesConditions(null, OtherConditions, Variables))
383 Items.Add(Pattern.Evaluate(Variables));
384 }
385
386 for (j = 0; j < c; j++)
387 {
388 e = Enumerators[j];
389 if (e.MoveNext())
390 break;
391
392 e.Reset();
393 e.MoveNext();
394 }
395 }
396 while (j < c);
397
398 return Items;
399 }
400 finally
401 {
402 if (Pushed)
403 Variables.Pop();
404
405 for (i = 0; i < c; i++)
406 Enumerators[i]?.Dispose();
407 }
408
409 }
410 else
411 return null;
412 }
413
423 public static async Task<IEnumerable<IElement>> CalculateElementsAsync(ScriptNode Pattern, IEnumerable<IElement> SuperSetElements,
424 In[] SetConditions, ScriptNode[] OtherConditions, Variables Variables)
425 {
426 if (!(SuperSetElements is null))
427 {
428 Dictionary<string, IElement> LocalVariables = new Dictionary<string, IElement>();
430
431 Variables.Push();
432 try
433 {
434 foreach (IElement Element in SuperSetElements)
435 {
436 LocalVariables.Clear();
437 switch (Pattern.PatternMatch(Element, LocalVariables))
438 {
439 case PatternMatchResult.Match:
440 foreach (KeyValuePair<string, IElement> P in LocalVariables)
441 Variables[P.Key] = P.Value;
442
443 try
444 {
445 if (!await SatisfiesConditionsAsync(SetConditions, OtherConditions, Variables))
446 continue;
447 }
448 catch (Exception)
449 {
450 continue;
451 }
452
453 break;
454
455 case PatternMatchResult.NoMatch:
456 continue;
457
458 case PatternMatchResult.Unknown:
459 default:
460 return null;
461 }
462
463 Items.Add(Element);
464 }
465 }
466 finally
467 {
468 Variables.Pop();
469 }
470
471 return Items;
472 }
473 else if (SuperSetElements is null && !(SetConditions is null))
474 {
475 int i, c = SetConditions.Length;
476 IEnumerator<IElement>[] Enumerators = new IEnumerator<IElement>[c];
477 string[][] AffectedVariables = new string[c][];
478 bool Pushed = false;
479
480 try
481 {
482 for (i = 0; i < c; i++)
483 {
484 IEnumerable<IElement> Members = GetSetMembers(await SetConditions[i].RightOperand.EvaluateAsync(Variables));
485 if (Members is null)
486 return null;
487
488 Enumerators[i] = Members.GetEnumerator();
489 if (!Enumerators[i].MoveNext())
490 return null;
491 }
492
493 Variables.Push();
494 Pushed = true;
495
497 Dictionary<string, IElement> LocalVariables = new Dictionary<string, IElement>();
498 IEnumerator<IElement> e;
499 bool Collision = false;
500 bool Match;
501 int j = c - 1;
502
503 do
504 {
505 if (Collision)
506 LocalVariables.Clear();
507 else
508 {
509 for (i = 0; i <= j; i++)
510 {
511 if (!(AffectedVariables[i] is null))
512 {
513 foreach (string s in AffectedVariables[i])
514 LocalVariables.Remove(s);
515 }
516 }
517 }
518
519 Match = true;
520
521 for (i = 0; Match && (i <= j || (Collision && i < c)); i++)
522 {
523 e = Enumerators[i];
524
525 if (AffectedVariables[i] is null)
526 {
527 Dictionary<string, IElement> v = new Dictionary<string, IElement>();
528
529 switch (SetConditions[i].LeftOperand.PatternMatch(e.Current, v))
530 {
531 case PatternMatchResult.Match:
532 string[] v2 = new string[v.Count];
533 v.Keys.CopyTo(v2, 0);
534 AffectedVariables[i] = v2;
535
536 foreach (KeyValuePair<string, IElement> P in v)
537 {
538 if (LocalVariables.TryGetValue(P.Key, out IElement E))
539 {
540 Collision = true;
541
542 if (!e.Current.Equals(E))
543 Match = false;
544 }
545 else
546 LocalVariables[P.Key] = P.Value;
547 }
548 break;
549
550 case PatternMatchResult.NoMatch:
551 Match = false;
552 break;
553
554 case PatternMatchResult.Unknown:
555 default:
556 return null;
557 }
558 }
559 else
560 {
561 switch (SetConditions[i].LeftOperand.PatternMatch(e.Current, LocalVariables))
562 {
563 case PatternMatchResult.Match:
564 break;
565
566 case PatternMatchResult.NoMatch:
567 Match = false;
568 break;
569
570 case PatternMatchResult.Unknown:
571 default:
572 return null;
573 }
574 }
575 }
576
577 if (Match)
578 {
579 foreach (KeyValuePair<string, IElement> P in LocalVariables)
580 Variables[P.Key] = P.Value;
581
582 if (await SatisfiesConditionsAsync(null, OtherConditions, Variables))
583 Items.Add(await Pattern.EvaluateAsync(Variables));
584 }
585
586 for (j = 0; j < c; j++)
587 {
588 e = Enumerators[j];
589 if (e.MoveNext())
590 break;
591
592 e.Reset();
593 e.MoveNext();
594 }
595 }
596 while (j < c);
597
598 return Items;
599 }
600 finally
601 {
602 if (Pushed)
603 Variables.Pop();
604
605 for (i = 0; i < c; i++)
606 Enumerators[i]?.Dispose();
607 }
608
609 }
610 else
611 return null;
612 }
613
619 public static IEnumerable<IElement> GetSetMembers(IElement E)
620 {
621 if (E is ISet Set)
622 {
623 if (!Set.Size.HasValue)
624 return null;
625 else
626 return Set.ChildElements;
627 }
628
629 if (E is IVector Vector)
630 return Vector.VectorElements;
631
632 object Obj = E.AssociatedObjectValue;
633 if (Obj is ISet Set2)
634 {
635 if (!Set2.Size.HasValue)
636 return null;
637 else
638 return Set2.ChildElements;
639 }
640
641 if (Obj is IEnumerable<IElement> Elements)
642 return Elements;
643
644 if (Obj is IEnumerable<object> Objects)
645 {
647
648 foreach (object x in Objects)
649 List.Add(Expression.Encapsulate(x));
650
651 return List;
652 }
653
654 return null;
655 }
656
658 public override bool Equals(object obj)
659 {
660 if (!(obj is ImplicitSet S))
661 return false;
662
663 if (this.superSet is null ^ S.superSet is null)
664 return false;
665
666 if (!(this.superSet is null) && !this.superSet.Equals(S.superSet))
667 return false;
668
669 return
670 this.pattern.Equals(S.pattern) &&
671 this.doubleColon.Equals(S.doubleColon) &&
672 ScriptNode.AreEqual(this.otherConditions, S.otherConditions) &&
673 ScriptNode.AreEqual(this.setConditions, S.setConditions);
674 }
675
677 public override int GetHashCode()
678 {
679 int Result = this.pattern.GetHashCode();
680
681 if (!(this.superSet is null))
682 Result ^= Result << 5 ^ this.superSet.GetHashCode();
683
684 Result ^= Result << 5 ^ ScriptNode.GetHashCode(this.otherConditions);
685 Result ^= Result << 5 ^ ScriptNode.GetHashCode(this.setConditions);
686 Result ^= Result << 5 ^ this.doubleColon.GetHashCode();
687
688 return Result;
689 }
690
692 public override string ToString()
693 {
694 if (!(this.finiteSet is null))
695 return this.finiteSet.ToString();
696
697 StringBuilder sb = new StringBuilder();
698
699 sb.Append('{');
700 sb.Append(this.pattern.SubExpression);
701
702 if (!(this.superSet is null))
703 {
704 sb.Append('∈');
705 sb.Append(this.superSet.ToString());
706 }
707
708 sb.Append(':');
709
710 if (this.doubleColon)
711 sb.Append(':');
712
713 bool First = true;
714
715 if (!(this.setConditions is null))
716 {
717 foreach (ScriptNode Condition in this.setConditions)
718 {
719 if (First)
720 First = false;
721 else
722 sb.Append(',');
723
724 sb.Append(Condition.SubExpression);
725 }
726 }
727
728 if (!(this.otherConditions is null))
729 {
730 foreach (ScriptNode Condition in this.otherConditions)
731 {
732 if (First)
733 First = false;
734 else
735 sb.Append(',');
736
737 sb.Append(Condition.SubExpression);
738 }
739 }
740
741 sb.Append('}');
742
743 return sb.ToString();
744 }
745 }
746}
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
Base class for all types of elements.
Definition: Element.cs:14
Base class for all types of sets.
Definition: Set.cs:14
virtual ? int Size
Size of set, if finite and known, otherwise null is returned.
Definition: Set.cs:100
override ICollection< IElement > ChildElements
An enumeration of child elements. If the element is a scalar, this property will return null.
Definition: Set.cs:84
Base class for script exceptions.
Class managing a script expression.
Definition: Expression.cs:41
static bool TryConvert(object Value, Type DesiredType, bool AcceptInformationLoss, out object Result)
Tries to convert an object Value to an object of type DesiredType .
Definition: Expression.cs:5530
static IElement Encapsulate(object Value)
Encapsulates an object.
Definition: Expression.cs:5241
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
string SubExpression
Sub-expression defining the node.
Definition: ScriptNode.cs:183
virtual PatternMatchResult PatternMatch(IElement CheckAgainst, Dictionary< string, IElement > AlreadyFound)
Performs a pattern match operation.
Definition: ScriptNode.cs:169
static bool AreEqual(ScriptNode S1, ScriptNode S2)
Compares if two script nodes are equal.
Definition: ScriptNode.cs:275
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
Represents a finite set.
Definition: FiniteSet.cs:13
override bool Contains(IElement Element)
Checks if the set contains an element.
Definition: FiniteSet.cs:47
override? int Size
Size of set, if finite and known, otherwise null is returned.
Definition: FiniteSet.cs:138
override ICollection< IElement > ChildElements
An enumeration of child elements. If the element is a scalar, this property will return null.
Definition: FiniteSet.cs:91
Represents an implicitly defined set
Definition: ImplicitSet.cs:18
static async Task< IEnumerable< IElement > > CalculateElementsAsync(ScriptNode Pattern, IEnumerable< IElement > SuperSetElements, In[] SetConditions, ScriptNode[] OtherConditions, Variables Variables)
Calculates elements specified using implicit notation.
Definition: ImplicitSet.cs:423
override? int Size
If the element represents a scalar value.
Definition: ImplicitSet.cs:183
ImplicitSet(ScriptNode Pattern, ISet SuperSet, In[] SetConditions, ScriptNode[] OtherConditions, Variables Variables, bool DoubleColon)
Represents an implicitly defined set
Definition: ImplicitSet.cs:36
static IEnumerable< IElement > GetSetMembers(IElement E)
Gets the elements of a (supposed) set.
Definition: ImplicitSet.cs:619
static IEnumerable< IElement > CalculateElements(ScriptNode Pattern, IEnumerable< IElement > SuperSetElements, In[] SetConditions, ScriptNode[] OtherConditions, Variables Variables)
Calculates elements specified using implicit notation.
Definition: ImplicitSet.cs:223
override ICollection< IElement > ChildElements
An enumeration of child elements. If the element is a scalar, this property will return null.
Definition: ImplicitSet.cs:166
override bool Equals(object obj)
Compares the element to another. If elements are equal.
Definition: ImplicitSet.cs:658
override int GetHashCode()
Calculates a hash code of the element. Hash code.
Definition: ImplicitSet.cs:677
override bool Contains(IElement Element)
Checks if the set contains an element.
Definition: ImplicitSet.cs:54
override IElement Evaluate(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
Definition: In.cs:35
override async Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
Definition: In.cs:48
Collection of variables.
Definition: Variables.cs:25
virtual void Push()
Pushes the current set of variables to the stack. This state is restored by calling Pop....
Definition: Variables.cs:184
virtual void Pop()
Pops a previously stored set of variables from the stack. Variables are stored on the stack by callin...
Definition: Variables.cs:206
void CopyTo(Variables Variables)
Copies available variables to another variable collection.
Definition: Variables.cs:334
Basic interface for all types of elements.
Definition: IElement.cs:21
object AssociatedObjectValue
Associated object value.
Definition: IElement.cs:34
Basic interface for vectors.
Definition: IVector.cs:9
Basic interface for all types of sets.
Definition: ISet.cs:10
PatternMatchResult
Status result of a pattern matching operation.
Definition: ScriptNode.cs:17