Implementing a Push Type

From a developer’s point of view, a Push type is implemented through a class, derived from PushTypeBase, as mentioned in the previous post.

Once the type is implemented in any .NET language the system will hook it into the currently available types, will add a parser and a stack for it.

All that needs to be done is:

  1. Declare a class, deriving from PushTypeBase, and decorated with PushType attribute. Here the required parameter to the attribute is the name of the type:
        [<PushType("FLOAT")>]
        type Float =
            inherit PushTypeBase
             
  2. Define default constructor, and the constructor with one argument: the underlying type value, e.g., for a FLOAT type – a float type value:

    in C#:

            public Float() : base() {};
            public Float(double d) : base (d) {};
             

    and here is the syntax for the same in F#:

            new () = {inherit PushTypeBase ()}
            new (f : float) = {inherit PushTypeBase(f)}
             
  3. For easy access to the type name of this Push type, define a static member and instantiate it with the default constructor.
              static member Me = Float()
             
  4. Implement custom parsing if required by creating a parse function and overriding the base class Parser property. Or simply override the Parser property to return Unchecked.defaultof<ExtendedTypeParser> in F#, null in C#:

            // custom parsing
            static member parse s =
                let result = ref Unchecked.defaultof<float>
                if not (System.Double.TryParse(s, result)) 
                then 
                    Unchecked.defaultof<PushTypeBase> 
                else 
                    new Float(!result) :> PushTypeBase
    
            override t.Parser 
                with get() = 
                    ExtendedTypeParser(Float.parse)
             
  5. Override the base class ToString() implementation, if necessary. The base implementation will simply call the ToString() of the underlying value type if it is implemented.
  6. Implement type specific operations (more in the next post):
           [<PushOperation("+")>]
            static member Add() =
                match processArgs2 Float.Me.MyType with
                | [a1; a2] -> pushResult(Float(a1.Raw<float>() + a2.Raw<float>()))
                | _ -> ()
                
            [<PushOperation("*")>]
            static member Multiply() =
                match processArgs2 Float.Me.MyType with
                | [a1; a2] -> pushResult(Float(a1.Raw<float>() * a2.Raw<float>()))
                | _ -> ()
    
             

Here is an example of extending the language with the URL type, implemented in C#:

    [PushType("URL")]
    public class UrlPushType : Type.PushTypeBase
    {
        public UrlPushType() : base() {}
        public UrlPushType(Uri url) : base(url) {}

        static UrlPushType UrlParse(string url)
        {
            try
            {
                if (!url.Trim().StartsWith("http://", true, CultureInfo.InvariantCulture))
                {
                    return null;
                }

                Uri uri = new Uri(url);
                if (uri.HostNameType != UriHostNameType.Dns)
                {
                    return null;
                }

                return new UrlPushType(uri);

            }
            catch (Exception)
            {
                return null;                
            }
        }

        public override Type.ExtendedTypeParser Parser
        {
            get 
            {
                return new Type.ExtendedTypeParser(UrlParse);
            }
        }

        [PushOperation("DOMAIN", Description="Extract domain name from the URL")]
        static void ExtractDomain()
        {
            // pop the URL from the URL stack
            var arg = TypeFactory.processArgs1("URL");

            //if there is nothing there...
            if (arg == null)
            {
                return;
            }

            // extract the underlying data
            var uri = arg.Raw<Uri>();

            //create the new URI
            var newUri = new UrlPushType(new Uri(uri.Host));
            
            // push it back to the URL stack.
            TypeFactory.pushResult(newUri);
        }

        public override string ToString()
        {
            return base.ToString();
        }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.