Tag Archives: polymorphism

SELF — one factory to rule them all

Another promise fulfilled — having pinned constructors in hand I could add “SELF” which behaves like implicit generics. Or you can think of it as virtual static feature.

Probably the best way to present it is using factory pattern:

struct Foo
  // constructor
  def pinned init() Foo 
  do
    return self // "this" in C++ family
  end

  def static Create() SELF
  do
    return new SELF();
  end
end

struct Bar : Foo
  def pinned init() Bar
  do
    return self 
  end
end  

The “SELF” which interests us sits in “Create” method. When you call it as “Foo.Create” you will get instance of “Foo”, but when you call it as “Bar.Create” you will get “Bar” object. Please note that such call does not cause an error:

var obj Bar = Bar.Create();

The above snippet would be erroneous if “Create” was defined differently, namely:

  ...
  def static Create() Foo
  do
    return new SELF();
  end

forcing you to write:

var obj Foo = Bar.Create(); 
// Bar is created nevertheless

But since it was defined with result type as “SELF”, the actual result type changes from call to call and compiler knows about it.

To summarize — “self” is a polymorphic reference to an object, “SELF” is a polymorphic reference to a type. You can create new instances using “SELF” as long as the used constructor is marked as pinned.

Advertisement
Tagged , , , ,

Implicit generics and pinned constructors

It is preliminary step of enhanced generics we know from C# and I hope all things finally clicked in for implementing this feature. Consider such code:

public class ClassModifier : TreeNode
{
  public bool IsAbstract { get; private set; }
  public bool IsVirtual { get; private set; }
  public bool IsStatic { get; private set; }

  private ClassModifier(NodeCoords coords)
    : base(coords)
  {
  }

  public static ClassModifier Abstract(NodeCoords coords)
  {
    return new ClassModifier(coords) 
      { IsAbstract = true };
  }
  ...

and

public class MethodModifier : TreeNode
{
  public bool IsAbstract { get; private set; }
  public bool IsVirtual { get; private set; }
  public bool IsStatic { get; private set; }
  public bool IsNew { get; private set; }
  public bool IsOverride { get; private set; }

  private MethodModifier(NodeCoords coords)
    : base(coords)
  {
  }

  public static MethodModifier Abstract(NodeCoords coords)
  {
    return new MethodModifier(coords) 
      { IsAbstract = true };
  }
...

Factory methods as usual, nothing special except the code is highly redundant. In PHP it can be expressed nicely because it has static constructor with late binding — it works like static polymorphism. It can be shortened in C# too, but with ugly twists.

However Skila is meant to be expressive and compiled language.

So I came up with idea of pinned constructor for the beginning. Once added to any class such constructor has to be overridden in every descendant class (or automatically upgraded). Secondly special keyword to express static polymorphism is needed — “SELF” sounds just right. With those two enhancements the code becomes much shorter (it is not Skila yet):

public class ClassModifier : TreeNode
{
  public bool IsAbstract { get; protected set; }
  public bool IsVirtual { get; protected set; }
  public bool IsStatic { get; protected set; }

  protected pinned ClassModifier(NodeCoords coords)
    : base(coords)
  {
  }

  public static SELF Abstract(NodeCoords coords)
  {
    return new SELF(coords) 
      { IsAbstract = true };
  }
  ...

public class MethodModifier : ClassModifier
{
  public bool IsNew { get; private set; }
  public bool IsOverride { get; private set; }
  ...
}

Thanks to pinned constructor it is safe to write “new SELF(coords)” — every class has to support such call. And because “SELF” works as implicit generics when I call “MethodModifier.Abstract()” I will get “MethodModifier”, not “ClassModifier” despite the fact the method is static and it is defined in “ClassModifier” class.

Tagged , , , , , , ,