Plasmaworks Community
News: SMF - Just Installed!
 
*
Welcome, Guest. Please login or register. September 09, 2010, 05:21:53 am


Login with username, password and session length


Pages: [1]
  Print  
Author Topic: Macro Templates  (Read 417 times)
Abe
PlasmaworksDev
Full Member
*****
Posts: 192


View Profile Email
« on: January 02, 2010, 11:18:22 pm »

I've been working on my annual Slag compiler revamp off and on for a few weeks.  I just now got Hello World (with a fair amount of static class initialization behind the scenes) working again, so it's pretty close to done.

This version is primarily a refactoring for flexibility and speed, but there is one exciting new feature I'd like to introduce: class templates can now have arbitrary expressions (instead of just type names) substituted in for the the placeholder names.

Here's how you'd handle the classic case of specializing a generic "Operator" class to have one variation for addition and one for multiplication:

Code:
class Test
  METHODS
    method init:
      local var add = Operator<<+>>(3,4)
      local var multiply = Operator<<*>>(3,4)
      println( add.apply )       # prints: 7
      println( multiply.apply )  # prints: 12
endClass

class GenericOperator( Int32 lhs, Int32 rhs )
  METHODS
    method apply.Int32: abstract
endClass

class Operator<<$op>> : GenericOperator
  method apply.Int32: return lhs $op rhs
endClass

I'm pretty pumped about using this in general game programming.  Nevermind inline anonymous classes; with these "macro templates", API's can more cleanly support arbitrary bits of code being passed in to functions.  Want to sort your list of actors by their y value?  That'll become:

Code:
obj_list.sort( CompareFn<<Actor,a.position.y < b.position.y>>() )

I'm also considering adding template methods that work the same way - it shouldn't be too hard given my current parsing framework.  Instead of having to send in a comparator object to a sort method, as above, the method itself could be specialized with a bit of code:

Code:
class List<<$DataType>>
  ...
  method sort( Comparator<<$DataType>> comparator ):  ... # core sort fn

  method sort<<$a_before_b_when>>: sort( CompareFn<<$DataType,$a_before_b_when>> )
endClass

...
obj_list.sort<<a.position.y < b.position.y>>
...


« Last Edit: January 02, 2010, 11:20:04 pm by Abe » Logged
Carl
Newbie
*
Posts: 15


View Profile Email
« Reply #1 on: April 07, 2010, 12:43:28 pm »

Nice!

I managed to get this working:
Code:
class TestSubClass( Int32 value )
  method value( Int32 newValue ):
    &value = newValue
    println( " my value is: " + value )
endClass

class AdjSubClasses<<$code>>
  method init( Test2 test2 ):
    forEach( sub in test2.subs ) $code
endClass

class Test2
  PROPERTIES
    subs = {
      TestSubClass( 1 ), TestSubClass( 2 ), TestSubClass( 3 )
    } : TestSubClass[]
  METHODS
    method init:
      println( "Adjusting:" )
      add1ToSubClasses
     
    method add1ToSubClasses:
      AdjSubClasses<<sub.value += 1>>( this )
endClass

Which outputs this:
Code:
my value is: 1
 my value is: 2
 my value is: 3
Adjusting:
 my value is: 2
 my value is: 3
 my value is: 4
(Because more examples are always good)

I think you should note (somewhere) that the templated code is scoped only to object you're creating it with. IOW, the code $code above (in AdjSubClasses) can only ref vars in AdjSubClasses (or global). Makes sense when ya think about it, but it's not immediately obvious and some peoples (like me) might think the code is scoped to where you defined the object with the template.


Coupla other things:
I can't pass a templated object as a param? Is there a way to do this?
Code:
class TestSubClass
  PROPERTIES
    value : Int32
  METHODS
    method init( value ):
    method value( Int32 newValue ):
      &value = newValue
      println( "my value is: " + value )
endClass

class AdjSubClass<<$code>>()
  method apply( TestSubClass subClass ): $code
endClass

class Test2
  PROPERTIES
    subs = {
      TestSubClass( 1 ), TestSubClass( 2 ), TestSubClass( 3 )
    } : TestSubClass[]
  METHODS
    method init:
      adjustSubClasses( AdjSubClass<<subClass.value += 1>>() )
     
    method adjustSubClasses( AdjSubClass adjuster ):
      forEach( sub in subs ) adjuster.apply( sub )
endClass
The above gives me this error (which is kinda vague I might add - not that compiler errors are ever clear as vodka):
Code:
ERROR:     Reference to type AdjSubClass is missing substitution values.
LINE 101:  method adjustSubClasses( AdjSubClass adjuster ):


I found this causes slagc.exe to crash (using most of the code directly above):
Code:
    method adjustSubClasses( AdjSubClass<<>> adjuster ):
      forEach( sub in subs ) adjuster.apply( sub )


Also (my two cents), although I understand templating and generics in general and the principle that code is data (or, at least, I like to think that I do), I'm not sure the <<>> syntax is really orthogonal for this code substitution stuff. Or, maybe, it's too orthogonal. Seems like some other delimiter would make this clearer when your dealing with code and not a $DataType. Then again, I don't know how much of a pain that would be.

Neat stuff, tho. Would definitely like to see method templating.
Logged
Abe
PlasmaworksDev
Full Member
*****
Posts: 192


View Profile Email
« Reply #2 on: April 07, 2010, 03:29:06 pm »

Right, TOO orthogonal.  A class "Operator<<+>>" is a totally different class than "Operator<<->>", so the trick is to have the parameter be a reference to a common base class type - "GenericOperator" in my example above.

For your example, change this:

Code:
class AdjSubClass<<$code>>()
  method apply( TestSubClass subClass ): $code
endClass

to this:

Code:
class GenericAdjSubClass;

class AdjSubClass<<$code>>() : GenericAdjSubClass
  method apply( TestSubClass subClass ): $code
endClass

and then have your parameter be type "GenericAdjSubClass"!
Logged
Carl
Newbie
*
Posts: 15


View Profile Email
« Reply #3 on: April 07, 2010, 04:29:27 pm »

Ok. So that's when that abstract parent class is working for ya, then? I think I got it.
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC

Valid XHTML 1.0! Valid CSS! Dilber MC Theme by HarzeM