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