otp.net /Otp/Erlang/PatternMatcher.cs

Language C# Lines 211
MD5 Hash 7d598d8790b58d633559b9803b7ad56f Estimated Cost $2,890 (why?)
Repository https://github.com/saleyn/otp.net.git View Raw File View Project SPDX
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using ErlObject = Otp.Erlang.Object;
using ErlVarBind = Otp.Erlang.VarBind;

namespace Otp.Erlang
{
    public delegate void PatternMatchAction(
        PatternMatcher.Pattern pattern, ErlObject term,
        ErlVarBind binding, params object[] args);

    public delegate void PatternMatchAction<TContext>(
        TContext ctx, PatternMatcher.Pattern pattern, ErlObject term,
        ErlVarBind binding, params object[] args);

    public delegate void PatternMatchAction<TContext, TErlTerm>(
        TContext ctx, PatternMatcher.Pattern pattern, TErlTerm term,
        ErlVarBind binding, params object[] args) where TErlTerm : ErlObject;

    /// <summary>
    /// Pattern matcher that implements a container of patterns to be
    /// matched against a given Erlang term.  On successful match, the
    /// corresponding action registered with that pattern gets invoked
    /// </summary>
    public class PatternMatcher : IEnumerable<PatternMatcher.Pattern>
    {
        #region Local Classes

            public struct Pattern
            {
                public readonly int                 ID;
                public readonly PatternMatchAction  Action;
                public readonly Erlang.Object       Term;

                public Pattern(int id, PatternMatchAction b, Erlang.Object p)
                {
                    ID = id; Action = b; Term = p;
                }

                public Pattern(int id, PatternMatchAction b, string pattern, params object[] args)
                {
                    ID = id; Action = b; Term = Object.Format(pattern, args);
                }
            }

        #endregion

        #region Fields

            List<Pattern>  m_patterns = new List<Pattern>();
            int            m_lastID   = 0;

        #endregion

        #region Public

            /// <summary>
            /// Add a matching pattern to the collection
            /// </summary>
            /// <param name="pattern">Pattern to compile</param>
            /// <param name="action">Action to invoke on successful match</param>
            /// <returns>ID of the newly added pattern</returns>
            public int Add(string pattern, PatternMatchAction action)
            {
                return Add(ErlObject.Format(pattern), action);
            }

            /// <summary>
            /// Add a matching pattern to the collection
            /// </summary>
            /// <param name="pattern">Pattern to compile</param>
            /// <param name="action">Action to invoke on successful match</param>
            /// <param name="args">Arguments used in the pattern</param>
            /// <returns>ID of the newly added pattern</returns>
            public int Add<TErlTerm>(TErlTerm pattern, PatternMatchAction action) where TErlTerm : ErlObject
            {
                int id = ++m_lastID;
                var pt = new Pattern(id, (p, t, b, args) => action(p, t.Cast<TErlTerm>(), b, args), pattern);
                m_patterns.Add(pt);
                return id;
            }

            /// <summary>
            /// Add a matching pattern to the collection
            /// </summary>
            /// <typeparam name="TContext">Type of context passed to action</typeparam>
            /// <param name="context">Context passed to action</param>
            /// <param name="pattern">Pattern to compile</param>
            /// <param name="action">Action to invoke on successful match</param>
            /// <returns>ID of the newly added pattern</returns>
            public int Add<TContext>(TContext context, string pattern, PatternMatchAction<TContext> action)
            {
                return Add(context, ErlObject.Format(pattern), action);
            }

            /// <summary>
            /// Add a matching pattern to the collection
            /// </summary>
            /// <typeparam name="TContext">Type of context passed to action</typeparam>
            /// <param name="context">Context passed to action</param>
            /// <param name="pattern">Pattern to compile</param>
            /// <param name="action">Action to invoke on successful match</param>
            /// <returns>ID of the newly added pattern</returns>
            public int Add<TContext, TErlTerm>(TContext context, string pattern,
                PatternMatchAction<TContext, TErlTerm> action
            ) where TErlTerm : ErlObject
            {
                return Add(context, ErlObject.Format(pattern).Cast<TErlTerm>(), action);
            }

            /// <summary>
            /// Add a matching pattern to the collection
            /// </summary>
            /// <typeparam name="TContext">Type of context passed to action</typeparam>
            /// <param name="context">Context passed to action</param>
            /// <param name="action">Action to invoke on successful match</param>
            /// <param name="pattern">Compiled pattern containing variables to match</param>
            /// <returns>ID of the newly added pattern</returns>
            public int Add<TContext>(TContext context, ErlObject pattern, PatternMatchAction<TContext> action)
            {
                int id = ++m_lastID;
                var pt = new Pattern(id, (p, t, b, args) => action(context, p, t, b, args), pattern);
                m_patterns.Add(pt);
                return id;
            }

            /// <summary>
            /// Add a matching pattern to the collection
            /// </summary>
            /// <typeparam name="TContext">Type of context passed to action</typeparam>
            /// <param name="context">Context passed to action</param>
            /// <param name="action">Action to invoke on successful match</param>
            /// <param name="pattern">Compiled pattern containing variables to match</param>
            /// <returns>ID of the newly added pattern</returns>
            public int Add<TContext, TErlTerm>(
                TContext context,
                TErlTerm pattern,
                PatternMatchAction<TContext, TErlTerm> action) where TErlTerm : ErlObject
            {
                int id = ++m_lastID;
                var pt = new Pattern(id, (p, t, b, args) => action(context, p, t.Cast<TErlTerm>(), b, args), pattern);
                m_patterns.Add(pt);
                return id;
            }

            /// <summary>
            /// Remove pattern from collection given its ID
            /// </summary>
            public void Remove(int id)
            {
                int i = m_patterns.FindIndex(d => d.ID == id);

                if (i != -1)
                    m_patterns.RemoveAt(i);
            }

            /// <summary>
            /// Match a term against the patterns in the collection.
            /// The first successful match will result in invokation of the action
            /// associated with the pattern
            /// </summary>
            /// <param name="term">Term to match against patterns</param>
            /// <returns>ID of the pattern that matched, or -1 if there were no matches</returns>
            public int Match<TErlTerm>(TErlTerm term, params object[] args) where TErlTerm : ErlObject
            {
                var binding = new VarBind();

                foreach (var p in m_patterns)
                {
                    if (p.Term.match(term, binding))
                    {
                        p.Action(p, term, binding, args);
                        return p.ID;
                    }
                    binding.clear();
                }

                return -1;
            }

            /// <summary>
            /// Clear the collection of patterns
            /// </summary>
            public void Clear()
            {
                m_patterns.Clear();
            }

            public string PatternsToString
            {
                get { return (new Erlang.List(m_patterns.Select(p => p.Term).ToArray())).ToString(); }
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return m_patterns.GetEnumerator();
            }

            IEnumerator<Pattern> IEnumerable<PatternMatcher.Pattern>.GetEnumerator()
            {
                return m_patterns.GetEnumerator();
            }

        #endregion
    }
}
Back to Top