Exemple #1
0
        public void ErlPatternMatchCollectionTest()
        {
            var state = new KVP();

            var pm = new ErlPatternMatcher
            {
                { 0, "{A::integer(), stop}", (_ctx, p, t, b, _args) => { state = new KVP(p, b); return(t); } },
                { "{A::integer(), status}", (p, t, b, _args) => { state = new KVP(p, b); return(t); } },
                { 1, "{A::integer(), {status, B::atom()}}", (_ctx, p, t, b, _args) => { state = new KVP(p, b); return(t); } },
                { "{A::integer(), {config, B::list()}}", (p, t, b, _args) => { state = new KVP(p, b); return(t); } }
            };

            var term = ErlObject.Parse("{10, stop}");

            Assert.AreEqual(1, pm.Match(ref term));
            Assert.AreEqual(10, state.Value["A"].ValueAsInt);

            term = ErlObject.Parse("{11, status}");
            Assert.AreEqual(2, pm.Match(ref term));
            Assert.AreEqual(11, state.Value["A"].ValueAsInt);

            term = ErlObject.Parse("{12, {status, ~w}}", new ErlAtom("a"));
            Assert.AreEqual(3, pm.Match(ref term));
            Assert.AreEqual(12, state.Value["A"].ValueAsInt);
            Assert.AreEqual("a", state.Value["B"].ValueAsString);

            term = ErlObject.Parse("{13, {config, ~w}}", new ErlList());
            Assert.AreEqual(4, pm.Match(ref term));
            Assert.AreEqual(13, state.Value["A"].ValueAsInt);
            Assert.AreEqual(0, (state.Value["B"] as ErlList).Count);

            term = ErlObject.Parse("{10, exit}");
            Assert.AreEqual(-1, pm.Match(ref term));

            var pts = pm.PatternsToString;

            Assert.AreEqual(
                "[{A::int(),stop},{A::int(),status},{A::int(),{status,B::atom()}},{A::int(),{config,B::list()}}]",
                pts);
        }
Exemple #2
0
 private IErlObject ioProcessRequests(
     ErlPatternMatcher pm, ErlList requests, IErlObject replyAs)
 {
     foreach (var r in requests)
     {
         IErlObject term = r;
         if (pm.Match(ref term, replyAs) < 0)
         {
             return(term);
         }
     }
     return(s_ReplyPattern.Subst(
                new ErlVarBind {
         { RA, replyAs },
         { R, (IErlObject)Tuple.Create(ConstAtoms.Error, ConstAtoms.Request) }
     }));
 }
Exemple #3
0
    /// <summary>
    /// Receive a message and match it against a given pattern
    /// </summary>
    /// <param name="pm">Patterns to match the message against</param>
    /// <param name="timeoutMsec">Timeout in milliseconds</param>
    /// <returns>Return a tuple containing the received message and index of the
    /// pattern in the pm instance that was successfully matched.
    /// On timeout the 2nd element of the tuple is -2 and 1st element of the tuple is null.
    /// On unsuccessful match the second element of the tuple is -1</returns>
    public Tuple<IErlObject, int> ReceiveMatch(ErlPatternMatcher pm, int timeoutMsec = -1)
    {
      var m = Receive(timeoutMsec);
      if (m == null) return Tuple.Create<IErlObject, int>(null, -2);

      int n = pm.Match(ref m);
      return Tuple.Create(m, n);
    }
Exemple #4
0
    private void threadSpinCore()
    {
      // For Erlang I/O protocol see:
      // http://erlang.org/doc/apps/stdlib/io_protocol.html

      var patterns = new ErlPatternMatcher
                {
                    {"{put_chars, ~v::atom(), ~v::string()}".ErlArgs(E, C),
                        (_p, _t, b, a) => ioProcessPutChars(
                            b.Cast<ErlAtom>(E), b.Cast<ErlString>(C), (IErlObject)a[1]) },
                    {"{put_chars, ~v::atom(), ~v::atom(), ~v::atom(), ~v::list()}".ErlArgs(E,M,F,A),
                        (_p, _t, b, a) => ioProcessPutChars(
                            b.Cast<ErlAtom>(E), b.Cast<ErlAtom>(M),
                            b.Cast<ErlAtom>(F), b.Cast<ErlList>(A),
                            (IErlObject)a[1]) },
                    {"{put_chars, ~v::string()}".ErlArgs(C),
                        (_p, _t, b, a) => ioProcessPutChars(
                            ConstAtoms.Latin1, b.Cast<ErlString>(C), (IErlObject)a[1]) },
                    {"{put_chars, ~v::atom(), ~v::atom(), ~v::list()}".ErlArgs(M,F,A),
                        (_p, _t, b, a) => ioProcessPutChars(
                            ConstAtoms.Latin1, b.Cast<ErlAtom>(M),
                            b.Cast<ErlAtom>(F), b.Cast<ErlList>(A),
                            (IErlObject)a[1]) },
                    {"{get_until, ~v::atom(), ~v, ~v::atom(), ~v::atom(), ~v::list()}".ErlArgs(E,P,M,F,A),
                        (_p, _t, b, a) => ioProcessGetUntil(
                            b.Cast<ErlAtom>(E), b[P], b.Cast<ErlAtom>(M), b.Cast<ErlAtom>(F),
                            b.Cast<ErlList>(A), (IErlObject)a[1]) },
                    {"{get_chars, ~v::atom(), ~v, ~v::integer()}".ErlArgs(E,P,N),
                        (_p, _t, b, a) => ioProcessGetChars(
                            b.Cast<ErlAtom>(E), b[P], b.Cast<ErlLong>(N), (IErlObject)a[1]) },
                    {"{get_line, ~v::atom(), ~v}".ErlArgs(E,P),
                        (_p, _t, b, a) => ioProcessGetLine(
                            b.Cast<ErlAtom>(E), b[P], (IErlObject)a[1]) },
                    {"{get_until, ~v, ~v::atom(), ~v::atom(), ~v::list()}".ErlArgs(P,M,F,A),
                        (_p, _t, b, a) => ioProcessGetUntil(
                            ConstAtoms.Latin1, b[P], b.Cast<ErlAtom>(M), b.Cast<ErlAtom>(F),
                            b.Cast<ErlList>(A), (IErlObject)a[1]) },
                    {"{get_chars, ~v, ~v::integer()}".ErlArgs(P,N),
                        (_p, _t, b, a) => ioProcessGetChars(
                            ConstAtoms.Latin1, b[P], b.Cast<ErlLong>(N), (IErlObject)a[1]) },
                    {"{get_line, ~v}".ErlArgs(P),
                        (_p, _t, b, a) => ioProcessGetLine(
                            ConstAtoms.Latin1, b[P], (IErlObject)a[1]) },
                    {"{requests, ~v::list()}".ErlArgs(R),
                        (_p, _t, b, a) => ioProcessRequests(
                            (ErlPatternMatcher)a[0], b.Cast<ErlList>(R), (IErlObject)a[1]) },
                };

      while (m_Active)
      {
        Tuple<IErlObject, ErlVarBind> res = Node.GroupLeader.ReceiveMatch(s_RequestPattern, 1500);

        if (res.Item1 == null) // Timeout
          continue;
        else if (res.Item2 == null) // No match
          App.Log.Write(Log.MessageType.Error,
              StringConsts.ERL_INVALID_IO_REQUEST + res.Item1.ToString(), from: GetType().Name);

        var from = res.Item2.Cast<ErlPid>(F);
        var replyAs = res.Item2[RA];
        var request = res.Item2.Cast<ErlTuple>(R);
        var req = (IErlObject)request;

        if (patterns.Match(ref req, patterns, replyAs) >= 0)
        {
          Node.Send(from, req);
          continue;
        }

        var reply = s_ReplyPattern.Subst(new ErlVarBind { { RA, replyAs }, { R, ConstAtoms.Request } });

        Debug.Assert(reply != null);
        Node.Send(from, reply);
      }

      App.Log.Write(Log.MessageType.Info, StringConsts.ERL_STOPPING_SERVER.Args(Node.NodeLongName, "I/O"));

      m_Thread = null;
    }
Exemple #5
0
    private IErlObject ioProcessRequests(
        ErlPatternMatcher pm, ErlList requests, IErlObject replyAs)
    {

      foreach (var r in requests)
      {
        IErlObject term = r;
        if (pm.Match(ref term, replyAs) < 0)
          return term;
      }
      return s_ReplyPattern.Subst(
          new ErlVarBind{
                        {RA, replyAs},
                        {R, (IErlObject)Tuple.Create(ConstAtoms.Error, ConstAtoms.Request)
                    }});
    }
Exemple #6
0
        private void startIO(object obj)
        {
            // For Erlang I/O protocol see:
            // http://erlang.org/doc/apps/stdlib/io_protocol.html

            var patterns = new ErlPatternMatcher
            {
                { "{put_chars, ~v::atom(), ~v::string()}".ErlArgs(E, C),
                  (_p, _t, b, a) => ioProcessPutChars(
                      b.Cast <ErlAtom>(E), b.Cast <ErlString>(C), (IErlObject)a[1]) },
                { "{put_chars, ~v::atom(), ~v::atom(), ~v::atom(), ~v::list()}".ErlArgs(E, M, F, A),
                  (_p, _t, b, a) => ioProcessPutChars(
                      b.Cast <ErlAtom>(E), b.Cast <ErlAtom>(M),
                      b.Cast <ErlAtom>(F), b.Cast <ErlList>(A),
                      (IErlObject)a[1]) },
                { "{put_chars, ~v::string()}".ErlArgs(C),
                  (_p, _t, b, a) => ioProcessPutChars(
                      ConstAtoms.Latin1, b.Cast <ErlString>(C), (IErlObject)a[1]) },
                { "{put_chars, ~v::atom(), ~v::atom(), ~v::list()}".ErlArgs(M, F, A),
                  (_p, _t, b, a) => ioProcessPutChars(
                      ConstAtoms.Latin1, b.Cast <ErlAtom>(M),
                      b.Cast <ErlAtom>(F), b.Cast <ErlList>(A),
                      (IErlObject)a[1]) },
                { "{get_until, ~v::atom(), ~v, ~v::atom(), ~v::atom(), ~v::list()}".ErlArgs(E, P, M, F, A),
                  (_p, _t, b, a) => ioProcessGetUntil(
                      b.Cast <ErlAtom>(E), b[P], b.Cast <ErlAtom>(M), b.Cast <ErlAtom>(F),
                      b.Cast <ErlList>(A), (IErlObject)a[1]) },
                { "{get_chars, ~v::atom(), ~v, ~v::integer()}".ErlArgs(E, P, N),
                  (_p, _t, b, a) => ioProcessGetChars(
                      b.Cast <ErlAtom>(E), b[P], b.Cast <ErlLong>(N), (IErlObject)a[1]) },
                { "{get_line, ~v::atom(), ~v}".ErlArgs(E, P),
                  (_p, _t, b, a) => ioProcessGetLine(
                      b.Cast <ErlAtom>(E), b[P], (IErlObject)a[1]) },
                { "{get_until, ~v, ~v::atom(), ~v::atom(), ~v::list()}".ErlArgs(P, M, F, A),
                  (_p, _t, b, a) => ioProcessGetUntil(
                      ConstAtoms.Latin1, b[P], b.Cast <ErlAtom>(M), b.Cast <ErlAtom>(F),
                      b.Cast <ErlList>(A), (IErlObject)a[1]) },
                { "{get_chars, ~v, ~v::integer()}".ErlArgs(P, N),
                  (_p, _t, b, a) => ioProcessGetChars(
                      ConstAtoms.Latin1, b[P], b.Cast <ErlLong>(N), (IErlObject)a[1]) },
                { "{get_line, ~v}".ErlArgs(P),
                  (_p, _t, b, a) => ioProcessGetLine(
                      ConstAtoms.Latin1, b[P], (IErlObject)a[1]) },
                { "{requests, ~v::list()}".ErlArgs(R),
                  (_p, _t, b, a) => ioProcessRequests(
                      (ErlPatternMatcher)a[0], b.Cast <ErlList>(R), (IErlObject)a[1]) },
            };

            while (m_Active)
            {
                Tuple <IErlObject, ErlVarBind> res = Node.GroupLeader.ReceiveMatch(s_RequestPattern, 1500);

                if (res.Item1 == null)     // Timeout
                {
                    continue;
                }
                else if (res.Item2 == null)     // No match
                {
                    App.Log.Write(Log.MessageType.Error,
                                  StringConsts.ERL_INVALID_IO_REQUEST + res.Item1.ToString(), from: GetType().Name);
                }

                var from    = res.Item2.Cast <ErlPid>(F);
                var replyAs = res.Item2[RA];
                var request = res.Item2.Cast <ErlTuple>(R);
                var req     = (IErlObject)request;

                if (patterns.Match(ref req, patterns, replyAs) >= 0)
                {
                    Node.Send(from, req);
                    continue;
                }

                var reply = s_ReplyPattern.Subst(new ErlVarBind {
                    { RA, replyAs }, { R, ConstAtoms.Request }
                });

                Debug.Assert(reply != null);
                Node.Send(from, reply);
            }

            App.Log.Write(Log.MessageType.Info, StringConsts.ERL_STOPPING_SERVER.Args(Node.NodeLongName, "I/O"));

            m_Thread = null;
        }