1 // =================================
  2 // Copyright (c) 2024 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Collections;
  8 using System.Xml;
  9 
 10 namespace System.XPath
 11 {
 12     public class StringValueComputerVisitor : System.Xml.Visitor
 13     {
 14         public StringValueComputerVisitor() : stringValue()
 15         {
 16         }
 17         public override void Visit(System.Xml.Text& text)
 18         {
 19             stringValue.Append(text.Data());
 20         }
 21         public string GetStringValue()
 22         {
 23             return Rvalue(stringValue);
 24         }
 25         private string stringValue;
 26     }
 27 
 28     public string GetStringValue(System.Xml.ParentNode* node)
 29     {
 30         StringValueComputerVisitor visitor;
 31         node->Accept(visitor);
 32         return visitor.GetStringValue();
 33     }
 34 
 35     public inline string StringValue(System.Xml.AttributeNode* attributeNode)
 36     {
 37         return attributeNode->Value();
 38     }
 39 
 40     public inline string StringValue(System.Xml.Document* documentNode)
 41     {
 42         return GetStringValue(documentNode);
 43     }
 44 
 45     public inline string StringValue(System.Xml.Element* elementNode)
 46     {
 47         return GetStringValue(elementNode);
 48     }
 49 
 50     public inline string StringValue(System.Xml.ProcessingInstruction* piNode)
 51     {
 52         return piNode->Data();
 53     }
 54 
 55     public inline string StringValue(System.Xml.Text* textNode)
 56     {
 57         return textNode->Data();
 58     }
 59 
 60     public inline string StringValue(System.Xml.CDataSection* cdataSectionNode)
 61     {
 62         return cdataSectionNode->Data();
 63     }
 64 
 65     public inline string StringValue(System.Xml.Comment* commentNode)
 66     {
 67         return commentNode->Data();
 68     }
 69 
 70     public string StringValue(System.Xml.Node* node)
 71     {
 72         switch (node->Kind())
 73         {
 74             case System.Xml.NodeKind.attributeNode:
 75             {
 76                 System.Xml.AttributeNode* attributeNode = cast<System.Xml.AttributeNode*>(node);
 77                 return StringValue(attributeNode);
 78             }
 79             case System.Xml.NodeKind.documentNode:
 80             {
 81                 System.Xml.Document* documentNode = cast<System.Xml.Document*>(node);
 82                 return StringValue(documentNode);
 83             }
 84             case System.Xml.NodeKind.elementNode:
 85             {
 86                 System.Xml.Element* elementNode = cast<System.Xml.Element*>(node);
 87                 return StringValue(elementNode);
 88             }
 89             case System.Xml.NodeKind.processingInstructionNode:
 90             {
 91                 System.Xml.ProcessingInstruction* processingInstructionNode = cast<System.Xml.ProcessingInstruction*>(node);
 92                 return StringValue(processingInstructionNode);
 93             }
 94             case System.Xml.NodeKind.textNode:
 95             {
 96                 System.Xml.Text* textNode = cast<System.Xml.Text*>(node);
 97                 return StringValue(textNode);
 98             }
 99             case System.Xml.NodeKind.cdataSectionNode:
100             {
101                 System.Xml.CDataSection* cdataSectionNode = cast<System.Xml.CDataSection*>(node);
102                 return StringValue(cdataSectionNode);
103             }
104             case System.Xml.NodeKind.commentNode:
105             {
106                 System.Xml.Comment* commentNode = cast<System.Xml.Comment*>(node);
107                 return StringValue(commentNode);
108             }
109         }
110         return string();
111     }
112 
113     [nodiscard]
114     public Result<UniquePtr<Object>> ToNumber(Object* objectContext& context)
115     {
116         auto numberFunctionResult = GetFunction(FunctionKind.number);
117         if (numberFunctionResult.Error())
118         {
119             return Result<UniquePtr<Object>>(ErrorId(numberFunctionResult.GetErrorId()));
120         }
121         Function* numberFunction = numberFunctionResult.Value();
122         List<Object*> args(1object);
123         return numberFunction->Evaluate(contextargs);
124     }
125 
126     [nodiscard]
127     public Result<UniquePtr<Object>> ToNumber(System.Xml.Node* nodeContext& context)
128     {
129         UniquePtr<Object> stringValue(new Str(StringValue(node)));
130         return ToNumber(stringValue.Get()context);
131     }
132 
133     [nodiscard]
134     public Result<Number*> NumberCast(Object* object)
135     {
136         if (object->IsNumber())
137         {
138             return Result<Number*>(cast<Number*>(object));
139         }
140         else
141         {
142             int errorId = AllocateError("number object expected");
143             return Result<Number*>(ErrorId(errorId));
144         }
145     }
146 
147     [nodiscard]
148     public Result<UniquePtr<Object>> ToBoolean(Object* objectContext& context)
149     {
150         auto booleanFunctionResult = GetFunction(FunctionKind.boolean);
151         if (booleanFunctionResult.Error())
152         {
153             return Result<UniquePtr<Object>>(ErrorId(booleanFunctionResult.GetErrorId()));
154         }
155         Function* booleanFunction = booleanFunctionResult.Value();
156         List<Object*> args(1object);
157         return booleanFunction->Evaluate(contextargs);
158     }
159 
160     [nodiscard]
161     public Result<Boolean*> BooleanCast(Object* object)
162     {
163         if (object->IsBoolean())
164         {
165             return Result<Boolean*>(cast<Boolean*>(object));
166         }
167         else
168         {
169             int errorId = AllocateError("Boolean object expected");
170             return Result<Boolean*>(ErrorId(errorId));
171         }
172     }
173 
174     [nodiscard]
175     public Result<NodeSet*> NodeSetCast(Object* object)
176     {
177         if (object->IsNodeSet())
178         {
179             return Result<NodeSet*>(cast<NodeSet*>(object));
180         }
181         else
182         {
183             int errorId = AllocateError("node-set object expected");
184             return Result<NodeSet*>(ErrorId(errorId));
185         }
186     }
187 
188     [nodiscard]
189     public Result<UniquePtr<Object>> EvaluateUnaryMinusExpr(Expr* operandContext& context)
190     {
191         auto operandResult = operand->Evaluate(context);
192         if (operandResult.Error())
193         {
194             return operandResult;
195         }
196         Result<UniquePtr<Object>> numberResult = ToNumber(operandResult.Value().Get()context);
197         if (numberResult.Error())
198         {
199             return numberResult;
200         }
201         auto numberCastResult = NumberCast(numberResult.Value().Get());
202         if (numberCastResult.Error())
203         {
204             return Result<UniquePtr<Object>>(ErrorId(numberCastResult.GetErrorId()));
205         }
206         Number* number = numberCastResult.Value();
207         return Result<UniquePtr<Object>>(UniquePtr<Object>(new Number(-number->Value())));
208     }
209 
210     [nodiscard]
211     public Result<UniquePtr<Object>> EvaluateParenExpr(Expr* operandContext& context)
212     {
213         return operand->Evaluate(context);
214     }
215 
216     [nodiscard]
217     public Result<UniquePtr<Object>> EvaluateOrExpr(Expr* leftExpr* rightContext& context)
218     {
219         auto booleanFunctionResult = GetFunction(FunctionKind.boolean);
220         if (booleanFunctionResult.Error())
221         {
222             return Result<UniquePtr<Object>>(ErrorId(booleanFunctionResult.GetErrorId()));
223         }
224         Function* booleanFunction = booleanFunctionResult.Value();
225         Result<UniquePtr<Object>> leftResult = left->Evaluate(context);
226         if (leftResult.Error())
227         {
228             return Result<UniquePtr<Object>>(ErrorId(leftResult.GetErrorId()));
229         }
230         List<Object*> leftArgs(1leftResult.Value().Get());
231         Result<UniquePtr<Object>> leftBooleanResult = booleanFunction->Evaluate(contextleftArgs);
232         if (leftBooleanResult.Error())
233         {
234             return Result<UniquePtr<Object>>(ErrorId(leftBooleanResult.GetErrorId()));
235         }
236         auto booleanCastResult = BooleanCast(leftBooleanResult.Value().Get());
237         if (booleanCastResult.Error())
238         {
239             return Result<UniquePtr<Object>>(ErrorId(booleanCastResult.GetErrorId()));
240         }
241         Boolean* leftAsBoolean = booleanCastResult.Value();
242         if (leftAsBoolean->Value())
243         {
244             return leftBooleanResult;
245         }
246         Result<UniquePtr<Object>> rightResult = right->Evaluate(context);
247         if (rightResult.Error())
248         {
249             return Result<UniquePtr<Object>>(ErrorId(rightResult.GetErrorId()));
250         }
251         List<Object*> rightArgs(1rightResult.Value().Get());
252         return booleanFunction->Evaluate(contextrightArgs);
253     }
254 
255     [nodiscard]
256     public Result<UniquePtr<Object>> EvaluateAndExpr(Expr* leftExpr* rightContext& context)
257     {
258         auto booleanFunctionResult = GetFunction(FunctionKind.boolean);
259         if (booleanFunctionResult.Error())
260         {
261             return Result<UniquePtr<Object>>(ErrorId(booleanFunctionResult.GetErrorId()));
262         }
263         Function* booleanFunction = booleanFunctionResult.Value();
264         Result<UniquePtr<Object>> leftResult = left->Evaluate(context);
265         if (leftResult.Error())
266         {
267             return Result<UniquePtr<Object>>(ErrorId(leftResult.GetErrorId()));
268         }
269         List<Object*> leftArgs(1leftResult.Value().Get());
270         Result<UniquePtr<Object>> leftBooleanResult = booleanFunction->Evaluate(contextleftArgs);
271         if (leftBooleanResult.Error())
272         {
273             return Result<UniquePtr<Object>>(ErrorId(leftBooleanResult.GetErrorId()));
274         }
275         auto booleanCastResult = BooleanCast(leftBooleanResult.Value().Get());
276         if (booleanCastResult.Error())
277         {
278             return Result<UniquePtr<Object>>(ErrorId(booleanCastResult.GetErrorId()));
279         }
280         Boolean* leftAsBoolean = booleanCastResult.Value();
281         if (!leftAsBoolean->Value())
282         {
283             return leftBooleanResult;
284         }
285         Result<UniquePtr<Object>> rightResult = right->Evaluate(context);
286         if (rightResult.Error())
287         {
288             return Result<UniquePtr<Object>>(ErrorId(rightResult.GetErrorId()));
289         }
290         List<Object*> rightArgs(1rightResult.Value().Get());
291         return booleanFunction->Evaluate(contextrightArgs);
292     }
293 
294     bool CompareStrings(const string& leftStrconst string& rightStrOperator op)
295     {
296         switch (op)
297         {
298             case Operator.equal:
299             {
300                 return leftStr == rightStr;
301             }
302             case Operator.notEqual:
303             {
304                 return leftStr != rightStr;
305             }
306             case Operator.less:
307             {
308                 return leftStr < rightStr;
309             }
310             case Operator.greater:
311             {
312                 return leftStr > rightStr;
313             }
314             case Operator.lessOrEqual:
315             {
316                 return leftStr <= rightStr;
317             }
318             case Operator.greaterOrEqual:
319             {
320                 return leftStr >= rightStr;
321             }
322         }
323         return false;
324     }
325 
326     public bool CompareNumbers(double leftdouble rightOperator op)
327     {
328         switch (op)
329         {
330             case Operator.equal:
331             {
332                 return left == right;
333             }
334             case Operator.notEqual:
335             {
336                 return left != right;
337             }
338             case Operator.less:
339             {
340                 return left < right;
341             }
342             case Operator.greater:
343             {
344                 return left > right;
345             }
346             case Operator.lessOrEqual:
347             {
348                 return left <= right;
349             }
350             case Operator.greaterOrEqual:
351             {
352                 return left >= right;
353             }
354         }
355         return false;
356     }
357 
358     public bool CompareBooleans(bool leftbool rightOperator op)
359     {
360         switch (op)
361         {
362             case Operator.equal:
363             {
364                 return left == right;
365             }
366             case Operator.notEqual:
367             {
368                 return left != right;
369             }
370             case Operator.less:
371             {
372                 return cast<int>(left) < cast<int>(right);
373             }
374             case Operator.greater:
375             {
376                 return cast<int>(left) > cast<int>(right);
377             }
378             case Operator.lessOrEqual:
379             {
380                 return cast<int>(left) <= cast<int>(right);
381             }
382             case Operator.greaterOrEqual:
383             {
384                 return cast<int>(left) >= cast<int>(right);
385             }
386         }
387         return false;
388     }
389 
390     [nodiscard]
391     public Result<UniquePtr<Object>> Compare(NodeSet* leftNodeSet* rightOperator op)
392     {
393         int n = left->Count();
394         for (int i = 0; i < n; ++i;)
395         {
396             System.Xml.Node* leftNode = left->GetNode(i);
397             string leftStringValue = StringValue(leftNode);
398             int m = right->Count();
399             for (int j = 0; j < m; ++j;)
400             {
401                 System.Xml.Node* rightNode = right->GetNode(j);
402                 string rightStringValue = StringValue(rightNode);
403                 if (CompareStrings(leftStringValuerightStringValueop))
404                 {
405                     return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(true)));
406                 }
407             }
408         }
409         return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(false)));
410     }
411 
412     [nodiscard]
413     public Result<UniquePtr<Object>> Compare(NodeSet* leftBoolean* rightOperator opContext& context)
414     {
415         auto leftAsBoolean = ToBoolean(leftcontext);
416         if (leftAsBoolean.Error())
417         {
418             return Result<UniquePtr<Object>>(ErrorId(leftAsBoolean.GetErrorId()));
419         }
420         auto booleanCastResult = BooleanCast(leftAsBoolean.Value().Get());
421         if (booleanCastResult.Error())
422         {
423             return Result<UniquePtr<Object>>(ErrorId(booleanCastResult.GetErrorId()));
424         }
425         Boolean* leftBoolean = booleanCastResult.Value();
426         return Compare(leftBooleanrightop);
427     }
428 
429     [nodiscard]
430     public Result<UniquePtr<Object>> Compare(Boolean* leftNodeSet* rightOperator opContext& context)
431     {
432         auto rightAsBoolean = ToBoolean(rightcontext);
433         if (rightAsBoolean.Error())
434         {
435             return Result<UniquePtr<Object>>(ErrorId(rightAsBoolean.GetErrorId()));
436         }
437         auto booleanCastResult = BooleanCast(rightAsBoolean.Value().Get());
438         if (booleanCastResult.Error())
439         {
440             return Result<UniquePtr<Object>>(ErrorId(booleanCastResult.GetErrorId()));
441         }
442         Boolean* rightBoolean = booleanCastResult.Value();
443         return Compare(leftrightBooleanop);
444     }
445 
446     [nodiscard]
447     public Result<UniquePtr<Object>> Compare(NodeSet* leftNumber* rightOperator opContext& context)
448     {
449         int n = left->Count();
450         for (int i = 0; i < n; ++i;)
451         {
452             System.Xml.Node* leftNode = left->GetNode(i);
453             auto leftAsNumberResult = ToNumber(leftNodecontext);
454             if (leftAsNumberResult.Error())
455             {
456                 return leftAsNumberResult;
457             }
458             auto numberCastResult = NumberCast(leftAsNumberResult.Value().Get());
459             if (numberCastResult.Error())
460             {
461                 return Result<UniquePtr<Object>>(ErrorId(numberCastResult.GetErrorId()));
462             }
463             Number* leftNumber = numberCastResult.Value();
464             if (CompareNumbers(leftNumber->Value()right->Value()op))
465             {
466                 return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(true)));
467             }
468         }
469         return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(false)));
470     }
471 
472     [nodiscard]
473     public Result<UniquePtr<Object>> Compare(NodeSet* leftStr* rightOperator opContext& context)
474     {
475         int n = left->Count();
476         for (int i = 0; i < n; ++i;)
477         {
478             System.Xml.Node* leftNode = left->GetNode(i);
479             string leftString = StringValue(leftNode);
480             if (CompareStrings(leftStringright->Value()op))
481             {
482                 return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(true)));
483             }
484         }
485         return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(false)));
486     }
487 
488     [nodiscard]
489     public Result<UniquePtr<Object>> Compare(Str* leftNodeSet* rightOperator opContext& context)
490     {
491         int n = right->Count();
492         for (int i = 0; i < n; ++i;)
493         {
494             System.Xml.Node* rightNode = right->GetNode(i);
495             string rightString = StringValue(rightNode);
496             if (CompareStrings(left->Value()rightStringop))
497             {
498                 return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(true)));
499             }
500         }
501         return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(false)));
502     }
503 
504     [nodiscard]
505     public Result<UniquePtr<Object>> Compare(Number* leftNodeSet* rightOperator opContext& context)
506     {
507         int n = right->Count();
508         for (int i = 0; i < n; ++i;)
509         {
510             System.Xml.Node* rightNode = right->GetNode(i);
511             auto rightAsNumberResult = ToNumber(rightNodecontext);
512             if (rightAsNumberResult.Error())
513             {
514                 return rightAsNumberResult;
515             }
516             auto numberCastResult = NumberCast(rightAsNumberResult.Value().Get());
517             if (numberCastResult.Error())
518             {
519                 return Result<UniquePtr<Object>>(ErrorId(numberCastResult.GetErrorId()));
520             }
521             Number* rightNumber = numberCastResult.Value();
522             if (CompareNumbers(left->Value()rightNumber->Value()op))
523             {
524                 return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(true)));
525             }
526         }
527         return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(false)));
528     }
529 
530     [nodiscard]
531     public Result<UniquePtr<Object>> Compare(Boolean* leftBoolean* rightOperator op)
532     {
533         return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(CompareBooleans(left->Value()right->Value()op))));
534     }
535 
536     [nodiscard]
537     public Result<UniquePtr<Object>> Compare(Boolean* leftNumber* rightOperator opContext& context)
538     {
539         auto rightAsBoolean = ToBoolean(rightcontext);
540         if (rightAsBoolean.Error())
541         {
542             return Result<UniquePtr<Object>>(ErrorId(rightAsBoolean.GetErrorId()));
543         }
544         auto booleanCastResult = BooleanCast(rightAsBoolean.Value().Get());
545         if (booleanCastResult.Error())
546         {
547             return Result<UniquePtr<Object>>(ErrorId(booleanCastResult.GetErrorId()));
548         }
549         Boolean* rightBoolean = booleanCastResult.Value();
550         return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(CompareBooleans(left->Value()rightBoolean->Value()op))));
551     }
552 
553     [nodiscard]
554     public Result<UniquePtr<Object>> Compare(Number* leftBoolean* rightOperator opContext& context)
555     {
556         auto leftAsBoolean = ToBoolean(leftcontext);
557         if (leftAsBoolean.Error())
558         {
559             return Result<UniquePtr<Object>>(ErrorId(leftAsBoolean.GetErrorId()));
560         }
561         auto booleanCastResult = BooleanCast(leftAsBoolean.Value().Get());
562         if (booleanCastResult.Error())
563         {
564             return Result<UniquePtr<Object>>(ErrorId(booleanCastResult.GetErrorId()));
565         }
566         Boolean* leftBoolean = booleanCastResult.Value();
567         return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(CompareBooleans(leftBoolean->Value()right->Value()op))));
568     }
569 
570     [nodiscard]
571     public Result<UniquePtr<Object>> Compare(Boolean* leftStr* rightOperator opContext& context)
572     {
573         auto rightAsBoolean = ToBoolean(rightcontext);
574         if (rightAsBoolean.Error())
575         {
576             return Result<UniquePtr<Object>>(ErrorId(rightAsBoolean.GetErrorId()));
577         }
578         auto booleanCastResult = BooleanCast(rightAsBoolean.Value().Get());
579         if (booleanCastResult.Error())
580         {
581             return Result<UniquePtr<Object>>(ErrorId(booleanCastResult.GetErrorId()));
582         }
583         Boolean* rightBoolean = booleanCastResult.Value();
584         return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(CompareBooleans(left->Value()rightBoolean->Value()op))));
585     }
586 
587     [nodiscard]
588     public Result<UniquePtr<Object>> Compare(Str* leftBoolean* rightOperator opContext& context)
589     {
590         auto leftAsBoolean = ToBoolean(leftcontext);
591         if (leftAsBoolean.Error())
592         {
593             return Result<UniquePtr<Object>>(ErrorId(leftAsBoolean.GetErrorId()));
594         }
595         auto booleanCastResult = BooleanCast(leftAsBoolean.Value().Get());
596         if (booleanCastResult.Error())
597         {
598             return Result<UniquePtr<Object>>(ErrorId(booleanCastResult.GetErrorId()));
599         }
600         Boolean* leftBoolean = booleanCastResult.Value();
601         return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(CompareBooleans(leftBoolean->Value()right->Value()op))));
602     }
603 
604     [nodiscard]
605     public Result<UniquePtr<Object>> Compare(Number* leftNumber* rightOperator op)
606     {
607         return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(CompareNumbers(left->Value()right->Value()op))));
608     }
609 
610     [nodiscard]
611     public Result<UniquePtr<Object>> Compare(Number* leftStr* rightOperator opContext& context)
612     {
613         auto rightAsNumber = ToNumber(rightcontext);
614         if (rightAsNumber.Error())
615         {
616             return Result<UniquePtr<Object>>(ErrorId(rightAsNumber.GetErrorId()));
617         }
618         auto numberCastResult = NumberCast(rightAsNumber.Value().Get());
619         if (numberCastResult.Error())
620         {
621             return Result<UniquePtr<Object>>(ErrorId(numberCastResult.GetErrorId()));
622         }
623         Number* rightNumber = numberCastResult.Value();
624         return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(CompareNumbers(left->Value()rightNumber->Value()op))));
625     }
626 
627     [nodiscard]
628     public Result<UniquePtr<Object>> Compare(Str* leftNumber* rightOperator opContext& context)
629     {
630         auto leftAsNumber = ToNumber(leftcontext);
631         if (leftAsNumber.Error())
632         {
633             return Result<UniquePtr<Object>>(ErrorId(leftAsNumber.GetErrorId()));
634         }
635         auto numberCastResult = NumberCast(leftAsNumber.Value().Get());
636         if (numberCastResult.Error())
637         {
638             return Result<UniquePtr<Object>>(ErrorId(numberCastResult.GetErrorId()));
639         }
640         Number* leftNumber = numberCastResult.Value();
641         return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(CompareNumbers(leftNumber->Value()right->Value()op))));
642     }
643 
644     [nodiscard]
645     public Result<UniquePtr<Object>> Compare(Str* leftStr* rightOperator op)
646     {
647         return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(CompareStrings(left->Value()right->Value()op))));
648     }
649 
650     [nodiscard]
651     public Result<UniquePtr<Object>> Compare(Expr* leftExpr* rightOperator opContext& context)
652     {
653         Result<UniquePtr<Object>> leftOperand = left->Evaluate(context);
654         if (leftOperand.Error())
655         {
656             return leftOperand;
657         }
658         Result<UniquePtr<Object>> rightOperand = right->Evaluate(context);
659         if (rightOperand.Error())
660         {
661             return rightOperand;
662         }
663         Object* leftObject = leftOperand.Value().Get();
664         Object* rightObject = rightOperand.Value().Get();
665         switch (leftObject->Kind())
666         {
667             case ObjectKind.nodeSet:
668             {
669                 NodeSet* leftNodeSet = cast<NodeSet*>(leftObject);
670                 switch (rightObject->Kind())
671                 {
672                     case ObjectKind.nodeSet:
673                     {
674                         NodeSet* rightNodeSet = cast<NodeSet*>(rightObject);
675                         return Compare(leftNodeSetrightNodeSetop);
676                     }
677                     case ObjectKind.boolean:
678                     {
679                         Boolean* rightBoolean = cast<Boolean*>(rightObject);
680                         return Compare(leftNodeSetrightBooleanopcontext);
681                     }
682                     case ObjectKind.number:
683                     {
684                         Number* rightNumber = cast<Number*>(rightObject);
685                         return Compare(leftNodeSetrightNumberopcontext);
686                     }
687                     case ObjectKind.string:
688                     {
689                         Str* rightString = cast<Str*>(rightObject);
690                         return Compare(leftNodeSetrightStringopcontext);
691                     }
692                 }
693                 break;
694             }
695             case ObjectKind.boolean:
696             {
697                 Boolean* leftBoolean = cast<Boolean*>(leftObject);
698                 switch (rightObject->Kind())
699                 {
700                     case ObjectKind.boolean:
701                     {
702                         Boolean* rightBoolean = cast<Boolean*>(rightObject);
703                         return Compare(leftBooleanrightBooleanop);
704                     }
705                     case ObjectKind.nodeSet:
706                     {
707                         NodeSet* rightNodeSet = cast<NodeSet*>(rightObject);
708                         return Compare(leftBooleanrightNodeSetopcontext);
709                     }
710                     case ObjectKind.number:
711                     {
712                         Number* rightNumber = cast<Number*>(rightObject);
713                         return Compare(leftBooleanrightNumberopcontext);
714                     }
715                     case ObjectKind.string:
716                     {
717                         Str* rightString = cast<Str*>(rightObject);
718                         return Compare(leftBooleanrightStringopcontext);
719                     }
720                 }
721                 break;
722             }
723             case ObjectKind.number:
724             {
725                 Number* leftNumber = cast<Number*>(leftObject);
726                 switch (rightObject->Kind())
727                 {
728                     case ObjectKind.number:
729                     {
730                         Number* rightNumber = cast<Number*>(rightObject);
731                         return Compare(leftNumberrightNumberop);
732                     }
733                     case ObjectKind.nodeSet:
734                     {
735                         NodeSet* rightNodeSet = cast<NodeSet*>(rightObject);
736                         return Compare(leftNumberrightNodeSetopcontext);
737                     }
738                     case ObjectKind.boolean:
739                     {
740                         Boolean* rightBoolean = cast<Boolean*>(rightObject);
741                         return Compare(leftNumberrightBooleanopcontext);
742                     }
743                     case ObjectKind.string:
744                     {
745                         Str* rightString = cast<Str*>(rightObject);
746                         return Compare(leftNumberrightStringopcontext);
747                     }
748                 }
749                 break;
750             }
751             case ObjectKind.string:
752             {
753                 Str* leftString = cast<Str*>(leftObject);
754                 switch (rightObject->Kind())
755                 {
756                     case ObjectKind.string:
757                     {
758                         Str* rightString = cast<Str*>(rightObject);
759                         return Compare(leftStringrightStringop);
760                     }
761                     case ObjectKind.nodeSet:
762                     {
763                         NodeSet* rightNodeSet = cast<NodeSet*>(rightObject);
764                         return Compare(leftStringrightNodeSetopcontext);
765                     }
766                     case ObjectKind.boolean:
767                     {
768                         Boolean* rightBoolean = cast<Boolean*>(rightObject);
769                         return Compare(leftStringrightBooleanopcontext);
770                     }
771                     case ObjectKind.number:
772                     {
773                         Number* rightNumber = cast<Number*>(rightObject);
774                         return Compare(leftStringrightNumberopcontext);
775                     }
776                 }
777                 break;
778             }
779         }
780         return Result<UniquePtr<Object>>(UniquePtr<Object>(new Boolean(false)));
781     }
782 
783     [nodiscard]
784     public Result<UniquePtr<Object>> EvaluateArithmeticOp(Expr* leftExpr* rightOperator opContext& context)
785     {
786         Result<UniquePtr<Object>> leftOperand = left->Evaluate(context);
787         if (leftOperand.Error())
788         {
789             return leftOperand;
790         }
791         Result<UniquePtr<Object>> rightOperand = right->Evaluate(context);
792         if (rightOperand.Error())
793         {
794             return rightOperand;
795         }
796         Object* leftObject = leftOperand.Value().Get();
797         Object* rightObject = rightOperand.Value().Get();
798         Result<UniquePtr<Object>> leftAsNumber = ToNumber(leftObjectcontext);
799         if (leftAsNumber.Error())
800         {
801             return leftAsNumber;
802         }
803         Result<Number*> leftNumberCastResult = NumberCast(leftAsNumber.Value().Get());
804         if (leftNumberCastResult.Error())
805         {
806             return Result<UniquePtr<Object>>(ErrorId(leftNumberCastResult.GetErrorId()));
807         }
808         Number* leftNumber = leftNumberCastResult.Value();
809         Result<UniquePtr<Object>> rightAsNumber = ToNumber(rightObjectcontext);
810         if (rightAsNumber.Error())
811         {
812             return rightAsNumber;
813         }
814         Result<Number*> rightNumberCastResult = NumberCast(rightAsNumber.Value().Get());
815         if (rightNumberCastResult.Error())
816         {
817             return Result<UniquePtr<Object>>(ErrorId(rightNumberCastResult.GetErrorId()));
818         }
819         Number* rightNumber = rightNumberCastResult.Value();
820         switch (op)
821         {
822             case Operator.plus:
823             {
824                 return Result<UniquePtr<Object>>(UniquePtr<Object>(new Number(leftNumber->Value() + rightNumber->Value())));
825             }
826             case Operator.minus:
827             {
828                 return Result<UniquePtr<Object>>(UniquePtr<Object>(new Number(leftNumber->Value() - rightNumber->Value())));
829             }
830             case Operator.mul:
831             {
832                 return Result<UniquePtr<Object>>(UniquePtr<Object>(new Number(leftNumber->Value() * rightNumber->Value())));
833             }
834             case Operator.div:
835             {
836                 return Result<UniquePtr<Object>>(UniquePtr<Object>(new Number(leftNumber->Value() / rightNumber->Value())));
837             }
838             case Operator.mod:
839             {
840                 return Result<UniquePtr<Object>>(UniquePtr<Object>(new Number(RtmRemainder(leftNumber->Value()rightNumber->Value()))));
841             }
842         }
843         int errorId = AllocateError("arithmetic binary operator expected");
844         return Result<UniquePtr<Object>>(ErrorId(errorId));
845     }
846 
847     [nodiscard]
848     public Result<UniquePtr<Object>> EvaluateUnionExpr(Expr* leftExpr* rightContext& context)
849     {
850         Result<UniquePtr<Object>> leftOperand = left->Evaluate(context);
851         if (leftOperand.Error())
852         {
853             return leftOperand;
854         }
855         Result<UniquePtr<Object>> rightOperand = right->Evaluate(context);
856         if (rightOperand.Error())
857         {
858             return rightOperand;
859         }
860         Object* leftObject = leftOperand.Value().Get();
861         Object* rightObject = rightOperand.Value().Get();
862         Result<NodeSet*> leftNodeSetCastResult = NodeSetCast(leftObject);
863         if (leftNodeSetCastResult.Error())
864         {
865             return Result<UniquePtr<Object>>(ErrorId(leftNodeSetCastResult.GetErrorId()));
866         }
867         NodeSet* leftNodeSet = leftNodeSetCastResult.Value();
868         Result<NodeSet*> rightNodeSetCastResult = NodeSetCast(rightObject);
869         if (rightNodeSetCastResult.Error())
870         {
871             return Result<UniquePtr<Object>>(ErrorId(rightNodeSetCastResult.GetErrorId()));
872         }
873         NodeSet* rightNodeSet = rightNodeSetCastResult.Value();
874         UniquePtr<NodeSet> nodeSet(new NodeSet());
875         int n = leftNodeSet->Count();
876         for (int i = 0; i < n; ++i;)
877         {
878             nodeSet->Add(leftNodeSet->GetNode(i));
879         }
880         int m = rightNodeSet->Count();
881         for (int i = 0; i < m; ++i;)
882         {
883             nodeSet->Add(rightNodeSet->GetNode(i));
884         }
885         Result<UniquePtr<Object>> result(UniquePtr<Object>(nodeSet.Release()));
886         return result;
887     }
888 
889     [nodiscard]
890     public Result<UniquePtr<Object>> EvaluateCombineStepExpr(Expr* leftExpr* rightContext& context)
891     {
892         Result<UniquePtr<Object>> leftOperand = left->Evaluate(context);
893         if (leftOperand.Error())
894         {
895             return leftOperand;
896         }
897         Result<NodeSet*> leftNodeSetCastResult = NodeSetCast(leftOperand.Value().Get());
898         if (leftNodeSetCastResult.Error())
899         {
900             return Result<UniquePtr<Object>>(ErrorId(leftNodeSetCastResult.GetErrorId()));
901         }
902         NodeSet* leftNodeSet = leftNodeSetCastResult.Value();
903         UniquePtr<NodeSet> result(new NodeSet());
904         int n = leftNodeSet->Count();
905         for (int i = 0; i < n; ++i;)
906         {
907             System.Xml.Node* leftNode = leftNodeSet->GetNode(i);
908             Context rightContext(leftNodei + 1n);
909             Result<UniquePtr<Object>> rightOperand = right->Evaluate(rightContext);
910             Result<NodeSet*> rightNodeSetCastResult = NodeSetCast(rightOperand.Value().Get());
911             if (rightNodeSetCastResult.Error())
912             {
913                 return Result<UniquePtr<Object>>(ErrorId(rightNodeSetCastResult.GetErrorId()));
914             }
915             NodeSet* rightNodeSet = rightNodeSetCastResult.Value();
916             int m = rightNodeSet->Count();
917             for (int j = 0; j < m; ++j;)
918             {
919                 System.Xml.Node* rightNode = rightNodeSet->GetNode(j);
920                 result->Add(rightNode);
921             }
922         }
923         return Result<UniquePtr<Object>>(UniquePtr<Object>(result.Release()));
924     }
925