Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
DebugViewWriter.cs
Go to the documentation of this file.
3using System.IO;
6
8
9internal sealed class DebugViewWriter : ExpressionVisitor
10{
11 [Flags]
12 private enum Flow
13 {
14 None = 0,
15 Space = 1,
16 NewLine = 2,
17 Break = 0x8000
18 }
19
20 private readonly TextWriter _out;
21
22 private int _column;
23
24 private readonly Stack<int> _stack = new Stack<int>();
25
26 private int _delta;
27
28 private Flow _flow;
29
31
33
35
37
38 private int Base
39 {
40 get
41 {
42 if (_stack.Count <= 0)
43 {
44 return 0;
45 }
46 return _stack.Peek();
47 }
48 }
49
50 private int Delta => _delta;
51
52 private int Depth => Base + Delta;
53
55 {
56 _out = file;
57 }
58
59 private void Indent()
60 {
61 _delta += 4;
62 }
63
64 private void Dedent()
65 {
66 _delta -= 4;
67 }
68
69 private void NewLine()
70 {
71 _flow = Flow.NewLine;
72 }
73
74 private static int GetId<T>(T e, ref Dictionary<T, int> ids)
75 {
76 if (ids == null)
77 {
78 ids = new Dictionary<T, int>();
79 ids.Add(e, 1);
80 return 1;
81 }
82 if (!ids.TryGetValue(e, out var value))
83 {
84 value = ids.Count + 1;
85 ids.Add(e, value);
86 }
87 return value;
88 }
89
91 {
92 return GetId(le, ref _lambdaIds);
93 }
94
96 {
97 return GetId(p, ref _paramIds);
98 }
99
100 private int GetLabelTargetId(LabelTarget target)
101 {
102 return GetId(target, ref _labelIds);
103 }
104
105 internal static void WriteTo(Expression node, TextWriter writer)
106 {
107 new DebugViewWriter(writer).WriteTo(node);
108 }
109
110 private void WriteTo(Expression node)
111 {
113 {
115 }
116 else
117 {
118 Visit(node);
119 }
120 while (_lambdas != null && _lambdas.Count > 0)
121 {
122 WriteLine();
123 WriteLine();
124 WriteLambda(_lambdas.Dequeue());
125 }
126 }
127
128 private void Out(string s)
129 {
130 Out(Flow.None, s, Flow.None);
131 }
132
133 private void Out(Flow before, string s)
134 {
135 Out(before, s, Flow.None);
136 }
137
138 private void Out(string s, Flow after)
139 {
140 Out(Flow.None, s, after);
141 }
142
143 [MethodImpl(MethodImplOptions.NoInlining)]
144 private void Out(Flow before, string s, Flow after)
145 {
146 switch (GetFlow(before))
147 {
148 case Flow.Space:
149 Write(" ");
150 break;
151 case Flow.NewLine:
152 WriteLine();
153 Write(new string(' ', Depth));
154 break;
155 }
156 Write(s);
157 _flow = after;
158 }
159
160 private void WriteLine()
161 {
162 _out.WriteLine();
163 _column = 0;
164 }
165
166 private void Write(string s)
167 {
168 _out.Write(s);
169 _column += s.Length;
170 }
171
173 {
174 Flow val = CheckBreak(_flow);
176 return (Flow)Math.Max((int)val, (int)flow);
177 }
178
180 {
181 if ((flow & Flow.Break) != 0)
182 {
183 flow = ((_column <= 120 + Depth) ? (flow & ~Flow.Break) : Flow.NewLine);
184 }
185 return flow;
186 }
187
192
194 {
196 {
197 Visit(e);
198 });
199 }
200
202 {
204 {
205 Out(variable.Type.ToString());
206 if (variable.IsByRef)
207 {
208 Out("&");
209 }
210 Out(" ");
212 });
213 }
214
216 {
217 Out(open.ToString());
218 if (expressions != null)
219 {
220 Indent();
221 bool flag = true;
222 foreach (T expression in expressions)
223 {
224 if (flag)
225 {
226 if (open == '{' || expressions.Count > 1)
227 {
228 NewLine();
229 }
230 flag = false;
231 }
232 else
233 {
234 Out(separator.ToString(), Flow.NewLine);
235 }
237 }
238 Dedent();
239 }
240 char c = open switch
241 {
242 '(' => ')',
243 '{' => '}',
244 '[' => ']',
245 _ => throw ContractUtils.Unreachable,
246 };
247 if (open == '{')
248 {
249 NewLine();
250 }
251 Out(c.ToString(), Flow.Break);
252 }
253
254 protected internal override Expression VisitBinary(BinaryExpression node)
255 {
256 if (node.NodeType == ExpressionType.ArrayIndex)
257 {
259 Out("[");
260 Visit(node.Right);
261 Out("]");
262 }
263 else
264 {
265 bool flag = NeedsParentheses(node, node.Left);
266 bool flag2 = NeedsParentheses(node, node.Right);
267 Flow before = Flow.Space;
268 string s;
269 switch (node.NodeType)
270 {
271 case ExpressionType.Assign:
272 s = "=";
273 break;
274 case ExpressionType.Equal:
275 s = "==";
276 break;
277 case ExpressionType.NotEqual:
278 s = "!=";
279 break;
280 case ExpressionType.AndAlso:
281 s = "&&";
282 before = Flow.Space | Flow.Break;
283 break;
284 case ExpressionType.OrElse:
285 s = "||";
286 before = Flow.Space | Flow.Break;
287 break;
288 case ExpressionType.GreaterThan:
289 s = ">";
290 break;
291 case ExpressionType.LessThan:
292 s = "<";
293 break;
294 case ExpressionType.GreaterThanOrEqual:
295 s = ">=";
296 break;
297 case ExpressionType.LessThanOrEqual:
298 s = "<=";
299 break;
300 case ExpressionType.Add:
301 s = "+";
302 break;
303 case ExpressionType.AddAssign:
304 s = "+=";
305 break;
306 case ExpressionType.AddAssignChecked:
307 s = "#+=";
308 break;
309 case ExpressionType.AddChecked:
310 s = "#+";
311 break;
312 case ExpressionType.Subtract:
313 s = "-";
314 break;
315 case ExpressionType.SubtractAssign:
316 s = "-=";
317 break;
318 case ExpressionType.SubtractAssignChecked:
319 s = "#-=";
320 break;
321 case ExpressionType.SubtractChecked:
322 s = "#-";
323 break;
324 case ExpressionType.Divide:
325 s = "/";
326 break;
327 case ExpressionType.DivideAssign:
328 s = "/=";
329 break;
330 case ExpressionType.Modulo:
331 s = "%";
332 break;
333 case ExpressionType.ModuloAssign:
334 s = "%=";
335 break;
336 case ExpressionType.Multiply:
337 s = "*";
338 break;
339 case ExpressionType.MultiplyAssign:
340 s = "*=";
341 break;
342 case ExpressionType.MultiplyAssignChecked:
343 s = "#*=";
344 break;
345 case ExpressionType.MultiplyChecked:
346 s = "#*";
347 break;
348 case ExpressionType.LeftShift:
349 s = "<<";
350 break;
351 case ExpressionType.LeftShiftAssign:
352 s = "<<=";
353 break;
354 case ExpressionType.RightShift:
355 s = ">>";
356 break;
357 case ExpressionType.RightShiftAssign:
358 s = ">>=";
359 break;
360 case ExpressionType.And:
361 s = "&";
362 break;
363 case ExpressionType.AndAssign:
364 s = "&=";
365 break;
366 case ExpressionType.Or:
367 s = "|";
368 break;
369 case ExpressionType.OrAssign:
370 s = "|=";
371 break;
372 case ExpressionType.ExclusiveOr:
373 s = "^";
374 break;
375 case ExpressionType.ExclusiveOrAssign:
376 s = "^=";
377 break;
378 case ExpressionType.Power:
379 s = "**";
380 break;
381 case ExpressionType.PowerAssign:
382 s = "**=";
383 break;
384 case ExpressionType.Coalesce:
385 s = "??";
386 break;
387 default:
388 throw new InvalidOperationException();
389 }
390 if (flag)
391 {
392 Out("(", Flow.None);
393 }
394 Visit(node.Left);
395 if (flag)
396 {
397 Out(Flow.None, ")", Flow.Break);
398 }
399 Out(before, s, Flow.Space | Flow.Break);
400 if (flag2)
401 {
402 Out("(", Flow.None);
403 }
404 Visit(node.Right);
405 if (flag2)
406 {
407 Out(Flow.None, ")", Flow.Break);
408 }
409 }
410 return node;
411 }
412
414 {
415 Out("$");
416 if (string.IsNullOrEmpty(node.Name))
417 {
418 Out("var" + GetParamId(node));
419 }
420 else
421 {
422 Out(GetDisplayName(node.Name));
423 }
424 return node;
425 }
426
427 protected internal override Expression VisitLambda<T>(Expression<T> node)
428 {
429 Out($".Lambda {GetLambdaName(node)}<{node.Type}>");
430 if (_lambdas == null)
431 {
433 }
434 if (!_lambdas.Contains(node))
435 {
436 _lambdas.Enqueue(node);
437 }
438 return node;
439 }
440
441 private static bool IsSimpleExpression(Expression node)
442 {
444 {
446 {
447 return !(binaryExpression.Right is BinaryExpression);
448 }
449 return false;
450 }
451 return false;
452 }
453
455 {
456 if (IsSimpleExpression(node.Test))
457 {
458 Out(".If (");
459 Visit(node.Test);
460 Out(") {", Flow.NewLine);
461 }
462 else
463 {
464 Out(".If (", Flow.NewLine);
465 Indent();
466 Visit(node.Test);
467 Dedent();
468 Out(Flow.NewLine, ") {", Flow.NewLine);
469 }
470 Indent();
471 Visit(node.IfTrue);
472 Dedent();
473 Out(Flow.NewLine, "} .Else {", Flow.NewLine);
474 Indent();
475 Visit(node.IfFalse);
476 Dedent();
477 Out(Flow.NewLine, "}");
478 return node;
479 }
480
481 protected internal override Expression VisitConstant(ConstantExpression node)
482 {
483 object value = node.Value;
484 if (value == null)
485 {
486 Out("null");
487 }
488 else if (value is string && node.Type == typeof(string))
489 {
490 Out($"\"{value}\"");
491 }
492 else if (value is char && node.Type == typeof(char))
493 {
494 Out($"'{value}'");
495 }
496 else if ((value is int && node.Type == typeof(int)) || (value is bool && node.Type == typeof(bool)))
497 {
498 Out(value.ToString());
499 }
500 else
501 {
503 if (constantValueSuffix != null)
504 {
505 Out(value.ToString());
507 }
508 else
509 {
510 Out($".Constant<{node.Type}>({value})");
511 }
512 }
513 return node;
514 }
515
516 private static string GetConstantValueSuffix(Type type)
517 {
518 if (type == typeof(uint))
519 {
520 return "U";
521 }
522 if (type == typeof(long))
523 {
524 return "L";
525 }
526 if (type == typeof(ulong))
527 {
528 return "UL";
529 }
530 if (type == typeof(double))
531 {
532 return "D";
533 }
534 if (type == typeof(float))
535 {
536 return "F";
537 }
538 if (type == typeof(decimal))
539 {
540 return "M";
541 }
542 return null;
543 }
544
546 {
547 Out(".RuntimeVariables");
548 VisitExpressions('(', node.Variables);
549 return node;
550 }
551
552 private void OutMember(Expression node, Expression instance, MemberInfo member)
553 {
554 if (instance != null)
555 {
556 ParenthesizedVisit(node, instance);
557 Out("." + member.Name);
558 }
559 else
560 {
561 Out(member.DeclaringType.ToString() + "." + member.Name);
562 }
563 }
564
565 protected internal override Expression VisitMember(MemberExpression node)
566 {
567 OutMember(node, node.Expression, node.Member);
568 return node;
569 }
570
572 {
573 Out(".Invoke ");
574 ParenthesizedVisit(node, node.Expression);
575 VisitExpressions('(', node.Arguments);
576 return node;
577 }
578
579 private static bool NeedsParentheses(Expression parent, Expression child)
580 {
581 if (child == null)
582 {
583 return false;
584 }
585 switch (parent.NodeType)
586 {
587 case ExpressionType.Decrement:
588 case ExpressionType.Increment:
589 case ExpressionType.Unbox:
590 case ExpressionType.IsTrue:
591 case ExpressionType.IsFalse:
592 return true;
593 default:
594 {
598 {
599 switch (parent.NodeType)
600 {
601 case ExpressionType.And:
602 case ExpressionType.AndAlso:
603 case ExpressionType.ExclusiveOr:
604 case ExpressionType.Or:
605 case ExpressionType.OrElse:
606 return false;
607 case ExpressionType.Add:
608 case ExpressionType.AddChecked:
609 case ExpressionType.Multiply:
610 case ExpressionType.MultiplyChecked:
611 return false;
612 case ExpressionType.Divide:
613 case ExpressionType.Modulo:
614 case ExpressionType.Subtract:
615 case ExpressionType.SubtractChecked:
616 {
618 return child == binaryExpression.Right;
619 }
620 default:
621 return true;
622 }
623 }
624 if (child != null && child.NodeType == ExpressionType.Constant && (parent.NodeType == ExpressionType.Negate || parent.NodeType == ExpressionType.NegateChecked))
625 {
626 return true;
627 }
629 }
630 }
631 }
632
634 {
635 switch (node.NodeType)
636 {
637 case ExpressionType.Coalesce:
638 case ExpressionType.Assign:
639 case ExpressionType.AddAssign:
640 case ExpressionType.AndAssign:
641 case ExpressionType.DivideAssign:
642 case ExpressionType.ExclusiveOrAssign:
643 case ExpressionType.LeftShiftAssign:
644 case ExpressionType.ModuloAssign:
645 case ExpressionType.MultiplyAssign:
646 case ExpressionType.OrAssign:
647 case ExpressionType.PowerAssign:
648 case ExpressionType.RightShiftAssign:
649 case ExpressionType.SubtractAssign:
650 case ExpressionType.AddAssignChecked:
651 case ExpressionType.MultiplyAssignChecked:
652 case ExpressionType.SubtractAssignChecked:
653 return 1;
654 case ExpressionType.OrElse:
655 return 2;
656 case ExpressionType.AndAlso:
657 return 3;
658 case ExpressionType.Or:
659 return 4;
660 case ExpressionType.ExclusiveOr:
661 return 5;
662 case ExpressionType.And:
663 return 6;
664 case ExpressionType.Equal:
665 case ExpressionType.NotEqual:
666 return 7;
667 case ExpressionType.GreaterThan:
668 case ExpressionType.GreaterThanOrEqual:
669 case ExpressionType.LessThan:
670 case ExpressionType.LessThanOrEqual:
671 case ExpressionType.TypeAs:
672 case ExpressionType.TypeIs:
673 case ExpressionType.TypeEqual:
674 return 8;
675 case ExpressionType.LeftShift:
676 case ExpressionType.RightShift:
677 return 9;
678 case ExpressionType.Add:
679 case ExpressionType.AddChecked:
680 case ExpressionType.Subtract:
681 case ExpressionType.SubtractChecked:
682 return 10;
683 case ExpressionType.Divide:
684 case ExpressionType.Modulo:
685 case ExpressionType.Multiply:
686 case ExpressionType.MultiplyChecked:
687 return 11;
688 case ExpressionType.Convert:
689 case ExpressionType.ConvertChecked:
690 case ExpressionType.Negate:
691 case ExpressionType.UnaryPlus:
692 case ExpressionType.NegateChecked:
693 case ExpressionType.Not:
694 case ExpressionType.Decrement:
695 case ExpressionType.Increment:
696 case ExpressionType.Throw:
697 case ExpressionType.Unbox:
698 case ExpressionType.PreIncrementAssign:
699 case ExpressionType.PreDecrementAssign:
700 case ExpressionType.OnesComplement:
701 case ExpressionType.IsTrue:
702 case ExpressionType.IsFalse:
703 return 12;
704 case ExpressionType.Power:
705 return 13;
706 default:
707 return 14;
708 case ExpressionType.Constant:
709 case ExpressionType.Parameter:
710 return 15;
711 }
712 }
713
715 {
716 if (NeedsParentheses(parent, nodeToVisit))
717 {
718 Out("(");
720 Out(")");
721 }
722 else
723 {
725 }
726 }
727
729 {
730 Out(".Call ");
731 if (node.Object != null)
732 {
734 }
735 else if (node.Method.DeclaringType != null)
736 {
737 Out(node.Method.DeclaringType.ToString());
738 }
739 else
740 {
741 Out("<UnknownType>");
742 }
743 Out(".");
744 Out(node.Method.Name);
745 VisitExpressions('(', node.Arguments);
746 return node;
747 }
748
749 protected internal override Expression VisitNewArray(NewArrayExpression node)
750 {
751 if (node.NodeType == ExpressionType.NewArrayBounds)
752 {
753 Out(".NewArray " + node.Type.GetElementType().ToString());
754 VisitExpressions('[', node.Expressions);
755 }
756 else
757 {
758 Out(".NewArray " + node.Type.ToString(), Flow.Space);
759 VisitExpressions('{', node.Expressions);
760 }
761 return node;
762 }
763
764 protected internal override Expression VisitNew(NewExpression node)
765 {
766 Out(".New " + node.Type.ToString());
767 VisitExpressions('(', node.Arguments);
768 return node;
769 }
770
772 {
773 if (node.Arguments.Count == 1)
774 {
775 Visit(node.Arguments[0]);
776 }
777 else
778 {
779 VisitExpressions('{', node.Arguments);
780 }
781 return node;
782 }
783
784 protected internal override Expression VisitListInit(ListInitExpression node)
785 {
786 Visit(node.NewExpression);
787 VisitExpressions('{', ',', node.Initializers, delegate(ElementInit e)
788 {
790 });
791 return node;
792 }
793
795 {
796 Out(assignment.Member.Name);
797 Out(Flow.Space, "=", Flow.Space);
798 Visit(assignment.Expression);
799 return assignment;
800 }
801
803 {
804 Out(binding.Member.Name);
805 Out(Flow.Space, "=", Flow.Space);
806 VisitExpressions('{', ',', binding.Initializers, delegate(ElementInit e)
807 {
809 });
810 return binding;
811 }
812
814 {
815 Out(binding.Member.Name);
816 Out(Flow.Space, "=", Flow.Space);
817 VisitExpressions('{', ',', binding.Bindings, delegate(MemberBinding e)
818 {
820 });
821 return binding;
822 }
823
825 {
826 Visit(node.NewExpression);
827 VisitExpressions('{', ',', node.Bindings, delegate(MemberBinding e)
828 {
830 });
831 return node;
832 }
833
835 {
836 ParenthesizedVisit(node, node.Expression);
837 switch (node.NodeType)
838 {
839 case ExpressionType.TypeIs:
840 Out(Flow.Space, ".Is", Flow.Space);
841 break;
842 case ExpressionType.TypeEqual:
843 Out(Flow.Space, ".TypeEqual", Flow.Space);
844 break;
845 }
846 Out(node.TypeOperand.ToString());
847 return node;
848 }
849
850 protected internal override Expression VisitUnary(UnaryExpression node)
851 {
852 switch (node.NodeType)
853 {
854 case ExpressionType.Convert:
855 Out("(" + node.Type.ToString() + ")");
856 break;
857 case ExpressionType.ConvertChecked:
858 Out("#(" + node.Type.ToString() + ")");
859 break;
860 case ExpressionType.Not:
861 Out((node.Type == typeof(bool)) ? "!" : "~");
862 break;
863 case ExpressionType.OnesComplement:
864 Out("~");
865 break;
866 case ExpressionType.Negate:
867 Out("-");
868 break;
869 case ExpressionType.NegateChecked:
870 Out("#-");
871 break;
872 case ExpressionType.UnaryPlus:
873 Out("+");
874 break;
875 case ExpressionType.Quote:
876 Out("'");
877 break;
878 case ExpressionType.Throw:
879 if (node.Operand == null)
880 {
881 Out(".Rethrow");
882 }
883 else
884 {
885 Out(".Throw", Flow.Space);
886 }
887 break;
888 case ExpressionType.IsFalse:
889 Out(".IsFalse");
890 break;
891 case ExpressionType.IsTrue:
892 Out(".IsTrue");
893 break;
894 case ExpressionType.Decrement:
895 Out(".Decrement");
896 break;
897 case ExpressionType.Increment:
898 Out(".Increment");
899 break;
900 case ExpressionType.PreDecrementAssign:
901 Out("--");
902 break;
903 case ExpressionType.PreIncrementAssign:
904 Out("++");
905 break;
906 case ExpressionType.Unbox:
907 Out(".Unbox");
908 break;
909 }
910 ParenthesizedVisit(node, node.Operand);
911 switch (node.NodeType)
912 {
913 case ExpressionType.TypeAs:
914 Out(Flow.Space, ".As", Flow.Space | Flow.Break);
915 Out(node.Type.ToString());
916 break;
917 case ExpressionType.ArrayLength:
918 Out(".Length");
919 break;
920 case ExpressionType.PostDecrementAssign:
921 Out("--");
922 break;
923 case ExpressionType.PostIncrementAssign:
924 Out("++");
925 break;
926 }
927 return node;
928 }
929
930 protected internal override Expression VisitBlock(BlockExpression node)
931 {
932 Out(".Block");
933 if (node.Type != node.GetExpression(node.ExpressionCount - 1).Type)
934 {
935 Out($"<{node.Type}>");
936 }
937 VisitDeclarations(node.Variables);
938 Out(" ");
939 VisitExpressions('{', ';', node.Expressions);
940 return node;
941 }
942
943 protected internal override Expression VisitDefault(DefaultExpression node)
944 {
945 Out(".Default(" + node.Type.ToString() + ")");
946 return node;
947 }
948
949 protected internal override Expression VisitLabel(LabelExpression node)
950 {
951 Out(".Label", Flow.NewLine);
952 Indent();
953 Visit(node.DefaultValue);
954 Dedent();
955 NewLine();
956 DumpLabel(node.Target);
957 return node;
958 }
959
960 protected internal override Expression VisitGoto(GotoExpression node)
961 {
962 Out("." + node.Kind, Flow.Space);
963 Out(GetLabelTargetName(node.Target), Flow.Space);
964 Out("{", Flow.Space);
965 Visit(node.Value);
966 Out(Flow.Space, "}");
967 return node;
968 }
969
970 protected internal override Expression VisitLoop(LoopExpression node)
971 {
972 Out(".Loop", Flow.Space);
973 if (node.ContinueLabel != null)
974 {
975 DumpLabel(node.ContinueLabel);
976 }
977 Out(" {", Flow.NewLine);
978 Indent();
979 Visit(node.Body);
980 Dedent();
981 Out(Flow.NewLine, "}");
982 if (node.BreakLabel != null)
983 {
984 Out("", Flow.NewLine);
985 DumpLabel(node.BreakLabel);
986 }
987 return node;
988 }
989
991 {
992 foreach (Expression testValue in node.TestValues)
993 {
994 Out(".Case (");
996 Out("):", Flow.NewLine);
997 }
998 Indent();
999 Indent();
1000 Visit(node.Body);
1001 Dedent();
1002 Dedent();
1003 NewLine();
1004 return node;
1005 }
1006
1007 protected internal override Expression VisitSwitch(SwitchExpression node)
1008 {
1009 Out(".Switch ");
1010 Out("(");
1011 Visit(node.SwitchValue);
1012 Out(") {", Flow.NewLine);
1014 if (node.DefaultBody != null)
1015 {
1016 Out(".Default:", Flow.NewLine);
1017 Indent();
1018 Indent();
1019 Visit(node.DefaultBody);
1020 Dedent();
1021 Dedent();
1022 NewLine();
1023 }
1024 Out("}");
1025 return node;
1026 }
1027
1029 {
1030 Out(Flow.NewLine, "} .Catch (" + node.Test.ToString());
1031 if (node.Variable != null)
1032 {
1033 Out(Flow.Space, "");
1034 VisitParameter(node.Variable);
1035 }
1036 if (node.Filter != null)
1037 {
1038 Out(") .If (", Flow.Break);
1039 Visit(node.Filter);
1040 }
1041 Out(") {", Flow.NewLine);
1042 Indent();
1043 Visit(node.Body);
1044 Dedent();
1045 return node;
1046 }
1047
1048 protected internal override Expression VisitTry(TryExpression node)
1049 {
1050 Out(".Try {", Flow.NewLine);
1051 Indent();
1052 Visit(node.Body);
1053 Dedent();
1055 if (node.Finally != null)
1056 {
1057 Out(Flow.NewLine, "} .Finally {", Flow.NewLine);
1058 Indent();
1059 Visit(node.Finally);
1060 Dedent();
1061 }
1062 else if (node.Fault != null)
1063 {
1064 Out(Flow.NewLine, "} .Fault {", Flow.NewLine);
1065 Indent();
1066 Visit(node.Fault);
1067 Dedent();
1068 }
1069 Out(Flow.NewLine, "}");
1070 return node;
1071 }
1072
1073 protected internal override Expression VisitIndex(IndexExpression node)
1074 {
1075 if (node.Indexer != null)
1076 {
1077 OutMember(node, node.Object, node.Indexer);
1078 }
1079 else
1080 {
1081 ParenthesizedVisit(node, node.Object);
1082 }
1083 VisitExpressions('[', node.Arguments);
1084 return node;
1085 }
1086
1087 protected internal override Expression VisitExtension(Expression node)
1088 {
1089 Out($".Extension<{node.GetType()}>");
1090 if (node.CanReduce)
1091 {
1092 Out(Flow.Space, "{", Flow.NewLine);
1093 Indent();
1094 Visit(node.Reduce());
1095 Dedent();
1096 Out(Flow.NewLine, "}");
1097 }
1098 return node;
1099 }
1100
1102 {
1103 Out($".DebugInfo({node.Document.FileName}: {node.StartLine}, {node.StartColumn} - {node.EndLine}, {node.EndColumn})");
1104 return node;
1105 }
1106
1107 private void DumpLabel(LabelTarget target)
1108 {
1109 Out(".LabelTarget " + GetLabelTargetName(target) + ":");
1110 }
1111
1112 private string GetLabelTargetName(LabelTarget target)
1113 {
1114 if (string.IsNullOrEmpty(target.Name))
1115 {
1116 return "#Label" + GetLabelTargetId(target);
1117 }
1118 return GetDisplayName(target.Name);
1119 }
1120
1122 {
1123 Out($".Lambda {GetLambdaName(lambda)}<{lambda.Type}>");
1124 VisitDeclarations(lambda.Parameters);
1125 Out(Flow.Space, "{", Flow.NewLine);
1126 Indent();
1127 Visit(lambda.Body);
1128 Dedent();
1129 Out(Flow.NewLine, "}");
1130 }
1131
1133 {
1134 if (string.IsNullOrEmpty(lambda.Name))
1135 {
1136 return "#Lambda" + GetLambdaId(lambda);
1137 }
1138 return GetDisplayName(lambda.Name);
1139 }
1140
1141 private static bool ContainsWhiteSpace(string name)
1142 {
1143 foreach (char c in name)
1144 {
1145 if (char.IsWhiteSpace(c))
1146 {
1147 return true;
1148 }
1149 }
1150 return false;
1151 }
1152
1153 private static string QuoteName(string name)
1154 {
1155 return "'" + name + "'";
1156 }
1157
1158 private static string GetDisplayName(string name)
1159 {
1160 if (ContainsWhiteSpace(name))
1161 {
1162 return QuoteName(name);
1163 }
1164 return name;
1165 }
1166}
bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
bool ICollection< KeyValuePair< TKey, TValue > >. Contains(KeyValuePair< TKey, TValue > keyValuePair)
void Add(TKey key, TValue value)
virtual void Write(char value)
virtual void WriteLine()
override Expression VisitConditional(ConditionalExpression node)
string GetLambdaName(LambdaExpression lambda)
override Expression VisitTry(TryExpression node)
string GetLabelTargetName(LabelTarget target)
static bool ContainsWhiteSpace(string name)
Dictionary< LabelTarget, int > _labelIds
override Expression VisitNewArray(NewArrayExpression node)
override Expression VisitDefault(DefaultExpression node)
override ElementInit VisitElementInit(ElementInit node)
override Expression VisitLabel(LabelExpression node)
static int GetId< T >(T e, ref Dictionary< T, int > ids)
static bool NeedsParentheses(Expression parent, Expression child)
override Expression VisitMemberInit(MemberInitExpression node)
void VisitExpressions< T >(char open, IReadOnlyList< T > expressions)
override Expression VisitNew(NewExpression node)
override MemberListBinding VisitMemberListBinding(MemberListBinding binding)
static string GetDisplayName(string name)
static int GetOperatorPrecedence(Expression node)
override Expression VisitDebugInfo(DebugInfoExpression node)
Dictionary< ParameterExpression, int > _paramIds
override CatchBlock VisitCatchBlock(CatchBlock node)
override Expression VisitSwitch(SwitchExpression node)
override Expression VisitExtension(Expression node)
override Expression VisitInvocation(InvocationExpression node)
void WriteLambda(LambdaExpression lambda)
override Expression VisitMember(MemberExpression node)
override SwitchCase VisitSwitchCase(SwitchCase node)
static void WriteTo(Expression node, TextWriter writer)
override Expression VisitBlock(BlockExpression node)
override Expression VisitLoop(LoopExpression node)
override Expression VisitConstant(ConstantExpression node)
override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding)
override Expression VisitMethodCall(MethodCallExpression node)
void Out(Flow before, string s, Flow after)
Dictionary< LambdaExpression, int > _lambdaIds
void ParenthesizedVisit(Expression parent, Expression nodeToVisit)
void OutMember(Expression node, Expression instance, MemberInfo member)
void VisitDeclarations(IReadOnlyList< ParameterExpression > expressions)
override MemberAssignment VisitMemberAssignment(MemberAssignment assignment)
static string GetConstantValueSuffix(Type type)
int GetParamId(ParameterExpression p)
override Expression VisitRuntimeVariables(RuntimeVariablesExpression node)
override Expression VisitIndex(IndexExpression node)
override Expression VisitLambda< T >(Expression< T > node)
override Expression VisitGoto(GotoExpression node)
override Expression VisitUnary(UnaryExpression node)
override Expression VisitBinary(BinaryExpression node)
override Expression VisitListInit(ListInitExpression node)
static bool IsSimpleExpression(Expression node)
override Expression VisitTypeBinary(TypeBinaryExpression node)
override Expression VisitParameter(ParameterExpression node)
virtual ? Expression Visit(Expression? node)
virtual MemberBinding VisitMemberBinding(MemberBinding node)
virtual ExpressionType NodeType
static byte Max(byte val1, byte val2)
Definition Math.cs:738
override string ToString()
Definition Type.cs:1108