2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-22 05:22:45 +00:00
Files
python/src/gen_function.py
Dave Abrahams 6a6084ed0e Metrowerks needs BOOST_NO_STD_LOCALE in config to be able to compile regex
regex test Jamfile updates so that some tests will actually run
warning suppression for condition.cpp

unit-test rule now accepts input files
updated metrowerks and borland to properly set up path for running tests

----------------------------------------------------------------------
Modified Files:
	boost/config/compiler/metrowerks.hpp
	libs/python/src/gen_function.py libs/regex/test/Jamfile
 Tag: thread-initial
	libs/thread/src/condition.cpp
 No tag
	tools/build/boost-base.jam tools/build/borland-tools.jam
	tools/build/metrowerks-tools.jam
----------------------------------------------------------------------


[SVN r11853]
2001-12-02 17:43:45 +00:00

235 lines
8.7 KiB
Python

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 _raise_no_argument(key, n, args):
raise IndexError(str(key) + " extra arg(s) not passed to gen_function")
def _gen_common_key(key, n, args, fill = _raise_no_argument):
# import sys
# print >> sys.stderr, "_gen_common_key(", repr(key), ",", repr(n), ',', repr(args), ',', fill, ')'
# sys.stderr.flush()
if len(key) > 0 and key in '123456789':
index = int(key) - 1;
if index >= len(args):
return fill(key, n, args)
arg = args[index]
if callable(arg):
return str(arg(key, n, args))
else:
return str(arg)
elif key in ('x','n','-','+'):
return str(n + {'-':-1,'+':+1,'x':0,'n':0}[key])
else:
return key
def _gen_arg(template, n, args, delimiter = '%', fill = _raise_no_argument):
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 0 and key == 'n':
result = result + `n`
else:
result = result + _gen_common_key(key, n, args, fill)
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 within %(...%). Elsewhere, %n is transformed into the
string representation of n
%- is transformed into the string representation of 0..n-1 for
each repetition within %(...%). Elsewhere, %- is transformed into the
string representation of n-1.
%+ is transformed into the string representation of 2..n+1 for
each repetition within %(...%). Elsewhere, %- is transformed into the
string representation of n+1.
%x is always transformed into the string representation of n
%z, where z is a digit, selects the corresponding additional
argument. If that argument is callable, it is called with three
arguments:
key - the string representation of 'z'
n - the iteration number
args - a tuple consisting of all the additional arguments to
this function
otherwise, the selected argument is converted to a string representation
for example,
>>> gen_function('%1 abc%x(%(int a%n%:, %));%{ // all args are ints%}', 2, 'void')
'void abc2(int a1, int a2); // all args are ints'
>>> gen_function('%1 abc(%(int a%n%:, %));%{ // all args are ints%}', 0, 'x')
'x abc();'
>>> gen_function('%1 abc(%(int a%n%:, %));%{ // all args are ints%}', 0, lambda key, n, args: 'abcd'[n])
'a abc();'
>>> gen_function('%2 %1 abc(%(int a%n%:, %));%{ // all args are ints%}', 0, 'x', fill = lambda key, n, args: 'const')
'const x abc();'
>>> gen_function('abc%[k%:v%]', 0, fill = lambda key, n, args, value = None: '<' + key + ',' + value + '>')
'abc<k,v>'
>>> 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', '%')
fill = keywords.get('fill', _raise_no_argument);
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)
remainder = template[separator_pos+2 : end]
if key == '(':
for x in range(1, n + 1):
result = result + _gen_arg(template[start:separator_pos], x, args,
delimiter)
if x != n:
result = result + remainder
else:
result = result + fill(template[start:separator_pos], n, args, value = remainder)
else:
result = result + _gen_common_key(key, n, args, fill)
i = delimiter_pos + 2
return result
def gen_functions(template, n, *args, **keywords):
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
"""
fill = keywords.get('fill', _raise_no_argument);
result = ''
for x in range(n + 1):
result = result + apply(gen_function, (template, x) + args, keywords)
return result
if __name__ == '__main__':
import doctest
import sys
doctest.testmod(sys.modules.get(__name__))