internal static IErlObject DecodeRPC(IErlObject msg) { var term = msg as ErlTuple; if (term == null) return null; var binding = term.Match(RpcReplyPattern); return binding != null ? binding[T] : null; }
/// <summary> /// Create a stream containing the serialized Erlang term. /// Optionally include in the beginning Erlang protocol version byte /// </summary> public ErlOutputStream(IErlObject o = null, bool writeVersion = true, bool writePktSize = false, int capacity = DEFAULT_INITIAL_SIZE) { m_Buffer = new byte[capacity]; m_Capacity = capacity; m_Position = 0; if (writePktSize) Write4BE(0); // make space for length data, but final value is not yet known if (o == null) { if (writeVersion) write(ErlExternalTag.Version); return; } encodeObject(o, writeVersion); if (writePktSize) Poke4BE(0, m_Position - 4); }
/// <summary> /// Create an Erlang string from the given string /// </summary> public ErlList(IErlObject[] items, bool clone = true) : base(items, clone) { }
/// <summary> /// Write an arbitrary Erlang term to the stream. /// </summary> public void Write(IErlObject o) { switch (o.TypeOrder) { case ErlTypeOrder.ErlAtom: WriteAtom((ErlAtom)o); break; case ErlTypeOrder.ErlBinary: WriteBinary((ErlBinary)o); break; case ErlTypeOrder.ErlBoolean: WriteBoolean((ErlBoolean)o); break; case ErlTypeOrder.ErlByte: WriteByte((ErlByte)o); break; case ErlTypeOrder.ErlDouble: WriteDouble((ErlDouble)o); break; case ErlTypeOrder.ErlLong: WriteLong((ErlLong)o); break; case ErlTypeOrder.ErlList: WriteList((ErlList)o); break; case ErlTypeOrder.ErlPid: WritePid((ErlPid)o); break; case ErlTypeOrder.ErlPort: WritePort((ErlPort)o); break; case ErlTypeOrder.ErlRef: WriteRef((ErlRef)o); break; case ErlTypeOrder.ErlString: WriteString((ErlString)o); break; case ErlTypeOrder.ErlTuple: WriteTuple((ErlTuple)o); break; default: throw new ErlException( StringConsts.ERL_UNSUPPORTED_ELEMENT_TYPE_ERROR, o.GetType().Name, o.TypeOrder.ToString()); } }
public ErlConnectionException(ErlAtom nodeName, IErlObject reason) : base(string.Empty) { Node = nodeName; Reason = reason; }
internal static ErlTuple EncodeRPC( ErlPid from, ErlAtom mod, ErlAtom fun, ErlList args, IErlObject gleader) { /*{Self, {call, Mod, Fun, Args, GroupLeader}} */ return new ErlTuple(from, new ErlTuple(ConstAtoms.Call, mod, fun, args, gleader)); }
/// <summary> /// Send a message to a named mailbox created from another node /// </summary> public bool Send(ErlAtom node, ErlAtom name, IErlObject msg) { return m_Node.Deliver(node, ErlMsg.RegSend(m_Self, name, msg)); }
private IErlObject ioProcessGetLine( ErlAtom encoding, IErlObject prompt, IErlObject replyAs) { return s_ReplyPattern.Subst( new ErlVarBind{ {RA, replyAs}, {R, (IErlObject)Tuple.Create(ConstAtoms.Error, ConstAtoms.Request)} }); }
internal static ErlTuple EncodeRPCcast( ErlPid from, ErlAtom mod, ErlAtom fun, ErlList args, IErlObject gleader) { /*{'$gen_cast', { cast, Mod, Fun, Args, GroupLeader}} */ return new ErlTuple( ConstAtoms.GenCast, new ErlTuple(ConstAtoms.Cast, mod, fun, args, gleader)); }
/// <summary> /// Determine if two Erlang objects are equal /// </summary> public override bool Equals(IErlObject o) { return(o is ErlList?Equals((ErlList)o) : false); }
public Pattern(int id, PatternMatchFunc b, IErlObject p) { ID = id; Func = b; Term = p; }
/* * send to remote name * dest is recipient's registered name, the nodename is implied by * the choice of connection. */ public void Send(ErlPid from, ErlAtom dest, IErlObject msg) { // encode and send the message base.Send(ErlMsg.RegSend(from, dest, msg, SendCookie)); }
/// <summary> /// Determine if two instances are equal /// </summary> public bool Equals(IErlObject o) { return((o is ErlBinary) ? Equals((ErlBinary)o) : false); }
/// <summary> /// Send an Erlang term to a Pid on a local or remote node /// </summary> public void Send(ErlPid dest, IErlObject msg) { base.Send(ErlMsg.Send(dest, msg, SendCookie)); }
/// <summary> /// Determine if two Erlang objects are equal /// </summary> public override bool Equals(IErlObject o) { return(o is ErlTuple?Equals((ErlTuple)o) : false); }
/// <summary> /// Compile a string fmt into an Erlang term /// </summary> internal static IErlObject Parse( string fmt, ref int pos, ref int argc, params object[] args) { var items = new List <IErlObject>(); IErlObject result = null; pos = skipWSAndComments(fmt, pos); if (pos < fmt.Length) { switch (fmt[pos++]) { case '{': if (State.Ok != pTuple(fmt, ref pos, ref items, ref argc, args)) { throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "tuple", pos); } result = new ErlTuple(items, false); break; case '[': if (fmt[pos] == ']') { result = new ErlList(); pos++; break; } else if (State.Ok == pList(fmt, ref pos, ref items, ref argc, args)) { result = new ErlList(items, false); break; } throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "list", pos); case '$': /* char-value? */ result = new ErlByte(Convert.ToByte(fmt[pos++])); break; case '~': if (State.Ok != pFormat(fmt, ref pos, ref items, ref argc, args)) { throw new ErlException(StringConsts.ERL_PARSING_AT_ERROR, "term", pos); } result = items[0]; break; default: char c = fmt[--pos]; if (char.IsLower(c)) { /* atom ? */ string s = pAtom(fmt, ref pos); result = createAtom(s); } else if (char.IsUpper(c) || c == '_') { result = pVariable(fmt, ref pos); } else if (char.IsDigit(c) || c == '-') { /* integer/float ? */ string s = pDigit(fmt, ref pos); if (s.IndexOf('.') < 0) { result = new ErlLong(long.Parse(s, CultureInfo.InvariantCulture)); } else { result = new ErlDouble(double.Parse(s, CultureInfo.InvariantCulture)); } } else if (c == '"') { /* string ? */ string s = pString(fmt, ref pos); result = new ErlString(s); } else if (c == '\'') { /* quoted atom ? */ string s = pQuotedAtom(fmt, ref pos); result = createAtom(s); } break; } } if (result == null) { throw new ErlException(StringConsts.ERL_INVALID_VALUE_ERROR.Args(fmt)); } return(result); }
/// <summary> /// Send a message to a named mailbox on local node /// </summary> public bool Send(ErlPid from, ErlAtom toName, IErlObject msg) { return Deliver(ErlMsg.RegSend(from, toName, msg)); }
public Pattern(int id, PatternMatchFunc b, string pattern, params object[] args) { ID = id; Func = b; Term = ErlObject.Parse(pattern, args); }
internal void IoOutput(ErlAtom encoding, IErlObject output) { if (m_OnIoOutput != null) m_OnIoOutput(encoding, output); }
/// <summary> /// Determine if two instances are equal /// </summary> public bool Equals(IErlObject o) { return((o is ErlLong && Equals((ErlLong)o)) || (o is ErlByte && Equals((ErlByte)o))); }
private IErlObject ioProcessPutChars(ErlAtom encoding, ErlString str, IErlObject replyAs) { Node.OnIoOutput(encoding, str); return s_ReplyPattern.Subst( new ErlVarBind { { RA, replyAs }, { R, ConstAtoms.Ok } }); }
internal static ErlMsg SendTT(ErlPid dest, IErlObject msg, ErlTrace traceToken, ErlAtom?cookie = null) { return(new ErlMsg(Tag.SendTT, ErlPid.Null, dest, payload: msg, trace: traceToken, cookie: cookie)); }
private IErlObject rpcCall(ErlPid from, ErlRef eref, ErlAtom mod, ErlAtom fun, ErlList args, IErlObject groupLeader) { // We spawn a new task, so that RPC calls wouldn't block the RPC server thread Task.Factory.StartNew(() => { var type = Type.GetType(mod); if (type == null) { sendRpcReply(from, eref, ErlTuple.Create(ConstAtoms.Error, "unknown type: {0}".Args(mod))); return; } // TODO: add LRU caching //var method = type.GetMethod(fun.Value, BindingFlags.Static | BindingFlags.Public); string methodName = fun.Value; if (args.Count == 0) { var pi = type.GetProperty(fun, BindingFlags.Static | BindingFlags.Public); if (pi != null) { try { var result = pi.GetValue(null, null); sendRpcReply(from, eref, ErlTuple.Create(ConstAtoms.Ok, result.ToErlObject())); } catch (Exception e) { sendRpcReply(from, eref, ErlTuple.Create(ConstAtoms.Error, new ErlString(e.Message))); }; return; } } var mi = type.GetMethods(BindingFlags.Static | BindingFlags.Public) .Where(m => m.Name == methodName && m.GetParameters().Count() == args.Count) .FirstOrDefault(); if (mi == null) { sendRpcReply(from, eref, ErlTuple.Create(ConstAtoms.Error, "unknown method: {0}".Args(fun))); return; } var pars = mi.GetParameters(); var margs = new object[pars.Length]; for (int i = 0; i < pars.Length; i++) { var par = pars[i]; var val = args[i]; margs[i] = val.AsType(par.ParameterType); } try { var result = mi.Invoke(type, margs); sendRpcReply(from, eref, ErlTuple.Create(ConstAtoms.Ok, result.ToErlObject())); } catch (Exception e) { sendRpcReply(from, eref, ErlTuple.Create(ConstAtoms.Error, new ErlString(e.Message))); } }); return (IErlObject)null; }
internal static ErlMsg RegSendTT(ErlPid from, ErlAtom dest, IErlObject msg, ErlTrace trace, ErlAtom?cookie = null) { return(new ErlMsg(Tag.RegSend, from, dest, payload: msg, cookie: cookie)); }
public ErlAuthException(ErlAtom nodeName, IErlObject reason) : base(nodeName, reason) { }
/// <summary> /// Used to break all known links to this mbox /// </summary> internal void BreakLinks(ErlAtom fromNode, IErlObject reason) { var links = m_Links.Remove(fromNode); foreach (var link in links) if (link.HasPid) m_Node.Deliver(ErlMsg.Exit(m_Self, link.Pid, reason)); else m_Node.Deliver(new ErlConnectionException(fromNode, reason)); foreach (var m in m_Monitors.Where(o => o.Value.Node == fromNode) .Where(m => m_Monitors.Remove(m.Key))) Deliver(new ErlConnectionException(fromNode, reason)); }
/// <summary> /// Determine if two Erlang objects are equal /// </summary> public override bool Equals(IErlObject o) { return o is ErlTuple ? Equals((ErlTuple)o) : false; }
internal static ErlMsg Exit2TT(ErlPid from, ErlPid dest, IErlObject reason, ErlTrace traceToken) { return(new ErlMsg(Tag.Exit2TT, from, dest, reason: reason, trace: traceToken)); }
public ErlIncompatibleTypesException(IErlObject lhs, Type rhs) : base(StringConsts.ERL_CANNOT_CONVERT_TYPES_ERROR, lhs.GetType().Name, rhs.Name) { }
/// <summary> /// Create an Erlang tuple from the given list of items /// </summary> public ErlTuple(IErlObject[] items) : base(items) {}
internal static ErlMsg DemonitorP(ErlPid from, IErlObject /* Pid or Atom */ dest, ErlRef eref) { return(new ErlMsg(Tag.DemonitorP, from, dest, eref: eref)); }
/// <summary> /// Determine if two Erlang objects are equal /// </summary> public override bool Equals(IErlObject o) { if (o is ErlList) return Equals((ErlList)o); if (o is ErlString) { var rhs = ((ErlString)o).Value; if (rhs.Length != m_Items.Count) return false; return !rhs.Where((t, i) => !m_Items[i].IsInt() || (int)t != m_Items[i].ValueAsInt).Any(); } return false; }
internal static ErlMsg MonitorPexit(IErlObject from, ErlPid dest, ErlRef eref, IErlObject reason) { return(new ErlMsg(Tag.MonitorPexit, from, dest, eref: eref, reason: reason)); }
/// <summary> /// Send a message to a remote <see cref="ErlPid"/>, representing /// either another <see cref="ErlMbox"/> or an Erlang process /// </summary> /// <returns>true if message was sent successfully</returns> public bool Send(ErlPid to, IErlObject msg) { return Deliver(ErlMsg.Send(to, msg)); }
internal static ErlMsg Send(ErlPid dest, IErlObject msg, ErlAtom?cookie = null) { return(new ErlMsg(Tag.Send, ErlPid.Null, dest, payload: msg, cookie: cookie)); }
/// <summary> /// Break links of all pids linked to pids on the fromNode node /// </summary> internal void BreakLinks(ErlAtom fromNode, IErlObject reason) { foreach (var m in m_Mailboxes) m.Value.BreakLinks(fromNode, reason); }
internal static ErlMsg Exit(ErlPid from, ErlPid dest, IErlObject reason) { return(new ErlMsg(Tag.Exit, from, dest, reason: reason)); }
private void checkForError(IErlObject pattern, IErlObject response, ErlVarBind bind, int reqID) { if (bind != null) return; bind = response.Match(pattern); if (bind == null) throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESP_PROTOCOL_ERROR + "invalid error response pattern", new Exception(response.ToString())); var gotReqID = bind[ATOM_ReqID].ValueAsLong; if (gotReqID != reqID) throw new ErlDataAccessException(StringConsts.ERL_DS_INVALID_RESP_PROTOCOL_ERROR + "unexpected transaction ID (expected={0}, got={1})".Args(reqID, gotReqID)); var ecode = bind[ATOM_Code].ValueAsInt; var rmsg = bind[ATOM_Msg]; var emsg = rmsg.TypeOrder == ErlTypeOrder.ErlString || rmsg.TypeOrder == ErlTypeOrder.ErlAtom ? rmsg.ValueAsString : rmsg.ToString(); Exception error; switch (ecode) { case INVALID_SUBSCRIPTION_REQUEST_EXCEPTION: error = new NFX.DataAccess.CRUD.Subscriptions.InvalidSubscriptionRequestException(emsg, null); break; case -1: error = new ErlDataAccessException("Remote error message: {0}".Args(emsg)); break; default: error = new ErlDataAccessException("Remote error code {0}. Message: {1}".Args(ecode, emsg)); break; } throw error; }
/// <summary> /// Determine if two atoms are equal /// </summary> public bool Equals(IErlObject o) { return(o is ErlAtom && Index == ((ErlAtom)o).Index); }
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) }}); }
public void ErlTestFormat() { { IErlObject obj1 = ErlObject.Parse("a"); Assert.IsInstanceOf(typeof(ErlAtom), obj1); Assert.AreEqual("a", obj1.ValueAsString); } { IErlObject obj1 = ErlObject.Parse("$a"); Assert.IsInstanceOf(typeof(ErlByte), obj1); Assert.AreEqual('a', (char)obj1.ValueAsInt); } { IErlObject obj1 = ErlObject.Parse("'Abc'"); Assert.IsInstanceOf(typeof(ErlAtom), obj1); Assert.AreEqual("Abc", obj1.ValueAsString); } { IErlObject obj1 = ErlObject.Parse("{'true', 'false', true, false}"); Assert.IsInstanceOf(typeof(ErlTuple), obj1); var t = (ErlTuple)obj1; Assert.AreEqual(4, t.Count); t.Select(o => { Assert.IsInstanceOf(typeof(ErlBoolean), o); return(0); }); Assert.AreEqual(true, t[0].ValueAsBool); Assert.AreEqual(false, t[1].ValueAsBool); Assert.AreEqual(true, t[2].ValueAsBool); Assert.AreEqual(false, t[3].ValueAsBool); } { IErlObject obj1 = ErlObject.Parse("\"Abc\""); Assert.IsInstanceOf(typeof(ErlString), obj1); Assert.AreEqual("Abc", obj1.ValueAsString); } { IErlObject obj1 = ErlObject.Parse("Abc"); Assert.IsInstanceOf(typeof(ErlVar), obj1); Assert.AreEqual("Abc", ((ErlVar)obj1).Name.Value); IErlObject obj2 = ErlObject.Parse("V"); Assert.IsInstanceOf(typeof(ErlVar), obj2); Assert.AreEqual("V", ((ErlVar)obj2).Name.Value); } { IErlObject obj1 = ErlObject.Parse("1"); Assert.IsInstanceOf(typeof(ErlLong), obj1); Assert.AreEqual(1, obj1.ValueAsInt); } { IErlObject obj1 = ErlObject.Parse("1.23"); Assert.IsInstanceOf(typeof(ErlDouble), obj1); Assert.AreEqual(1.23, obj1.ValueAsDouble); } { IErlObject obj1 = ErlObject.Parse("$a"); Assert.IsInstanceOf(typeof(ErlByte), obj1); Assert.AreEqual('a', (char)obj1.ValueAsInt); } { IErlObject obj1 = ErlObject.Parse("{1}"); Assert.IsInstanceOf(typeof(ErlTuple), obj1); Assert.AreEqual(1, ((ErlTuple)obj1).Count); Assert.IsInstanceOf(typeof(ErlLong), ((ErlTuple)obj1)[0]); Assert.AreEqual(1, (obj1 as ErlTuple)[0].ValueAsInt); } { IErlObject obj0 = ErlObject.Parse("[]"); Assert.IsInstanceOf(typeof(ErlList), obj0); Assert.AreEqual(0, ((ErlList)obj0).Count); IErlObject obj1 = ErlObject.Parse("[1]"); Assert.IsInstanceOf(typeof(ErlList), obj1); Assert.AreEqual(1, ((ErlList)obj1).Count); Assert.IsInstanceOf(typeof(ErlLong), (obj1 as ErlList)[0]); Assert.AreEqual(1, (obj1 as ErlList)[0].ValueAsInt); } { IErlObject obj1 = ErlObject.Parse("[{1,2}, []]"); Assert.IsInstanceOf(typeof(ErlList), obj1); Assert.AreEqual(2, (obj1 as ErlList).Count); Assert.IsInstanceOf(typeof(ErlTuple), (obj1 as ErlList)[0]); Assert.AreEqual(2, ((obj1 as ErlList)[0] as ErlTuple).Count); Assert.AreEqual(0, ((obj1 as ErlList)[1] as ErlList).Count); } { IErlObject obj1 = ErlObject.Parse("{a, [b, 1, 2.0, \"abc\"], {1, 2}}"); Assert.IsInstanceOf(typeof(ErlTuple), obj1); Assert.AreEqual(3, (obj1 as ErlTuple).Count); } { IErlObject obj1 = ErlObject.Parse("~w", 1); Assert.IsInstanceOf(typeof(ErlLong), obj1); Assert.AreEqual(1, (((ErlLong)obj1)).ValueAsInt); IErlObject obj2 = ErlObject.Parse("{~w, ~w,~w}", 1, 2, 3); Assert.IsInstanceOf(typeof(ErlTuple), obj2); Assert.AreEqual(3, (obj2 as ErlTuple).Count); Assert.IsInstanceOf(typeof(ErlLong), (obj2 as ErlTuple)[0]); Assert.AreEqual(1, (obj2 as ErlTuple)[0].ValueAsInt); Assert.IsInstanceOf(typeof(ErlLong), (obj2 as ErlTuple)[1]); Assert.AreEqual(2, (obj2 as ErlTuple)[1].ValueAsInt); Assert.IsInstanceOf(typeof(ErlLong), (obj2 as ErlTuple)[2]); Assert.AreEqual(3, (obj2 as ErlTuple)[2].ValueAsInt); } { IErlObject obj2 = ErlObject.Parse("{~w, ~w,~w,~w, ~w}", 1.0, 'a', "abc", 2, true); Assert.IsInstanceOf(typeof(ErlTuple), obj2); Assert.AreEqual(5, (obj2 as ErlTuple).Count); Assert.IsInstanceOf(typeof(ErlDouble), (obj2 as ErlTuple)[0]); Assert.AreEqual(1.0, (obj2 as ErlTuple)[0].ValueAsDouble); Assert.IsInstanceOf(typeof(ErlByte), (obj2 as ErlTuple)[1]); Assert.AreEqual((byte)'a', (obj2 as ErlTuple)[1].ValueAsInt); Assert.IsInstanceOf(typeof(ErlString), (obj2 as ErlTuple)[2]); Assert.AreEqual("abc", (obj2 as ErlTuple)[2].ValueAsString); Assert.IsInstanceOf(typeof(ErlLong), (obj2 as ErlTuple)[3]); Assert.AreEqual(2, (obj2 as ErlTuple)[3].ValueAsInt); Assert.IsInstanceOf(typeof(ErlBoolean), (obj2 as ErlTuple)[4]); Assert.AreEqual(true, (obj2 as ErlTuple)[4].ValueAsBool); } }
private IErlObject ioProcessPutChars(ErlAtom encoding, ErlAtom mod, ErlAtom fun, ErlList args, IErlObject replyAs) { string term; if (mod == ConstAtoms.Io_Lib && fun == ConstAtoms.Format && args.Count == 2) try { term = ErlObject.Format(args); } catch { term = "{0}:{1}({2})".Args(mod, fun, args.ToString(true)); } else term = "{0}:{1}({2})".Args(mod, fun, args.ToString(true)); Node.OnIoOutput(encoding, new ErlString(term)); return s_ReplyPattern.Subst( new ErlVarBind { { RA, replyAs }, { R, ConstAtoms.Ok } }); }
public void ErlTestMatchVariable() { var cases = new KeyValueList <string, IErlObject> { { "B", new ErlLong(1) }, { "B", new ErlAtom("abc") }, { "B", new ErlString("efg") }, { "B", new ErlDouble(10.0) }, { "B::int()", new ErlLong(10) }, { "B::integer()", new ErlLong(20) }, { "B::string()", new ErlString("xxx") }, { "B::atom()", new ErlAtom("xyz") }, { "B::float()", new ErlDouble(5.0) }, { "B::double()", new ErlDouble(3.0) }, { "B::binary()", new ErlBinary(new byte[] { 1, 2, 3 }) }, { "B::bool()", new ErlBoolean(true) }, { "B::boolean()", new ErlBoolean(false) }, { "B::byte()", new ErlByte(1) }, { "B::char()", new ErlByte('a') }, { "B::list()", new ErlList(1, 2, 3) }, { "B::tuple()", new ErlTuple(new ErlByte('a'), 1, "aaa") }, { "B::pid()", new ErlPid("xxx", 1, 2, 3) }, { "B::ref()", new ErlRef("xxx", 1, 0, 0, 3) }, { "B::reference()", new ErlRef("xxx", 1, 0, 0, 3) }, { "B::port()", new ErlPort("xxx", 1, 3) } }; foreach (var p in cases) { { IErlObject pat = p.Key.ToErlObject(); IErlObject obj = p.Value; var binding = new ErlVarBind(); binding[B] = obj; Assert.IsTrue(pat.Match(obj, binding)); } { IErlObject pat = p.Key.ToErlObject(); IErlObject obj = p.Value; var binding = new ErlVarBind(); Assert.IsTrue(pat.Match(obj, binding)); var b = binding["B"]; Assert.AreEqual(obj.TypeOrder, b.TypeOrder); Assert.IsTrue(obj.Equals(b)); } } var revCases = cases.Reverse <KeyValuePair <string, IErlObject> >().ToList(); cases.Zip(revCases, (p1, p2) => { ErlVar pat = ErlObject.Parse <ErlVar>(p1.Key); IErlObject obj = p2.Value; var binding = new ErlVarBind(); if (pat.ValueType == ErlTypeOrder.ErlObject || pat.ValueType == obj.TypeOrder) { Assert.IsTrue(pat.Match(obj, binding)); } else { Assert.IsFalse(pat.Match(obj, binding)); } return(false); }).ToList(); }
private void sendRpcReply(ErlPid from, ErlRef eref, IErlObject reply) { if (from.Empty) return; Node.Send(from, ErlTuple.Create(eref, reply)); }
public void ErlTestPatternMatch() { { var binding = new ErlVarBind(); IErlObject obj = ErlObject.Parse("{snapshot, x12, []}"); IErlObject pat = ErlObject.Parse("{snapshot, N, L}"); Assert.IsTrue(pat.Match(obj, binding)); ErlAtom n = binding.Cast <ErlAtom>(N); ErlList l = binding.Cast <ErlList>(L); Assert.IsNotNull(n); Assert.IsNotNull(l); Assert.IsTrue(l.Count == 0); } { IErlObject pat = ErlObject.Parse("{test, A, B, C}"); IErlObject obj = ErlObject.Parse("{test, 10, a, [1,2,3]}"); var binding = new ErlVarBind(); Assert.IsTrue(pat.Match(obj, binding)); Assert.AreEqual(3, binding.Count); Assert.AreEqual(10, binding.Cast <ErlLong>(A)); Assert.AreEqual("a", binding.Cast <ErlAtom>(B).ValueAsString); Assert.AreEqual("[1,2,3]", binding["C"].ToString()); } { var binding = new ErlVarBind(); IErlObject obj = ErlObject.Parse("[1,a,$b,\"xyz\",{1,10.0},[]]"); IErlObject pat = ErlObject.Parse("[A,B,C,D,E,F]"); Assert.IsTrue(pat.Match(obj, binding)); Assert.IsNotNull(binding.Cast <ErlLong>(A)); Assert.IsNotNull(binding.Cast <ErlAtom>(B)); Assert.IsNotNull(binding.Cast <ErlByte>(C)); Assert.IsNotNull(binding.Cast <ErlString>(D)); Assert.IsNotNull(binding.Cast <ErlTuple>(E)); Assert.IsNotNull(binding.Cast <ErlList>(F)); Assert.IsTrue(binding.Cast <ErlTuple>(E).Count == 2); Assert.IsTrue(binding.Cast <ErlList>(F).Count == 0); } IErlObject pattern = ErlObject.Parse("{test, T}"); string exp = "{test, ~w}"; { var binding = new ErlVarBind(); IErlObject obj = ErlObject.Parse(exp, (int)3); Assert.IsTrue(pattern.Match(obj, binding)); Assert.AreEqual(3, binding.Cast <ErlLong>(T)); } { var binding = new ErlVarBind(); IErlObject obj = ErlObject.Parse(exp, (long)100); Assert.IsTrue(pattern.Match(obj, binding)); Assert.AreEqual(100, binding.Cast <ErlLong>(T)); } { var binding = new ErlVarBind(); IErlObject obj = ErlObject.Parse(exp, 100.0); Assert.IsTrue(pattern.Match(obj, binding)); Assert.AreEqual(100.0, binding.Cast <ErlDouble>(T).ValueAsDouble); } { var binding = new ErlVarBind(); IErlObject obj = ErlObject.Parse(exp, "test"); Assert.IsTrue(pattern.Match(obj, binding)); Assert.AreEqual("test", binding.Cast <ErlString>(T).ValueAsString); } { var binding = new ErlVarBind(); IErlObject obj = ErlObject.Parse(exp, true); Assert.IsTrue(pattern.Match(obj, binding)); Assert.AreEqual(true, binding.Cast <ErlBoolean>(T).ValueAsBool); } { var binding = new ErlVarBind(); IErlObject obj = ErlObject.Parse(exp, 'c'); Assert.IsTrue(pattern.Match(obj, binding)); Assert.AreEqual((byte)'c', binding.Cast <ErlByte>(T).ValueAsInt); } { var binding = new ErlVarBind(); var pid = new ErlPid("tmp", 1, 2, 3); IErlObject obj = ErlObject.Parse(exp, pid as IErlObject); Assert.IsTrue(pattern.Match(obj, binding)); Assert.AreEqual(pid, binding.Cast <ErlPid>(T)); Assert.AreEqual(pid, binding.Cast <ErlPid>(T).Value); obj = ErlObject.Parse(exp, pid); Assert.IsTrue(pattern.Match(obj, binding)); Assert.AreEqual(pid, binding.Cast <ErlPid>(T).Value); } { var binding = new ErlVarBind(); var port = new ErlPort("tmp", 1, 2); IErlObject obj = ErlObject.Parse(exp, port); Assert.IsTrue(pattern.Match(obj, binding)); Assert.AreEqual(port, binding.Cast <ErlPort>(T)); Assert.AreEqual(port, binding.Cast <ErlPort>(T).Value); } { var binding = new ErlVarBind(); var reference = new ErlRef("tmp", 1, 0, 0, 2); IErlObject obj = ErlObject.Parse(exp, reference); Assert.IsTrue(pattern.Match(obj, binding)); Assert.AreEqual(reference, binding.Cast <ErlRef>(T)); Assert.AreEqual(reference, binding.Cast <ErlRef>(T).Value); } { var binding = new ErlVarBind(); ErlList obj = new ErlList(new ErlLong(10), new ErlDouble(30.0), new ErlString("abc"), new ErlAtom("a"), new ErlBinary(new byte[] { 1, 2, 3 }), false, new ErlBoolean(true)); IErlObject pat = ErlObject.Parse("T"); Assert.IsTrue(pat.Match(obj, binding)); IErlObject expected = ErlObject.Parse("[10, 30.0, \"abc\", 'a', ~w, \'false\', true]", new ErlBinary(new byte[] { 1, 2, 3 })); IErlObject result = binding[T]; Assert.IsTrue(expected.Equals(result)); } }
internal static ErlTuple EncodeRPCcast( ErlPid from, string mod, string fun, ErlList args, IErlObject gleader) { return EncodeRPCcast(from, new ErlAtom(mod), new ErlAtom(fun), args, gleader); }
/// <summary> /// Determine if two instances are equal /// </summary> public bool Equals(IErlObject o) { return((o is ErlBinary) && Equals((ErlBinary)o)); }
/// <summary> /// Perform pattern match on this Erlang term without binding any variables /// </summary> public bool Matches(IErlObject pattern) { return(pattern is ErlVar?pattern.Matches(this) : Equals(pattern)); }
/// <summary> /// Receive a message and match it against a given pattern /// </summary> /// <param name="pattern">Pattern to match the message against</param> /// <param name="timeoutMsec">Timeout in milliseconds</param> /// <returns>Return a tuple containing the received message and variable /// binding object. On timeout the first element of the tuple is null. /// On unsuccessful match the second element of the tuple is null</returns> public Tuple<IErlObject, ErlVarBind> ReceiveMatch(IErlObject pattern, int timeoutMsec = -1) { var m = Receive(timeoutMsec); if (m == null) return Tuple.Create<IErlObject, ErlVarBind>(null, null); var binding = new ErlVarBind(); bool res = m.Match(pattern, binding); return Tuple.Create(m, res ? binding : null); }
/// <summary> /// Determine if two atoms are equal /// </summary> public bool Equals(IErlObject o) { return(o is ErlBoolean?Equals((ErlBoolean)o) : false); }
public void RPCcast(ErlAtom node, ErlAtom mod, ErlAtom fun, ErlList args, IErlObject ioServer) { if (node.Equals(m_Node.NodeName)) throw new ErlException(StringConsts.ERL_CONN_CANT_RPC_TO_LOCAL_NODE_ERROR); else { var msg = Internal.ErlRpcServer.EncodeRPCcast(m_Self, mod, fun, args, ioServer); var conn = m_Node.Connection(node); if (conn == null) throw new ErlConnectionException( node, StringConsts.ERL_CONN_CANT_CONNECT_TO_NODE_ERROR.Args(node)); conn.Send(m_Self, ConstAtoms.Rex, msg); } }
/// <summary> /// Compare this instance to the object. /// Negative value means that the atom is less than obj, positive - greater than the obj /// </summary> public int CompareTo(object obj) { IErlObject o = obj as IErlObject; return(o == null ? -1 : CompareTo(o)); }
protected string HeaderType(IErlObject h) { var tag = h is ErlTuple ? (ErlMsg.Tag)(((ErlTuple)h)[0].ValueAsInt) : ErlMsg.Tag.Undefined; return tag.ToString().ToUpper(); }
public bool Subst(ref IErlObject term, ErlVarBind binding) { return(false); }
public static int EncodeSize(IErlObject o) { switch (o.TypeOrder) { case ErlTypeOrder.ErlAtom: return 1 + 2 + o.ValueAsString.Length; case ErlTypeOrder.ErlBinary: return 5 + o.ValueAsByteArray.Length; case ErlTypeOrder.ErlBoolean: return 1 + 2 + (o.ValueAsBool ? ErlConsts.TRUE.Length : ErlConsts.FALSE.Length); case ErlTypeOrder.ErlByte: return 1 + 1; case ErlTypeOrder.ErlDouble: return 9; case ErlTypeOrder.ErlLong: long l1 = o.ValueAsLong; if ((l1 & 0xff) == l1) return 2; else if ((ErlConsts.ERL_INT_MIN <= l1) && (l1 <= ErlConsts.ERL_INT_MAX)) return 5; return longArity(l1); case ErlTypeOrder.ErlList: var l2 = (ErlList)o; if (l2.Count == 0) return 1; return 5 + l2.Value.Sum(obj1 => EncodeSize(obj1)); case ErlTypeOrder.ErlPid: var p1 = (ErlPid)o; return 1 + (1 + 2 + p1.Node.Length) + 4 + 4 + 1; case ErlTypeOrder.ErlPort: var p2 = (ErlPort)o; return 1 + (1 + 2 + p2.Node.Length) + 4 + 1; case ErlTypeOrder.ErlRef: var p3 = (ErlRef)o; return 1 + (1 + 2 + p3.Node.Length) + 1 + 4 * p3.Ids.Length; case ErlTypeOrder.ErlString: var l3 = o.ValueAsString; if (l3.Length == 0) return 1; if (l3.Length < 0xffff) return 2 + l3.Length; return 1 + 4 + 2 * l3.Length; case ErlTypeOrder.ErlTuple: var l4 = (ErlTuple)o; int sz = 1 + (l4.Count < 0xff ? 1 : 4); return sz + l4.Value.Sum(obj2 => EncodeSize(obj2)); default: throw new ErlException(StringConsts.ERL_UNSUPPORTED_ELEMENT_TYPE_ERROR, o.GetType().Name, o.TypeOrder.ToString()); } }
/// <summary> /// Perform pattern match on this Erlang term returning null if match fails /// or a dictionary of matched variables bound in the pattern /// </summary> public ErlVarBind Match(IErlObject pattern) { return(pattern is ErlVar ? pattern.Match(this) : Equals(pattern) ? new ErlVarBind() : null); }
private void encodeObject(IErlObject o, bool writeVersion) { if (writeVersion) write(ErlExternalTag.Version); Write(o); }
/// <summary> /// Perform pattern match on this Erlang term, storing matched variables /// found in the pattern into the binding. /// </summary> public bool Match(IErlObject pattern, ErlVarBind binding) { return(pattern is ErlVar?pattern.Match(this, binding) : Equals(pattern)); }