Metasyntax/Macros

Michele Simionato mis6 at pitt.edu
Wed Jun 4 12:08:10 EDT 2003


Donald 'Paddy' McCarthy <paddy3118 at blueyonder.co.ukNOTthisBIT> wrote in message news:<3ED52C50.3020002 at blueyonder.co.ukNOTthisBIT>...

<snip>

> Anyone for meta-macro programming ;-)

The subject of macros come often in this newgroup. I've got 
the impression that it is not difficult to implement them, the 
problem is that the developers DON'T WANT them. I think they are 
most probably right. Nevertheless, I have just finished an
experimental
project with the purpose of adding a macro facility to Python (it was 
a proof of concept for me). This is done via a pure Python module,
called (according to the Principle of Minimal Surprise ;) 'macro.py'.
At the moment, it is still little tested, but it works along the
following
lines:

1. In order to define a macro, the user has to supply a template
function,
i.e. is a function that takes as arguments Python expressions in
string
format and returns as output a string Python expression (or
statement).
In the present implementation I have forced the time-honored
convention
that macros/template functions are all capitals.
An example is the following:

  #<example1.py>

  def PRINT(*args):
      "The arguments are strings; returns a print statement"
      return "print "+','.join(['"%s =",%s' % (a,a) for a in args])

  #</example1.py>

PRINT works as follows:

  >>> from example1 import PRINT
  >>> PRINT()
  'print '
  >>> PRINT('x')
  'print "x =",x'
  >>> PRINT('x','y') # etc.
  'print "x =",x,"y =",y'

2. In order to use the macro (the macro evaluate the output of the
template
function) the user has to write it inside a function or inside a
class;
the function or the class are then explicitly interpreted by using the
command 'expand' in the 'macro' module, which expands the template
function.
This is an example of usage:

  #<example1.py>

  import macro

  def print_x(x):
      PRINT(x) # will expand --> print "x=",x 

  expanded_print_x=macro.expand(print_x) 

  #</example1.py>

3. At this point, in ``expanded_print_x`` the macro PRINT(x) is
effectively
expanded to ``print "x=",x`` and calling the function gives the result

  >>> from example1 import expanded_print_x
  >>> expanded_print_x(1)
  x = 1

4. Since using macro.expand repetitively can be annoying, I have
provided a metaclass facility. When a class has a ``__metaclass__ =
macro.expand()`` attribute, macros are automagically expanded in all 
its methods and attributes, and in its derived classes, too.

  #<example2.py>

  import macro,example1

  class B(object):
      __metaclass__=macro.expand()

  class C(B): # macros are automagically expanded
      def __init__(self,x=None):
          example1.PRINT(x) # --> print "x=",x 

  #</example2.py>

  >>> from example2 import C
  >>> c=C()
  x = None

It works also for macros containing other macros (but 
not for recursive macros). 
Consider for instance the following ternary operator

  #<example3.py>

  def IF(cond,e1,e2):
      return '(%s and [%s] or [%s])[0]' % (cond,e1,e2)

  #</example3.py>

It can be composed with PRINT as in the following script:

  #<example3.py>
  
  from example1 import PRINT,macro

  def print_ternary():
      PRINT(IF(True,1,0)) # --> IF(True,1,0) = 1

  print_ternary=macro.expand(print_ternary)

  #</example3.py>

Here is how it works:

  >>> from example3 import print_ternary
  >>> print_ternary()
  IF ( True , 1 , 0 ) = 1

I wonder if this approach could satisfy your requirements.

My module is still experimental and not for distribution; as I said,
the principal interest to me was to show that implementing macros IN
SOME WAY in pure Python is indeed possible with a reasonable amount of
effort.
However, implementing them WELL is a completely different story and I
expect
it to be extremely difficult ;)

Cheers,

--
Michele Simionato - Dept. of Physics and Astronomy
210 Allen Hall Pittsburgh PA 15260 U.S.A.
Phone: 001-412-624-9041 Fax: 001-412-624-9163
Home-page: http://www.phyast.pitt.edu/~micheles/




More information about the Python-list mailing list