Mercury library  1.0
Translation of CFG grammars into an object model (Bachelor's thesis).
 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 }
ArithmeticAction(string name, Func< dynamic, dynamic, dynamic > f)
Initializes a new instance of the ArithmeticAction{T} class.
override V Evaluate(Argument[] arguments, RecursiveEval< T > eval, InterpreterContext< T > context)
Evaluates the action.
delegate T RecursiveEval< T >(Tree< Symbol > tree, InterpreterContext< T > context)
Delegate type for recursive evaluation (interpretation)
Exception thrown by basic actions when a problem was encountered.
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)
ArgumentType
Defines argument types using in the Mercury library
Definition: Argument.cs:11
static IReadOnlyDictionary< string, string > GetAliases()
Returns aliases for basic actions. It contains the following aliases:
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...
Function that wraps constant values in the RHS
SymbolType
Represents a type of symbol. Implemented as Flags since Symbol type inference is ambiguous.
Definition: Symbol.cs:16
OperationAction(string name, Func< U, U, V > f, ArgumentType flags=ArgumentType.None)
Initializes a new instance of the OperationAction{T, U, V} class.
override V Evaluate(Argument[] arguments, RecursiveEval< T > eval, InterpreterContext< T > context)
Evaluates the action.
Represents an argument passed to the Mercury.Interpreting.InterpreterAction{T}, the actual parameter ...
Definition: Argument.cs:58
override U Evaluate(Argument[] arguments, RecursiveEval< T > eval, InterpreterContext< T > context)
Evaluates the action.
static IReadOnlyList< InterpreterAction< T > > GetAllActions()
Provides basic Mercury actions
ConstantAction(string name, U value)
Initializes a new instance of the ConstantAction{T, U} class.
override V Evaluate(Argument[] arguments, RecursiveEval< T > eval, InterpreterContext< T > context)
Evaluates the action.
Interpreter Context class. Some languages may use it to override it and remember data when parse tree...
Represents a single symbol of the grammar. This is an immutable class. For a symbol name to be val...
Definition: Symbol.cs:51
static InterpreterAction< T > CreateTracer(string name, TextWriter writer)
Creates custom trace action with stream, useful for logging.
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.
ConvertAction(string name, Func< U, V > f, ArgumentType flags=ArgumentType.None)
Initializes a new instance of the ConvertAction{T, U, V} class.
override ArgumentType InferReturnType(ArgumentType expected, ArgumentType[] actual)
Infers the actual return type from provided parameter types