Manipulating Particles of Type anytype

MLDesigner allows primitives to be written that will read and write particles of any type.

It is possible to declare inputs and outputs to be of type anytype. A primitive may need to do this, for example, if it simply copies its inputs without regard to type, as in the case of a Fork primitive, or if it calls a generic function that is overloaded by every data type, such as sink primitives which call the print method of the type.

The following is an example of a primitive that operates on anytype particles:

defprimitive
{
  name        { Fork }
  domain      { SDF }
  desc
  {
    Copies input to each output.
  }

  input
  {
    name { input }
    type { anytype }
  }

  outmulti
  {
    name { output }
    type { =input }
  }

  location { SDF main library }

  ccinclude {"kernel/Message.h","kernel/Type.h" }

  go
  {
    OutSDFMPHIter nextp(output);
    OutSDFPort* p;
    Particle& pp = input%0;
    Type *tType(0);
    if((pp.type() == DATASTRUCTTYPE) && (tType = (Type*)pp))
    {
      while ((p = (OutSDFPort*)nextp.next()) != 0)
        (*p)%0 << tType->clone();
    }
    else
    {
      while ((p = (OutSDFPort*)nextp.next()) != 0)
        (*p)%0 = pp;
    }
  }
}


It should be noticed that in the definition of the output port, the primitive simply says that its output type will be the same as the input type. Ptlang translates this definition into an ANYTYPE output porthole and a statement in the primitive constructor that reads

output.inheritTypeFrom(input);

During module setup, the MLDesigner kernel assigns actual types to ANYTYPE ports, making use of the types of connected ports and inheritTypeFrom connections. For example, if a Fork input is connected to an output port of type INT, the Fork input’s type becomes INT, and, because of the inheritTypeFrom connection, the output will do, too. At runtime, there is no such thing as an ANYTYPE porthole. Every port has been resolved to some specific data type, which can be obtained from the porthole using the resolvedType() method. However, this mechanism does not differ among the various subclasses of Message, so if the programmer is using Message particles, he still needs to check the actual type of each Message received.

Porthole type assignment is really a fairly complex and subtle algorithm. The important properties for a primitive writer to know are these:

go
{
  double value = double(in%0);
  ...
}

        but this is not strictly necessary in the current system.

out%0 << t;