mirror of
https://github.com/boostorg/python.git
synced 2026-01-22 17:32:55 +00:00
This commit was generated by cvs2svn to compensate for changes in r315,
which included commits to RCS files with non-trunk default branches. [SVN r7932]
This commit is contained in:
184
gen_function.py
Normal file
184
gen_function.py
Normal file
@@ -0,0 +1,184 @@
|
||||
import string
|
||||
|
||||
def _find(s, sub, start=0, end=None):
|
||||
"""Just like string.find, except it returns end or len(s) when not found.
|
||||
"""
|
||||
if end == None:
|
||||
end = len(s)
|
||||
|
||||
pos = string.find(s, sub, start, end)
|
||||
if pos < 0:
|
||||
return end
|
||||
else:
|
||||
return pos
|
||||
|
||||
def _gen_common_key(key, n, args):
|
||||
if len(key) > 0 and key in '123456789':
|
||||
return str(args[int(key) - 1])
|
||||
elif key == 'x':
|
||||
return str(n)
|
||||
else:
|
||||
return key
|
||||
|
||||
def _gen_arg(template, n, args, delimiter = '%'):
|
||||
result = ''
|
||||
i = 0
|
||||
while i < len(template): # until the template is consumed
|
||||
# consume everything up to the first delimiter
|
||||
delimiter_pos = _find(template, delimiter, i)
|
||||
result = result + template[i:delimiter_pos]
|
||||
|
||||
# The start position of whatever comes after the delimiter+key
|
||||
start = delimiter_pos + 2
|
||||
key = template[start - 1 : start] # the key character. If there were no
|
||||
# delimiters left, key will be empty
|
||||
|
||||
if key == 'n':
|
||||
result = result + `n`
|
||||
else:
|
||||
result = result + _gen_common_key(key, n, args)
|
||||
|
||||
i = start
|
||||
|
||||
return result
|
||||
|
||||
def gen_function(template, n, *args, **keywords):
|
||||
r"""gen_function(template, n, [args...] ) -> string
|
||||
|
||||
Generate a function declaration based on the given template.
|
||||
|
||||
Sections of the template between '%(', '%)' pairs are repeated n times. If '%:'
|
||||
appears in the middle, it denotes the beginning of a delimiter.
|
||||
|
||||
Sections of the template between '%{', '%}' pairs are ommitted if n == 0.
|
||||
|
||||
%n is transformed into the string representation of 1..n for each repetition
|
||||
of n.
|
||||
|
||||
%x, where x is a digit, is transformed into the corresponding additional
|
||||
argument.
|
||||
|
||||
for example,
|
||||
|
||||
>>> gen_function('%1 abc(%(int a%n%:, %));%{ // all args are ints%}', 2, 'void')
|
||||
'void abc(int a1, int a2); // all args are ints'
|
||||
>>> gen_function('%1 abc(%(int a%n%:, %));%{ // all args are ints%}', 0, 'x')
|
||||
'x abc();'
|
||||
|
||||
|
||||
>>> template = ''' template <class T%(, class A%n%)>
|
||||
... static PyObject* call( %1(T::*pmf)(%(A%n%:, %))%2, PyObject* args, PyObject* /* keywords */ ) {
|
||||
... PyObject* self;
|
||||
... %( PyObject* a%n;
|
||||
... %) if (!PyArg_ParseTuple(args, const_cast<char*>("O%(O%)"), &self%(, &a%n%)))
|
||||
... return 0;
|
||||
... T& target = from_python(self, Type<T&>());
|
||||
... %3to_python((target.*pmf)(%(
|
||||
... from_python(a%n, Type<A%n>())%:,%)
|
||||
... ));%4
|
||||
... }'''
|
||||
|
||||
>>> print gen_function(template, 0, 'R ', '', 'return ', '')
|
||||
template <class T>
|
||||
static PyObject* call( R (T::*pmf)(), PyObject* args, PyObject* /* keywords */ ) {
|
||||
PyObject* self;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("O"), &self))
|
||||
return 0;
|
||||
T& target = from_python(self, Type<T&>());
|
||||
return to_python((target.*pmf)(
|
||||
));
|
||||
}
|
||||
|
||||
>>> print gen_function(template, 2, 'R ', '', 'return ', '')
|
||||
template <class T, class A1, class A2>
|
||||
static PyObject* call( R (T::*pmf)(A1, A2), PyObject* args, PyObject* /* keywords */ ) {
|
||||
PyObject* self;
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOO"), &self, &a1, &a2))
|
||||
return 0;
|
||||
T& target = from_python(self, Type<T&>());
|
||||
return to_python((target.*pmf)(
|
||||
from_python(a1, Type<A1>()),
|
||||
from_python(a2, Type<A2>())
|
||||
));
|
||||
}
|
||||
|
||||
>>> print gen_function(template, 3, 'void ', ' const', '', '\n'+8*' ' + 'return none();')
|
||||
template <class T, class A1, class A2, class A3>
|
||||
static PyObject* call( void (T::*pmf)(A1, A2, A3) const, PyObject* args, PyObject* /* keywords */ ) {
|
||||
PyObject* self;
|
||||
PyObject* a1;
|
||||
PyObject* a2;
|
||||
PyObject* a3;
|
||||
if (!PyArg_ParseTuple(args, const_cast<char*>("OOOO"), &self, &a1, &a2, &a3))
|
||||
return 0;
|
||||
T& target = from_python(self, Type<T&>());
|
||||
to_python((target.*pmf)(
|
||||
from_python(a1, Type<A1>()),
|
||||
from_python(a2, Type<A2>()),
|
||||
from_python(a3, Type<A3>())
|
||||
));
|
||||
return none();
|
||||
}
|
||||
"""
|
||||
delimiter = keywords.get('delimiter', '%')
|
||||
result = ''
|
||||
i = 0
|
||||
while i < len(template): # until the template is consumed
|
||||
# consume everything up to the first delimiter
|
||||
delimiter_pos = _find(template, delimiter, i)
|
||||
result = result + template[i:delimiter_pos]
|
||||
|
||||
# The start position of whatever comes after the delimiter+key
|
||||
start = delimiter_pos + 2
|
||||
key = template[start - 1 : start] # the key character. If there were no
|
||||
# delimiters left, key will be empty
|
||||
|
||||
pairs = { '(':')', '{':'}' }
|
||||
|
||||
if key in pairs.keys():
|
||||
end = string.find(template, delimiter + pairs[key], start)
|
||||
assert end >= 0, "Matching '" + delimiter + pairs[key] +"' not found!"
|
||||
delimiter_pos = end
|
||||
|
||||
if key == '{':
|
||||
if n > 0:
|
||||
result = result + gen_function(template[start:end], n, args, delimiter)
|
||||
else:
|
||||
separator_pos = _find(template, delimiter + ':', start, end)
|
||||
separator = template[separator_pos+2 : end]
|
||||
|
||||
for x in range(1, n + 1):
|
||||
result = result + _gen_arg(template[start:separator_pos], x, args,
|
||||
delimiter)
|
||||
if x != n:
|
||||
result = result + separator
|
||||
|
||||
else:
|
||||
result = result + _gen_common_key(key, n, args)
|
||||
|
||||
i = delimiter_pos + 2
|
||||
|
||||
return result
|
||||
|
||||
def gen_functions(template, n, *args):
|
||||
r"""gen_functions(template, n, [args...]) -> string
|
||||
|
||||
Call gen_function repeatedly with from 0..n and the given optional
|
||||
arguments.
|
||||
|
||||
>>> print gen_functions('%1 abc(%(int a%n%:, %));%{ // all args are ints%}\n', 2, 'void'),
|
||||
void abc();
|
||||
void abc(int a1); // all args are ints
|
||||
void abc(int a1, int a2); // all args are ints
|
||||
|
||||
"""
|
||||
result = ''
|
||||
for x in range(n + 1):
|
||||
result = result + apply(gen_function, (template, x) + args)
|
||||
return result
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
Reference in New Issue
Block a user