C++ code generation
CHEN Guang
dr.cg at 126.com
Tue Mar 16 21:54:25 EDT 2010
PythoidC ( http://pythoidc.googlecode.com ) is a C code generator (not C++)
----- Original Message -----
From: "Dan Goodman" <dg.gmane at thesamovar.net>
To: <python-list at python.org>
Sent: Wednesday, March 17, 2010 9:00 AM
Subject: C++ code generation
> Hi all,
>
> I'm doing some C++ code generation using Python, and would be interested
> in any comments on the approach I'm taking.
>
> Basically, the problem involves doing some nested loops and executing
> relatively simple arithmetic code snippets, like:
>
> for i in xrange(len(X)):
> X[i] += 5
>
> Actually they're considerably more complicated than this, but this gives
> the basic idea. One way to get C++ code from this would be to use
> Cython, but there are two problems with doing that. The first problem is
> that the arithmetic code snippets are user-specified. What I want to do
> is generate code, and then compile and run it using Scipy's weave
> package. The second problem is that I have various different data
> structures and the C++ code generated needs to be different for the
> different structures (e.g. sparse or dense matrices).
>
> So far what I've been doing is writing Python code that writes the C++
> code, but in a very non-transparent way. I like the idea of specifying
> the C++ code using Python syntax, like in Cython. So the idea I came up
> with was basically to abuse generators and iterators so that when you
> write something like:
>
> for x in X:
> ...
>
> it actually outputs some C++ code that looks like:
>
> for(int i=0; i<X_len; i++){
> double &x = X[i];
> ...
> }
>
> The ... in the Python code is only executed once because when X is
> iterated over it only returns one value.
>
> Here's the example I've written so far (complete code given below):
>
> # initialisation code
> code = OutputCode()
> evaluate = Evaluator(code)
> X = Array(code, 'values')
> # specification of the C++ loop
> for x in X:
> evaluate('x += 5; x *= 2')
> # and show the output
> print code.code
>
> It generates the following C++ code:
>
> for(int values_index=0; values_index<values_len; values_index++){
> double &values = values_array[values_index];
> values += 5;
> values *= 2;
> }
>
> OK, so that's an overview of the idea that I have of how to do it. Any
> comments or suggestions on either the approach or the implementation?
>
> Below is the complete code I've written for the example above (linewraps
> aren't perfect but there's only a couple of lines to correct).
>
> Thanks for any feedback,
>
> Dan
>
> import re, inspect
>
> # We just use this class to identify certain variables
> class Symbol(str): pass
>
> # This class is basically just a mutable string
> class OutputCode(object):
> def __init__(self):
> self.code = ''
> def __iadd__(self, code):
> self.code = self.code+code
> return self
>
> # Iterating over instances of this class generates code
> # for iterating over a C++ array, it yields a single
> # Symbol object, the variable name of the value in the
> # array
> class Array(object):
> def __init__(self, code, name, dtype='double'):
> self.name = name
> self.dtype = dtype
> self.code = code
> def __iter__(self):
> def f():
> self.code += 'for(int {name}_index=0;
> {name}_index<{name}_len; {name}_index++){{\n'.format(name=self.name)
> self.code += '{dtype} &{name} =
> {name}_array[{name}_index];\n'.format(dtype=self.dtype, name=self.name)
> yield Symbol(self.name)
> self.code += '}\n'
> return f()
>
> # Instances of this class generate C++ code from Python syntax
> # code snippets, replacing variable names that are a Symbol in the
> # namespace with the value of that Symbol.
> class Evaluator(object):
> def __init__(self, code):
> self.code = code
> def __call__(self, code):
> # The set of variables in the code snippet
> vars = re.findall(r'\b(\w+)\b', code)
> # Extract any names from the namespace of the calling frame
> frame = inspect.stack()[1][0]
> globals, locals = frame.f_globals, frame.f_locals
> values = {}
> for var in vars:
> if var in locals:
> values[var] = locals[var]
> elif var in globals:
> values[var] = globals[var]
> # Replace any variables whose values are Symbols with their values
> for var, value in values.iteritems():
> if isinstance(value, Symbol):
> code = re.sub(r'\b{var}\b'.format(var=var), str(value),
> code)
> # Turn Python snippets into C++ (just a simplified version for now)
> code = code.replace(';', '\n')
> lines = [line.strip() for line in code.split('\n')]
> code = ''.join(line+';\n' for line in lines)
> self.code += code
>
> if __name__=='__main__':
> code = OutputCode()
> evaluate = Evaluator(code)
> X = Array(code, 'values')
> for x in X:
> evaluate('x += 5; x *= 2')
> print code.code
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20100317/c0ee7c83/attachment-0001.html>
More information about the Python-list
mailing list