Mercury library 1.0 Translation of CFG grammars into an object model (Bachelor's thesis).

- Main Page
- Packages
- Classes
- Files

- File List

All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties
BasicActions.cs
Go to the documentation of this file.
1 using Mercury.Exceptions;
2 using Mercury.Nucleus.Trees;
3 using Mercury.Syntax;
4 using System;
5 using System.Collections.Generic;
6 using System.Globalization;
7 using System.IO;
8 using System.Linq;
9
10 namespace Mercury.Interpreting
11 {
12
13 //=============================================================================
14 // BasicActions
15 //=============================================================================
16
39 public static class BasicActions<T>
40 where T : class
41 {
42 //--[ Private fields ]-----------------------------------------------
43
44 private static CultureInfo cinf = CultureInfo.InvariantCulture;
45
46 //==<< Actions >>====================================================
47
48 //--[ Parsing actions ]----------------------------------------------
49
54 public static readonly InterpreterAction<T> ParseInteger
55 = new ConvertAction<T, string, int>("ParseInteger",
56 x => { int i; return int.TryParse(x, NumberStyles.Integer, cinf, out i) ? i : default(int); });
57
62 public static readonly InterpreterAction<T> ParseReal
63 = new ConvertAction<T, string, double>("ParseReal",
64 x => { double d; return double.TryParse(x, NumberStyles.Float, cinf, out d) ? d : default(double); });
65
70 public static readonly InterpreterAction<T> ParseBoolean
71 = new ConvertAction<T, string, bool>("ParseBoolean",
72 x => { bool b; return bool.TryParse(x, out b) ? b : default(bool); });
73
74 //--[ Rounding and conversions ]-------------------------------------
75
77 public static readonly InterpreterAction<T> Round
78 = new ConvertAction<T, double, int>("Round", x => Convert.ToInt32(Math.Round(x)));
80 public static readonly InterpreterAction<T> Ceiling
81 = new ConvertAction<T, double, int>("Ceiling", x => Convert.ToInt32(Math.Ceiling(x)));
83 public static readonly InterpreterAction<T> Floor
84 = new ConvertAction<T, double, int>("Floor", x => Convert.ToInt32(Math.Floor(x)));
86 public static readonly InterpreterAction<T> ToReal
87 = new ConvertAction<T, int, double>("ToReal", x => Convert.ToDouble(x));
89 public static readonly InterpreterAction<T> String
90 = new ConvertAction<T, object, string>("String", x => x.ToString());
91
92 //--[ Arithmetics ]--------------------------------------------------
93
95 public static readonly InterpreterAction<T> Add
96 = new ArithmeticAction<T>("Add", (x, y) => x + y);
98 public static readonly InterpreterAction<T> Sub
99 = new ArithmeticAction<T>("Sub", (x, y) => x - y);
101 public static readonly InterpreterAction<T> Mul
102 = new ArithmeticAction<T>("Mul", (x, y) => x * y);
104 public static readonly InterpreterAction<T> Div
105 = new ArithmeticAction<T>("Div", (x, y) => x / y);
107 public static readonly InterpreterAction<T> Pow
108 = new ArithmeticAction<T>("Pow", (x, y) => Math.Pow(x, y));
110 public static readonly InterpreterAction<T> FDiv
111 = new OperationAction<T, double, double>("FDiv", (x, y) => x / y);
113 public static readonly InterpreterAction<T> Mod
114 = new OperationAction<T, int, int>("Mod", (x, y) => x % y);
115
116 //--[ Boolean operations ]-------------------------------------------
117
119 public static readonly InterpreterAction<T> IsNull
120 = new ConvertAction<T, object, bool>("IsNull", x => x == null, ArgumentType.Null);
122 public static readonly InterpreterAction<T> And
123 = new FoldingAction<T, bool, bool>("And", 2, (x, y) => x && y, true);
125 public static readonly InterpreterAction<T> Or
126 = new FoldingAction<T, bool, bool>("Or", 2, (x, y) => x && y, false);
128 public static readonly InterpreterAction<T> Not
129 = new ConvertAction<T, bool, bool>("Not", x => !x);
131 public static readonly InterpreterAction<T> Xor
132 = new OperationAction<T, bool, bool>("Xor", (x, y) => x ^ y);
137 public static readonly InterpreterAction<T> Eq
138 = new OperationAction<T, object, bool>("Eq", (x, y) => (x != null) && x.Equals(y), ArgumentType.Null);
140 public static readonly InterpreterAction<T> Neq
141 = new OperationAction<T, object, bool>("Neq", (x, y) => (x == null) || !x.Equals(y), ArgumentType.Null);
143 public static readonly InterpreterAction<T> Gr
144 = new OperationAction<T, double, bool>("Gr", (x, y) => x > y);
146 public static readonly InterpreterAction<T> Ls
147 = new OperationAction<T, double, bool>("Ls", (x, y) => x < y);
149 public static readonly InterpreterAction<T> Geq
150 = new OperationAction<T, double, bool>("Geq", (x, y) => x >= y);
152 public static readonly InterpreterAction<T> Leq
153 = new OperationAction<T, double, bool>("Leq", (x, y) => x <= y);
154
155 //--[ String actions ]-----------------------------------------------
156
158 public static readonly InterpreterAction<T> Empty
159 = new ConstantAction<T, string>("Empty", "");
164 public static readonly InterpreterAction<T> Join
165 = new JoinAction<T>();
167 public static readonly InterpreterAction<T> Concat
168 = new ConcatAction<T>();
173 public static readonly InterpreterAction<T> Flatten
174 = new FlattenAction<T>();
175
176 //--[ Tree and symbol actions ]--------------------------------------
177
179 public static readonly InterpreterAction<T> Name
180 = new ConvertAction<T, Symbol, string>("Name", x => x.Name);
182 public static readonly InterpreterAction<T> Symbol
183 = new ConvertAction<T, Tree<Symbol>, Symbol>("Symbol", x => x.Value);
185 public static readonly InterpreterAction<T> Depth
186 = new ConvertAction<T, Tree<Symbol>, int>("Depth", x => x.Depth);
188 public static readonly InterpreterAction<T> Leaves
189 = new ConvertAction<T, Tree<Symbol>, int>("Leaves", x => x.LeavesCount);
195 public static readonly InterpreterAction<T> SubTree
196 = new SubTreeAction<T>();
197
203 public static readonly InterpreterAction<T> Preterminal
204 = new ConvertAction<T, Tree<Symbol>, string>("Preterminal", x =>
205 {
206 return ((x.Children.Count != 1)
207 || ((x[0].Value.Type & (SymbolType.Terminal | SymbolType.Epsilon)) == SymbolType.None))
208 ? null : x[0].Value.Name;
209 });
210
211 //--[ Control actions ]----------------------------------------------
212
220 public static readonly InterpreterAction<T> If
221 = new IfAction<T>();
229 public static readonly InterpreterAction<T> Select
230 = new SelectAction<T>();
237 public static readonly InterpreterAction<T> Case
238 = new CaseAction<T>();
240 public static readonly InterpreterAction<T> Eval
241 = new EvaluateAction<T>();
247 public static readonly InterpreterAction<T> Simple
248 = new SimpleAction<T>();
250 public static readonly InterpreterAction<T> Fail
251 = new FailAction<T>();
259 public static readonly InterpreterAction<T> Try
260 = new TryAction<T>();
266 public static readonly InterpreterAction<T> Error
267 = new ConvertAction<T, string, object>("Error", x => { throw new ErrorActionException(x); });
268
269 //--[ Utilities ]----------------------------------------------------
270
272 public static readonly InterpreterAction<T> Identity
273 = new IdentityAction<T>();
281 public static readonly InterpreterAction<T> Let
282 = new LetAction<T>();
289 public static readonly InterpreterAction<T> Var
290 = new VarAction<T>();
295 public static readonly InterpreterAction<T> ArgsCount
296 = new ArgsCountAction<T>();
298 public static readonly InterpreterAction<T> Trace
299 = new TraceAction<T>();
300
304 public static IReadOnlyList<InterpreterAction<T>> GetAllActions()
305 {
306 return new List<InterpreterAction<T>>()
307 {
308 ParseInteger, ParseReal, ParseBoolean,
309 Round, Ceiling, Floor, ToReal, String,
310 Add, Sub, Mul, Div, Pow, FDiv, Mod,
311 IsNull, And, Or, Not, Xor, Eq, Neq, Gr, Ls, Geq, Leq,
312 Empty, Join, Concat, Flatten,
313 Name, Symbol, Depth, Leaves, SubTree, Preterminal,
314 If, Select, Case, Eval, Simple, Fail, Try, Error,
315 Identity, Let, Var, ArgsCount, Trace
316 };
317 }
318
332 public static IReadOnlyDictionary<string,string> GetAliases()
333 {
334 return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
335 {
336 { "ToString", "String" },
337
338 { "+", "Add" }, { "-", "Sub" }, { "*", "Mul" }, { "/", "Div" },
339 { "//", "FDiv" }, { "%", "Mod" }, { "**", "Pow" },
340 { "@", "String" }, { "++", "Concat" }, { "#", "Var" },
341 { "&", "And" }, { "|", "Or" }, { "^", "Xor" }, { "!", "Not" },
342 { "==", "Eq" }, { "/=", "Neq" },
343 { ">", "Gr" }, { "<", "Ls" }, { ">=", "Geq"}, { "<=", "Leq" },
344 { "$", "Eval" }, { "id", "Identity" },
345 };
346 }
347
352 public static InterpreterAction<T> CreateTracer(string name, TextWriter writer)
353 { return new TraceAction<T>(writer){ Name = name }; }
354
355 }
356
357 //=============================================================================
358 // << Action Templates >>
359 //=============================================================================
360
361 //==<< OperationAction >>====================================================
362
369 public sealed class OperationAction<T, U, V> : InterpreterAction<T, V>
370 where T : class
371 {
372 private Func<U, U, V> f;
373
374 //--[ Constructors ]-------------------------------------------------
375
383 public OperationAction(string name, Func<U, U, V> f, ArgumentType flags = ArgumentType.None)
384 : base(name, Tuple.Create(2, 2),
385 new[] { Defaults.TypeToArgType<T,U>() | (flags & ArgumentType.Flags) })
386 {
387 if (f == null) throw new ArgumentNullException("f");
388 this.f = f;
389 }
390
391 //--[ Overriden methods ]--------------------------------------------
392
393 #region [ InterpreterAction ]
394
395 public override V Evaluate(Argument[] arguments, RecursiveEval<T> eval,
396 InterpreterContext<T> context)
397 { return f(arguments[0].Value, arguments[1].Value); }
398
399 #endregion
400
401 }
402
403 //==<< FoldingAction >>=======================================================
404
415 public sealed class FoldingAction<T, U, V> : InterpreterAction<T, V>
416 where T : class
417 {
418 private Func<V, U, V> f;
419 private V s;
420
421 //--[ Constructors ]-------------------------------------------------
422
432 public FoldingAction(string name, int minargs, Func<V, U, V> f, V seed,
433 ArgumentType flags = ArgumentType.None)
434 : base(name, Tuple.Create(minargs, int.MaxValue),
435 new[] { Defaults.TypeToArgType<T, U>() | (flags & ArgumentType.Flags) })
436 {
437 if (f == null) throw new ArgumentNullException("f");
438 this.f = f;
439 this.s = seed;
440 }
441
442 //--[ Overriden methods ]--------------------------------------------
443
444 #region [ InterpreterAction ]
445
446 public override V Evaluate(Argument[] arguments, RecursiveEval<T> eval,
447 InterpreterContext<T> context)
448 { return arguments.Aggregate(s, (x, y) => f(x, y.Value)); }
449
450 #endregion
451
452
453 }
454
455 //==<< ConvertAction >>======================================================
456
461 public sealed class ConvertAction<T, U, V> : InterpreterAction<T, V>
462 where T : class
463 {
464 private Func<U, V> f;
465
466 //--[ Constructors ]-------------------------------------------------
467
475 public ConvertAction(string name, Func<U, V> f, ArgumentType flags = ArgumentType.None)
476 : base(name, Tuple.Create(1, 1),
477 new[] { Defaults.TypeToArgType<T, U>() | (flags & ArgumentType.Flags) })
478 {
479 if (f == null) throw new ArgumentNullException("f");
480 this.f = f;
481 }
482
483 //--[ Overriden methods ]--------------------------------------------
484
485 #region [ InterpreterAction ]
486
487 public override V Evaluate(Argument[] arguments, RecursiveEval<T> eval,
488 InterpreterContext<T> context)
489 { return f((U) arguments[0].Data); }
490
491 #endregion
492
493 }
494
495 //==<< ConstantAction >>=====================================================
496
500 public sealed class ConstantAction<T, U> : InterpreterAction<T, U>
501 where T : class
502 {
503 private U value;
504
505 //--[ Constructors ]-------------------------------------------------
506
512 public ConstantAction(string name, U value)
513 : base(name, Tuple.Create(0, 0), new ArgumentType[0])
514 { this.value = value; }
515
516 //--[ Overriden methods ]--------------------------------------------
517
518 #region [ InterpreterAction ]
519
520 public override U Evaluate(Argument[] arguments, RecursiveEval<T> eval,
521 InterpreterContext<T> context)
522 { return value; }
523
524 #endregion
525
526 }
527
528 //==<< ArithmeticAction >>===================================================
529
539 public sealed class ArithmeticAction<T> : GenericAction<T>
540 where T : class
541 {
542 private Func<dynamic, dynamic, dynamic> f;
543
544 //--[ Constructors ]-------------------------------------------------
545
552 public ArithmeticAction(string name, Func<dynamic, dynamic, dynamic> f)
553 : base(name, Tuple.Create(2, int.MaxValue), new[] { ArgumentType.Integer | ArgumentType.Real })
554 {
555 if (f == null) throw new ArgumentNullException("f");
556 this.f = f;
557 }
558
559 //--[ Overriden methods ]--------------------------------------------
560
561 #region [ GenericAction ]
562
563 public override ArgumentType InferReturnType(ArgumentType expected, ArgumentType[] actual)
564 {
565 return actual.All(x => x.HasFlag(ArgumentType.Integer))
566 ? ArgumentType.Integer | ArgumentType.Real
567 : ArgumentType.Real;
568 }
569
570 public override object Invoke(Argument[] arguments, RecursiveEval<T> eval,
571 InterpreterContext<T> context)
572 {
573 try
574 {
575 dynamic val = arguments[0].Value;
576 for (int ix = 1; ix < arguments.Length; ++ix)
577 val = f(val, arguments[ix].Value);
578 return val;
579 } catch (ArithmeticException ex)
580 { throw new ErrorActionException(ex.Message); }
581 }
582
583 #endregion
584
585 }
586
587 //=============================================================================
588 // << Internal implementations >>
589 //=============================================================================
590
591 //==<< Join Action >>========================================================
592
593 internal class JoinAction<T> : InterpreterAction<T, string>
594 where T : class
595 {
596 //--[ Constructors ]-------------------------------------------------
597
598 public JoinAction()
599 : base("Join", Tuple.Create(1, int.MaxValue), new[] { ArgumentType.String, ArgumentType.Any })
600 { }
601
602 //--[ Overriden methods ]--------------------------------------------
603
604 #region [ InterpreterAction ]
605
606 public override string Evaluate(Argument[] arguments, RecursiveEval<T> eval,
607 InterpreterContext<T> context)
608 { return string.Join(arguments[0].Data as string, arguments.Skip(1).Select(x => x.Data.ToString())); }
609
610 #endregion
611
612 }
613
614 //==<< ConcatAction >>=======================================================
615
616 internal class ConcatAction<T> : InterpreterAction<T, string>
617 where T : class
618 {
619 //--[ Constructors ]-------------------------------------------------
620
621 public ConcatAction()
622 : base("Concat", Tuple.Create(0, int.MaxValue), new[] { ArgumentType.Any })
623 { }
624
625 //--[ Overriden methods ]--------------------------------------------
626
627 #region [ InterpreterAction ]
628
629 public override string Evaluate(Argument[] arguments, RecursiveEval<T> eval,
630 InterpreterContext<T> context)
631 { return string.Concat(arguments.Select(x => x.Data.ToString())); }
632
633 #endregion
634
635 }
636
637 //==<< FlattenAction >>======================================================
638
639 internal class FlattenAction<T> : InterpreterAction<T, string>
640 where T : class
641 {
642 //--[ Constructors ]-------------------------------------------------
643
644 public FlattenAction()
645 : base("Flatten", Tuple.Create(1, 2), new[] { ArgumentType.Tree, ArgumentType.Integer })
646 { }
647
648 //--[ Overriden methods ]--------------------------------------------
649
650 #region [ InterpreterAction ]
651
652 public override string Evaluate(Argument[] arguments, RecursiveEval<T> eval,
653 InterpreterContext<T> context)
654 {
655 int maxdepth = arguments.Length == 1 ? -1 : arguments[1].Value;
656 return (arguments[0].Data as Tree<Symbol>).ToString(maxdepth);
657 }
658
659 #endregion
660
661 }
662
663 //==<< SubTreeAction >>======================================================
664
665 internal class SubTreeAction<T> : InterpreterAction<T, Tree<Symbol>>
666 where T : class
667 {
668 //--[ Constructors ]-------------------------------------------------
669
670 public SubTreeAction()
671 : base("SubTree", Tuple.Create(2, 2),
672 new[] { ArgumentType.Integer, ArgumentType.Tree })
673 { }
674
675 //--[ Overriden methods ]--------------------------------------------
676
677 #region [ InterpreterAction ]
678
679 public override Tree<Symbol> Evaluate(Argument[] arguments, RecursiveEval<T> eval,
680 InterpreterContext<T> context)
681 {
682 int ix = arguments[0].Value;
683 var tr = arguments[1].Data as Tree<Symbol>;
684
685 return (0 > ix || ix >= tr.Children.Count) ? null : tr[ix];
686 }
687
688 #endregion
689
690 }
691
692 //==<< IdentityAction >>=====================================================
693
694 internal class IdentityAction<T> : GenericAction<T>
695 where T : class
696 {
697 //--[ Constructors ]-------------------------------------------------
698
699 public IdentityAction()
700 : base("Identity", Tuple.Create(1, 1), new[] { ArgumentType.Any })
701 { }
702
703 //--[ Overriden methods ]--------------------------------------------
704
705 #region [ GenericAction ]
706
707 public override ArgumentType InferReturnType(ArgumentType expected, ArgumentType[] actual)
708 { return actual[0] & expected; }
709
710 public override object Invoke(Argument[] arguments, RecursiveEval<T> eval,
711 InterpreterContext<T> context)
712 { return arguments[0].Data; }
713
714 #endregion
715
716 }
717
718 //==<< LetAction >>==========================================================
719
720 internal class LetAction<T> : GenericAction<T>
721 where T : class
722 {
723 //--[ Constructors ]-------------------------------------------------
724
725 public LetAction()
726 : base("Let", Tuple.Create(3, int.MaxValue),
727 new[] { ArgumentType.Any | ArgumentType.Lazy }, false)
728 { }
729
730 //--[ Overriden methods ]--------------------------------------------
731
732 #region [ GenericAction ]
733
734 public override ArgumentType InferReturnType(ArgumentType expected, ArgumentType[] actual)
735 {
736 if (actual.Length % 2 != 1) return ArgumentType.None;
737
738 for (int ix = 0; ix < actual.Length - 2; ix += 2)
739 if (!actual[ix].HasFlag(ArgumentType.String)) return ArgumentType.None;
740
741 return actual[actual.Length - 1];
742 }
743
744 public override object Invoke(Argument[] arguments, RecursiveEval<T> eval,
745 InterpreterContext<T> context)
746 {
747 for (int ix = 0; ix < arguments.Length - 2; ix += 2)
748 {
749 var name = arguments[ix].Data as string;
750
751 if (context.bindings.ContainsKey(name))
752 throw new ErrorActionException("multiple bindings of variable '{0}'", name);
753
754 context.bindings.Add(name, arguments[ix + 1]);
755 }
756
757 context.LogEntry("{0} values binded", arguments.Length / 2);
758 return arguments[arguments.Length - 1].Data;
759 }
760
761 #endregion
762
763 }
764
765 //==<< VarAction >>==========================================================
766
767 internal class VarAction<T> : InterpreterAction<T, object>
768 where T : class
769 {
770 //--[ Constructors ]-------------------------------------------------
771
772 public VarAction()
773 : base("Var", Tuple.Create(1, 1), new[] { ArgumentType.String })
774 { }
775
776 //--[ Overriden methods ]--------------------------------------------
777
778 #region [ InterpreterAction ]
779
780 public override object Evaluate(Argument[] arguments, RecursiveEval<T> eval,
781 InterpreterContext<T> context)
782 {
783 var name = arguments[0].Data as string;
784 Argument bval;
785
786 if (!context.bindings.TryGetValue(name, out bval))
787 throw new ErrorActionException("variable '{0}' binding does not exist", name);
788
789 if ((bval.Type & context.reqtp) == ArgumentType.None)
790 throw new ErrorActionException("runtime type check error in the binding of '{0}'", name);
791
792 context.LogEntry("value of {0} fetched", name);
793 return bval.Data;
794 }
795
796 #endregion
797
798 }
799
800 //==<< TryAction >>==========================================================
801
802 internal class TryAction<T> : GenericAction<T>
803 where T : class
804 {
805 //--[ Constructors ]-------------------------------------------------
806
807 public TryAction()
808 : base("Try", Tuple.Create(1, 2), new[] { ArgumentType.Any | ArgumentType.Lazy })
809 { }
810
811 //--[ Overriden methods ]--------------------------------------------
812
813 #region [ GenericAction ]
814
815 public override ArgumentType InferReturnType(ArgumentType expected, ArgumentType[] actual)
816 { return (actual.Length == 1 ? actual[0] : actual[0] & actual[1]) & expected; }
817
818 public override object Invoke(Argument[] arguments, RecursiveEval<T> eval,
819 InterpreterContext<T> context)
820 {
821 try
822 { return arguments[0].Data; }
823 catch (ErrorActionException ex)
824 {
825 context.LogEntryEx("EXCEPTION", "'{0}' caught in '{1}'",
826 ex.Message, context.action);
827 return arguments.Length == 2 ? arguments[1].Data : null;
828 }
829 }
830
831 #endregion
832
833 }
834
835 //==<< IfAction >>===========================================================
836
837 internal class IfAction<T> : GenericAction<T>
838 where T : class
839 {
840 //--[ Constructors ]-------------------------------------------------
841
842 public IfAction()
843 : base("If", Tuple.Create(3, int.MaxValue),
844 new[] { ArgumentType.Any | ArgumentType.Lazy }, false)
845 { }
846
847 //--[ Overriden methods ]--------------------------------------------
848
849 #region [ GenericAction ]
850
851 public override ArgumentType InferReturnType(ArgumentType expected, ArgumentType[] actual)
852 {
853 if (actual.Length % 2 != 1) return ArgumentType.None;
854
855 ArgumentType argtp = ArgumentType.Any;
856 for(int ix = 0; ix < actual.Length - 1; ix += 2)
857 {
858 if (!(actual[ix] & ArgumentType.Any).HasFlag(ArgumentType.Boolean))
859 return ArgumentType.None;
860 argtp &= actual[ix + 1];
861 }
862
863 return (argtp & actual[actual.Length - 1]) & expected;
864 }
865
866 public override object Invoke(Argument[] arguments, RecursiveEval<T> eval,
867 InterpreterContext<T> context)
868 {
869 for (int ix = 0; ix < arguments.Length - 1; ix += 2)
870 if ((arguments[ix].Data != null) && arguments[ix].Value)
871 return arguments[ix + 1].Data;
872
873 return arguments[arguments.Length - 1].Data;
874 }
875
876 #endregion
877
878 }
879
880 //==<< SelectAction >>=======================================================
881
882 internal class SelectAction<T> : GenericAction<T>
883 where T : class
884 {
885 //--[ Constructors ]-------------------------------------------------
886
887 public SelectAction()
888 : base("Select", Tuple.Create(2, int.MaxValue),
889 new[] { ArgumentType.Integer, ArgumentType.Any | ArgumentType.Lazy })
890 { }
891
892 //--[ Overriden methods ]--------------------------------------------
893
894 #region [ GenericAction ]
895
896 public override ArgumentType InferReturnType(ArgumentType expected, ArgumentType[] actual)
897 { return actual.Skip(2).Aggregate(actual[1], (x, y) => x & y) & expected; }
898
899 public override object Invoke(Argument[] arguments, RecursiveEval<T> eval,
900 InterpreterContext<T> context)
901 {
902 int ix = arguments[0].Value;
903 context.LogEntry("selector value is '{0}'", ix);
904 return ((0 > ix) || (ix >= arguments.Length - 2)) ? arguments[1].Value : arguments[ix + 2].Data;
905 }
906
907 #endregion
908
909 }
910
911 //==<< CaseAction >>=========================================================
912
913 internal class CaseAction<T> : GenericAction<T>
914 where T : class
915 {
916 //--[ Constructors ]-------------------------------------------------
917
918 public CaseAction()
919 : base("Case", Tuple.Create(2, int.MaxValue),
920 new[] { ArgumentType.Any, ArgumentType.Any | ArgumentType.Lazy },
921 false)
922 { }
923
924 //--[ Interface implementation ]-------------------------------------
925
926 #region [ GenericAction ]
927
928 public override ArgumentType InferReturnType(ArgumentType expected, ArgumentType[] actual)
929 {
930 if ((actual.Length % 2) == 1)
931 return ArgumentType.None;
932
933 ArgumentType valtp = ArgumentType.Any;
934 ArgumentType restp = ArgumentType.Any;
935
936 for (int ix = 0; ix < actual.Length; ix += 2)
937 {
938 valtp &= actual[ix];
939 restp &= actual[ix + 1];
940 }
941
942 return (valtp == ArgumentType.None) ? ArgumentType.None : restp & expected;
943 }
944
945 public override object Invoke(Argument[] arguments, RecursiveEval<T> eval,
946 InterpreterContext<T> context)
947 {
948 var val = arguments[0].Data;
949 context.LogEntry("selector value is '{0}'", val ?? "null");
950
951 if (val != null)
952 {
953 for (int ix = 2; ix < arguments.Length; ix += 2)
954 if (val.Equals(arguments[ix].Data)) return arguments[ix + 1].Data;
955 }
956
957 return arguments[1].Data;
958 }
959
960 #endregion
961
962 }
963
964 //==<< ArgsCountAction >>====================================================
965
966 internal class ArgsCountAction<T> : InterpreterAction<T, int>
967 where T : class
968 {
969
970 //--[ Constructors ]-------------------------------------------------
971
972 public ArgsCountAction()
973 : base("ArgsCount", Tuple.Create(0, int.MaxValue), new[] { ArgumentType.Any | ArgumentType.Lazy })
974 { }
975
976 //--[ Overriden methods ]--------------------------------------------
977
978 #region [ InterpreterAction ]
979
980 public override int Evaluate(Argument[] arguments, RecursiveEval<T> eval,
981 InterpreterContext<T> context)
982 { return arguments.Length; }
983
984 #endregion
985
986 }
987
988 //==<< EvaluateAction >>=====================================================
989
990 internal class EvaluateAction<T> : InterpreterAction<T, T>
991 where T : class
992 {
993 //--[ Constructors ]-------------------------------------------------
994
995 public EvaluateAction()
996 : base("Eval", Tuple.Create(1, 1), new[] { ArgumentType.Tree })
997 { }
998
999 //--[ Overriden methods ]--------------------------------------------
1000
1001 #region [ InterpreterAction ]
1002
1003 public override T Evaluate(Argument[] arguments, RecursiveEval<T> eval,
1004 InterpreterContext<T> context)
1005 { return eval(arguments[0].Data as Tree<Symbol>, context); }
1006
1007 #endregion
1008
1009 }
1010
1011 //==<< FailAction >>========================================================
1012
1013 internal class FailAction<T> : GenericAction<T>
1014 where T : class
1015 {
1016 //--[ Constructors ]-------------------------------------------------
1017
1018 public FailAction()
1019 : base("Fail", Tuple.Create(0, 0), new ArgumentType[0])
1020 { }
1021
1022 //--[ Overriden methods ]--------------------------------------------
1023
1024 #region [ GenericAction ]
1025
1026 public override ArgumentType InferReturnType(ArgumentType expected, ArgumentType[] actual)
1027 { return expected; }
1028
1029 public override object Invoke(Argument[] arguments, RecursiveEval<T> eval, InterpreterContext<T> context)
1030 { return null; }
1031
1032 #endregion
1033
1034 }
1035
1036 //==<< SimpleAction >>=======================================================
1037
1038 internal class SimpleAction<T> : InterpreterAction<T, T>
1039 where T : class
1040 {
1041 //--[ Constructors ]-------------------------------------------------
1042
1046 public SimpleAction()
1047 : base("Simple", Tuple.Create(1, 1), new[] { ArgumentType.Tree })
1048 { }
1049
1050 //--[ Overriden methods ]--------------------------------------------
1051
1052 #region [ InterpreterAction ]
1053
1054 public override T Evaluate(Argument[] arguments, RecursiveEval<T> eval,
1055 InterpreterContext<T> context)
1056 {
1057 var val = arguments[0].Data as Tree<Symbol>;
1058 if ((val.Children.Count != 1) || (val.Children[0].Value.Type != SymbolType.Nonterminal))
1059 return null;
1060
1061 return eval(val.Children[0], context);
1062 }
1063
1064 #endregion
1065
1066 }
1067
1068 //==<< TraceAction >>========================================================
1069
1070 internal class TraceAction<T> : GenericAction<T>
1071 where T : class
1072 {
1073 //--[ Private fields ]-----------------------------------------------
1074
1075 private TextWriter writer;
1076
1077 //--[ Constructors ]-------------------------------------------------
1078
1079 public TraceAction()
1080 : this(null)
1081 { }
1082
1083 public TraceAction(TextWriter writer)
1084 : base("Trace", Tuple.Create(2, int.MaxValue),
1085 new[] { ArgumentType.Any | ArgumentType.Lazy, ArgumentType.String, ArgumentType.Any })
1086 { this.writer = writer; }
1087
1088 //--[ Overriden methods ]--------------------------------------------
1089
1090 #region [ GenericAction ]
1091
1092 public override ArgumentType InferReturnType(ArgumentType expected, ArgumentType[] actual)
1093 { return actual[0] & expected; }
1094
1095 public override object Invoke(Argument[] arguments, RecursiveEval<T> eval,
1096 InterpreterContext<T> context)
1097 {
1098 var value = arguments[0].Value; // forces evaluation
1099 var msgc = string.Format(arguments[1].Value.ToString(), arguments.Skip(2).Select(x => x.Value.ToString()).ToArray());
1100 var msg = string.Format("{0} <ret {1}>", msgc, value == null ? "null" : "value");
1101
1102 context.LogEntryEx("TRACE", msg);
1103 if (writer != null) writer.Write(msg);
1104
1105 return value;
1106 }
1107
1108 #endregion
1109
1110 }
1111
1112
1113 }
Mercury.Interpreting.ArithmeticAction< T >.ArithmeticAction
ArithmeticAction(string name, Func< dynamic, dynamic, dynamic > f)
Initializes a new instance of the ArithmeticAction{T} class.
Definition: BasicActions.cs:552
Mercury.Interpreting.ConvertAction< T, U, V >.Evaluate
override V Evaluate(Argument[] arguments, RecursiveEval< T > eval, InterpreterContext< T > context)
Evaluates the action.
Definition: BasicActions.cs:487
Mercury.Interpreting.RecursiveEval< T >
delegate T RecursiveEval< T >(Tree< Symbol > tree, InterpreterContext< T > context)
Delegate type for recursive evaluation (interpretation)
Mercury.Exceptions.ErrorActionException
Exception thrown by basic actions when a problem was encountered.
Definition: InterpretingExceptions.cs:178
Mercury.Interpreting.ArithmeticAction< T >
Represents the arithmetic action. It is similar to the Mercury.Interpreting.FoldingAction{T,U,V} but does not require initial value. The minimal number of arguments is therefore 2. For instance, "1 2 3" would be evaluated as f(f(1, 2), 3)
Definition: BasicActions.cs:539
Mercury.Interpreting.ArgumentType
ArgumentType
Defines argument types using in the Mercury library
Definition: Argument.cs:11
Mercury.Interpreting.BasicActions< T >.GetAliases
static IReadOnlyDictionary< string, string > GetAliases()
Returns aliases for basic actions. It contains the following aliases:
Definition: BasicActions.cs:332
Mercury.Interpreting.ArithmeticAction< T >.Invoke
override object Invoke(Argument[] arguments, RecursiveEval< T > eval, InterpreterContext< T > context)
Evaluates the arguments. It is guaranteed to have a valid number of arguments (specified by Arity) a...
Definition: BasicActions.cs:570
Mercury.Interpreting.InterpreterAction< T >
Function that wraps constant values in the RHS
Definition: InterpreterAction.cs:46
Mercury.Syntax.SymbolType
SymbolType
Represents a type of symbol. Implemented as Flags since Symbol type inference is ambiguous.
Definition: Symbol.cs:16
Mercury.Interpreting.OperationAction< T, U, V >.OperationAction
OperationAction(string name, Func< U, U, V > f, ArgumentType flags=ArgumentType.None)
Initializes a new instance of the OperationAction{T, U, V} class.
Definition: BasicActions.cs:383
Mercury.Interpreting.FoldingAction< T, U, V >.Evaluate
override V Evaluate(Argument[] arguments, RecursiveEval< T > eval, InterpreterContext< T > context)
Evaluates the action.
Definition: BasicActions.cs:446
Mercury.Interpreting.Argument
Represents an argument passed to the Mercury.Interpreting.InterpreterAction{T}, the actual parameter ...
Definition: Argument.cs:58
Mercury.Interpreting.ConstantAction< T, U >.Evaluate
override U Evaluate(Argument[] arguments, RecursiveEval< T > eval, InterpreterContext< T > context)
Evaluates the action.
Definition: BasicActions.cs:520
Mercury.Interpreting.BasicActions< T >.GetAllActions
static IReadOnlyList< InterpreterAction< T > > GetAllActions()
Provides basic Mercury actions
Definition: BasicActions.cs:304
Mercury.Interpreting.ConstantAction< T, U >.ConstantAction
ConstantAction(string name, U value)
Initializes a new instance of the ConstantAction{T, U} class.
Definition: BasicActions.cs:512
Mercury.Interpreting.OperationAction< T, U, V >.Evaluate
override V Evaluate(Argument[] arguments, RecursiveEval< T > eval, InterpreterContext< T > context)
Evaluates the action.
Definition: BasicActions.cs:395
Mercury.Interpreting.InterpreterContext< T >
Interpreter Context class. Some languages may use it to override it and remember data when parse tree...
Definition: InterpreterContext.cs:18
Mercury.Interpreting.String
String value
Mercury.Syntax.Symbol
Represents a single symbol of the grammar. This is an immutable class. For a symbol name to be val...
Definition: Symbol.cs:51
Mercury.Interpreting.BasicActions< T >.CreateTracer
static InterpreterAction< T > CreateTracer(string name, TextWriter writer)
Creates custom trace action with stream, useful for logging.
Definition: BasicActions.cs:352
Mercury.Interpreting.FoldingAction< T, U, V >.FoldingAction
FoldingAction(string name, int minargs, Func< V, U, V > f, V seed, ArgumentType flags=ArgumentType.None)
Initializes a new instance of the FoldingAction{T, U, V} class.
Definition: BasicActions.cs:432
Mercury.Interpreting.ConvertAction< T, U, V >.ConvertAction
ConvertAction(string name, Func< U, V > f, ArgumentType flags=ArgumentType.None)
Initializes a new instance of the ConvertAction{T, U, V} class.
Definition: BasicActions.cs:475
Mercury.Interpreting.ArithmeticAction< T >.InferReturnType
override ArgumentType InferReturnType(ArgumentType expected, ArgumentType[] actual)
Infers the actual return type from provided parameter types
Definition: BasicActions.cs:563