Skip to content
May 3, 2009 / Abe Pralle

Slag wrapper methods

I’ve been encountering some programming situations lately that cried out for some aspect-oriented features that weren’t in Slag – until tonight!

A bit of background: aspect-oriented programming (AOP), in a nutshell, is being able to write your program as independent layers of functionality that are merged together to create the final result. For example, mixing drawing code in with your game logic is frowned upon, since if you need to entirely re-do either of those aspects – or port your software to a different system – then you’ve got to wade through everything looking for the bits and pieces you need to change.

This Slag code can be tough to maintain:

  class Spaceship
    METHODS
      method init: set_position; load_graphics
      method update: ...
      method draw: ...
  endClass

  class Laser
    METHODS
      method init: set_position; load_graphics
      method update: ...
      method draw: ...
  endClass

while this AO Slag code behaves the same and is easier to work with in the long run:

  class Spaceship
    METHODS
      method init: set_position
      method update: ...
  endClass

  class Laser
    METHODS
      method init: set_position
      method update: ...
  endClass
  ...
  overlaying augment Spaceship
    METHODS
      method init: underlying; load_graphics
      method draw: ...
  endAugment

  overlaying augment Laser
    METHODS
      method init: underlying; load_graphics
      method draw: ...
  endAugment

* * *

In retrospect I realize that Slag’s AO features were focused on creating static class definitions and what it needs are some AO features to assist dynamic calls between objects.

Prime example: Plasmacore v2 operates on a system of view windows, each with its own 2D transformation matrix (usually there’s just one window, btw). For a view to be drawn it needs to push its transformation matrix onto the transform stack, draw itself, and then pop off its transformation matrix.

To allow the draw() method to be easily overridden I can’t put the transform adjustments in that method itself, so what I end up with is:

  view.push_transform
  view.draw
  view.pop_transform

It’d be really nice to allow an application programmer to just call “view.draw” and have the transforms automatically pushed and popped. There’s various kludgy ways to do it – especially renaming the actual draw to something else – but I came up with a more elegant way that was fairly quick to implement.

Slag v2 now has wrapper methods. If you call a method “fn” and there’s a method “fn-wrapper” defined, fn-wrapper() is the method that ACTUALLY gets called, and it should call the original fn() at some point. The View class would now look like this:

  class View
    METHODS
      method draw: ...

      method draw-wrapper:
        push_transform
        draw
        pop_transform

From the outside you’d just call “view.draw” and it would actually call “view.draw-wrapper”.

The reason why you couldn’t do this with an ordinary aspect is that the calls to push/pop transform would become embedded in the actual draw code, which would make overriding draw() a hassle.

All of that is almost true.  There’s an additional twist – Murphy noticed a flaw in this new system and suggested a very elegant solution!

The problem is, say that class Beta extends Alpha and Beta defines draw-wrapper but Alpha doesn’t. In accordance with the standard rules of polymorphism, if you were to write:

  local Alpha a = Beta()
  a.draw

then it would call Beta::draw() without calling Beta::draw-wrapper() since the call context is class Alpha and the compiler can’t know for sure that the object will have the wrapper method.

The solution is to take any class with both “fn” and “fn-wrapper” defined and, in the compiler, change the names to be “fn-inner” and “fn”, respectively. The name is unchanged in base classes without wrapper methods, and the wrapper methods take on the original name in extended classes so that they’re called polymorphically.

I added wrapper methods into the compiler tonight – only took me about an hour after getting the idea ironed out!

Advertisements

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s

%d bloggers like this: