Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

c macros in python.

6 views
Skip to first unread message

noagbod...@gmail.com

unread,
May 6, 2007, 5:01:20 PM5/6/07
to
Hey,

I'm writing a script to generate code. I'm a bit tired of typing
outfile.write(....). Does python have a way to c-like macros? Every
instance of o(...) in the code will be replaced by outfile.write(...)?

Amaury Forgeot d'Arc

unread,
May 6, 2007, 5:06:58 PM5/6/07
to
noagbod...@gmail.com a écrit :

First: Python has no macro facility.

But in this particular case, it is very simple. Just add:
o = outfile.write
after the variable outfile is initialized.
It is not a macro (just another name for a function object)
but it looks the same...

--
Amaury

John Machin

unread,
May 6, 2007, 5:09:49 PM5/6/07
to

Functions and methods are first-class citizens in Python; all you have
to do is:

o = outfile.write
o('blah blah\n')
o('etc\n')

Bonus: your code will run (measurably but almost imperceptibly)
faster, because you save a method lookup every time you use it.This
would not happen with a text-substituting macro approach.

HTH,
John

noagbod...@gmail.com

unread,
May 6, 2007, 5:11:46 PM5/6/07
to
Great python!!!


ici

unread,
May 6, 2007, 5:22:30 PM5/6/07
to
All in Python is pointer to object, and functions too, so

o = outfile.write
o("Some Text")

You can redirect print to file also:

print >> outfile, "Text", var1, var2[2:]
or
o = outfile
print >> o, "Text", var1, var2[2:]
:)


A.T.Hofkamp

unread,
May 7, 2007, 3:19:52 AM5/7/07
to

Just in case you don't know, you can write an arbitrary number of lines in one
write. Below is how I format a usage() message of a program in one write call:

def usage(fp):
fp.write("Usage: convert options [infile] [outfile]\n"
"with\n"
" options\n"
"\t--prefix=<name-prefix>\t(obligatory)\n"
"\t--write-size\t\tWrite a line containing the size\n"
"\t--append-zero\t\tAppend a terminating 0 byte\n")

ie one multi-line write call. Pyhon concatenates two consequtive string
literals for us. Unfortunately, this gets less pretty when inserting variable
values.


In other code generation code, I normally use a list of lines. Rather than
writing everything directly to file, I make a list data structure containing
lines, then dump the list to file, as in:

lines = []
gencode_first(lines)
gencode_second(lines)
lines.append("the end")
write_lines(lines)

where write_lines() is

def write_lines(lines):
for line in lines:
outfile.write(line)
outfile.write('\n')

(i left out the opening and closing of outfile).


I normally do not include the \n in the list but instead add it while writing
it to file. This makes life much easier since there are no special last-value
problems in the code generator itself.
The nice thing here is that 'lines' is a normal data structure which you can
manipulate if you like.


For more demanding code generators (ie C or C++ code) I use the concept
'sections'. At a global level, the generated code has an 'include',
'declarations', 'definitions', and 'main' section, each section is a list of
lines.
I use a dictionary for this, like

output = { 'incl': [], 'decl': [], 'def': [], 'main': [] }

then pass around this in the code generator.
Each part of the generator can write in each section, for example when defining
a C function, you can write the declaration in the decl section and the
definition in the def section at the same time.
For example

def write_c_function(output):
output['decl'].append('int mycfunc(void);')
output['def'].extend(['int myfunc(void)', '{' 'return 131;', }' ])

Reducing such a dictionary to a list is then something like

def make_lines(sec_list, output):
lines = []
for sec in sec_list:
lines.extend(output[sec])
return lines

And outputting the code is then something like

write_lines(make_lines(['incl', 'decl', 'def', 'main'], output))

In this way you can abstract away from the order of code as required by the
target language and instead generate code in a nicer order.
Note that this section trick can be done recursively. for example, a function
can be thought of as a number of sections like

funcoutput = { 'header': [], 'opening-bracket' : [], 'localvars':[], 'closing-bracket': [] }

so you can generate a function using sections as well, then at the end reduce
funcoutput to a list of lines, and insert that in a section of the global
'output'.


Last but not least, if you replace the lists by an object, you can do much
smarter things. For example, in general you don't want to have double #include
lines in the 'incl' section. Instead of worrying about generation of doubles,
just make an object that behaves like a list but silently drops doubles.
In the same way, you can create a list-like object that handles indenting for
you.

The possibilities here are endless!!


Good luck with your code generation problem, I hope I gave you some ideas of
alternative solutions that are available.

Albert

Cameron Laird

unread,
May 7, 2007, 8:49:25 AM5/7/07
to
In article <f1lg15$g0k$1...@talisker.lacave.net>,

Amaury Forgeot d'Arc <afaN...@neuf.fr> wrote:
>noagbod...@gmail.com a écrit :
>> Hey,
>>
>> I'm writing a script to generate code. I'm a bit tired of typing
>> outfile.write(....). Does python have a way to c-like macros? Every
>> instance of o(...) in the code will be replaced by outfile.write(...)?
>
>First: Python has no macro facility.
.
.
.
For the sake of completeness, I want to note that the standard
distribution includes Tools/Scripts/ifdef.py, and pyparsing now
has an example macro preprocessor. Neither of these would be
the correct response to the original question, of course, but
they might interest other readers who believe they need "c-like
macros".
0 new messages