2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-12 12:02:24 +00:00

Merge Python function support into function.c

[SVN r77518]
This commit is contained in:
Steven Watanabe
2012-03-24 21:07:49 +00:00
parent 0b3b574817
commit 888393c652
6 changed files with 353 additions and 453 deletions

View File

@@ -1841,12 +1841,7 @@ LIST * builtin_python_import_rule( FRAME * frame, int flags )
if ( pFunc && PyCallable_Check( pFunc ) )
{
module_t * m = bindmodule( jam_module );
RULE * r = bindrule( jam_rule, m );
/* Make pFunc owned. */
Py_INCREF( pFunc );
r->python_function = pFunc;
new_rule_body( m, jam_rule, 0, function_python( pFunc, 0 ), 0 );
}
else
{
@@ -2014,25 +2009,7 @@ PyObject * bjam_import_rule( PyObject * self, PyObject * args )
object_free( rule_name );
/* Make pFunc owned. */
Py_INCREF( func );
r->python_function = func;
r->arguments = 0;
if (bjam_signature)
{
argument_list * arg_list = args_new();
Py_ssize_t i;
Py_ssize_t s = PySequence_Size (bjam_signature);
for (i = 0; i < s; ++i)
{
PyObject* v = PySequence_GetItem (bjam_signature, i);
lol_add(arg_list->data, list_from_python (v));
Py_DECREF(v);
}
r->arguments = arg_list;
}
r->procedure = function_python( func, bjam_signature );
Py_INCREF( Py_None );
return Py_None;

View File

@@ -115,391 +115,6 @@ void frame_free( FRAME* frame )
}
static void argument_error( const char * message, RULE * rule, FRAME * frame, OBJECT * arg )
{
LOL * actual = frame->args;
assert( rule->procedure != 0 );
backtrace_line( frame->prev );
printf( "*** argument error\n* rule %s ( ", frame->rulename );
lol_print( rule->arguments->data );
printf( " )\n* called with: ( " );
lol_print( actual );
printf( " )\n* %s %s\n", message, arg ? object_str ( arg ) : "" );
function_location( rule->procedure, &frame->file, &frame->line );
print_source_line( frame );
printf( "see definition of rule '%s' being called\n", object_str( rule->name ) );
backtrace( frame->prev );
exit( 1 );
}
/* Define delimiters for type check elements in argument lists (and return type
* specifications, eventually).
*/
# define TYPE_OPEN_DELIM '['
# define TYPE_CLOSE_DELIM ']'
/*
* is_type_name() - true iff the given string represents a type check
* specification.
*/
int is_type_name( const char * s )
{
return ( s[ 0 ] == TYPE_OPEN_DELIM ) &&
( s[ strlen( s ) - 1 ] == TYPE_CLOSE_DELIM );
}
/*
* arg_modifier - if the next element of formal is a single character, return
* that; return 0 otherwise. Used to extract "*+?" modifiers * from argument
* lists.
*/
static char arg_modifier( LISTITER iter, LISTITER end )
{
iter = list_next( iter );
if ( iter != end )
{
const char * next = object_str( list_item( iter ) );
if ( next && ( next[ 0 ] != 0 ) && ( next[ 1 ] == 0 ) )
return next[ 0 ];
}
return 0;
}
/*
* type_check() - checks that each element of values satisfies the requirements
* of type_name.
*
* caller - the frame of the rule calling the rule whose arguments are
* being checked
*
* called - the rule being called
*
* arg_name - a list element containing the name of the argument being
* checked
*/
static void type_check_range
(
OBJECT * type_name,
LISTITER iter,
LISTITER end,
FRAME * caller,
RULE * called,
OBJECT * arg_name
)
{
static module_t * typecheck = 0;
/* If nothing to check, bail now. */
if ( iter == end || !type_name )
return;
if ( !typecheck )
{
typecheck = bindmodule( constant_typecheck );
}
/* If the checking rule can not be found, also bail. */
if ( !typecheck->rules || !hash_find( typecheck->rules, type_name ) )
return;
for ( ; iter != end; iter = list_next( iter ) )
{
LIST *error;
FRAME frame[1];
frame_init( frame );
frame->module = typecheck;
frame->prev = caller;
frame->prev_user = caller->module->user_module ? caller : caller->prev_user;
/* Prepare the argument list */
lol_add( frame->args, list_new( L0, object_copy( list_item( iter ) ) ) );
error = evaluate_rule( type_name, frame );
if ( !list_empty( error ) )
argument_error( object_str( list_front( error ) ), called, caller, arg_name );
frame_free( frame );
}
}
static void type_check
(
OBJECT * type_name,
LIST * values,
FRAME * caller,
RULE * called,
OBJECT * arg_name
)
{
type_check_range( type_name, list_begin( values ), list_end( values ), caller, called, arg_name );
}
/*
* collect_arguments() - local argument checking and collection
*/
static SETTINGS *
collect_arguments( RULE* rule, FRAME* frame )
{
SETTINGS *locals = 0;
LOL * all_actual = frame->args;
LOL * all_formal = rule->arguments ? rule->arguments->data : 0;
if ( all_formal ) /* Nothing to set; nothing to check */
{
int max = all_formal->count > all_actual->count
? all_formal->count
: all_actual->count;
int n;
for ( n = 0; n < max ; ++n )
{
LIST *actual = lol_get( all_actual, n );
OBJECT * type_name = 0;
LIST *formal;
LISTITER formal_iter, formal_end;
LISTITER actual_iter = list_begin( actual ), actual_end = list_end( actual );
for ( formal = lol_get( all_formal, n ),
formal_iter = list_begin( formal ), formal_end = list_end( formal );
formal_iter != formal_end; formal_iter = list_next( formal_iter ) )
{
OBJECT * name = list_item( formal_iter );
if ( is_type_name( object_str( name ) ) )
{
if ( type_name )
argument_error( "missing argument name before type name:", rule, frame, name );
if ( list_next( formal_iter ) == formal_end )
argument_error( "missing argument name after type name:", rule, frame, name );
type_name = name;
}
else
{
LIST* value = L0;
char modifier;
OBJECT* arg_name = list_item( formal_iter ); /* hold the argument name for type checking */
int multiple = 0;
/* Stop now if a variable number of arguments are specified */
if ( object_str( name )[0] == '*' && object_str( name )[1] == 0 )
return locals;
modifier = arg_modifier( formal_iter, formal_end );
if ( actual_iter == actual_end && modifier != '?' && modifier != '*' )
argument_error( "missing argument", rule, frame, name );
switch ( modifier )
{
case '+':
case '*':
value = list_copy_range( actual, actual_iter, actual_end );
multiple = 1;
actual_iter = actual_end;
/* skip an extra element for the modifier */
formal_iter = list_next( formal_iter );
break;
case '?':
/* skip an extra element for the modifier */
formal_iter = list_next( formal_iter );
/* fall through */
default:
if ( actual_iter != actual_end ) /* in case actual is missing */
{
value = list_new( L0, object_copy( list_item( actual_iter ) ) );
actual_iter = list_next( actual_iter );
}
}
locals = addsettings(locals, VAR_SET, name, value);
locals->multiple = multiple;
type_check( type_name, value, frame, rule, arg_name );
type_name = 0;
}
}
if ( actual_iter != actual_end )
{
argument_error( "extra argument", rule, frame, list_item( actual_iter ) );
}
}
}
return locals;
}
RULE *
enter_rule( char *rulename, module_t *target_module );
#ifdef HAVE_PYTHON
static int python_instance_number = 0;
/* Given a Python object, return a string to use in Jam
code instead of said object.
If the object is string, use the string value
If the object implemenets __jam_repr__ method, use that.
Otherwise return 0. */
OBJECT *python_to_string(PyObject* value)
{
if (PyString_Check(value))
{
return object_new(PyString_AsString(value));
}
else
{
/* See if this is an instance that defines special __jam_repr__
method. */
if (PyInstance_Check(value)
&& PyObject_HasAttrString(value, "__jam_repr__"))
{
PyObject* repr = PyObject_GetAttrString(value, "__jam_repr__");
if (repr)
{
PyObject* arguments2 = PyTuple_New(0);
PyObject* value2 = PyObject_Call(repr, arguments2, 0);
Py_DECREF(repr);
Py_DECREF(arguments2);
if (PyString_Check(value2))
{
return object_new(PyString_AsString(value2));
}
Py_DECREF(value2);
}
}
return 0;
}
}
static LIST*
call_python_function(RULE* r, FRAME* frame)
{
LIST * result = 0;
PyObject * arguments = 0;
PyObject * kw = NULL;
int i ;
PyObject * py_result;
FRAME * prev_frame_before_python_call;
if (r->arguments)
{
SETTINGS * args;
arguments = PyTuple_New(0);
kw = PyDict_New();
for (args = collect_arguments(r, frame); args; args = args->next)
{
PyObject *key = PyString_FromString(object_str(args->symbol));
PyObject *value = 0;
if (args->multiple)
value = list_to_python(args->value);
else {
if (!list_empty(args->value))
value = PyString_FromString(object_str(list_front(args->value)));
}
if (value)
PyDict_SetItem(kw, key, value);
Py_DECREF(key);
Py_XDECREF(value);
}
}
else
{
arguments = PyTuple_New( frame->args->count );
for ( i = 0; i < frame->args->count; ++i )
{
PyObject * arg = PyList_New(0);
LIST* l = lol_get( frame->args, i);
LISTITER iter = list_begin( l ), end = list_end( l );
for ( ; iter != end; iter = list_next( iter ) )
{
PyObject * v = PyString_FromString(object_str(list_item(iter)));
PyList_Append( arg, v );
Py_DECREF(v);
}
/* Steals reference to 'arg' */
PyTuple_SetItem( arguments, i, arg );
}
}
prev_frame_before_python_call = frame_before_python_call;
frame_before_python_call = frame;
py_result = PyObject_Call( r->python_function, arguments, kw );
frame_before_python_call = prev_frame_before_python_call;
Py_DECREF(arguments);
Py_XDECREF(kw);
if ( py_result != NULL )
{
if ( PyList_Check( py_result ) )
{
int size = PyList_Size( py_result );
int i;
for ( i = 0; i < size; ++i )
{
PyObject * item = PyList_GetItem( py_result, i );
OBJECT *s = python_to_string (item);
if (!s) {
fprintf( stderr, "Non-string object returned by Python call.\n" );
} else {
result = list_new (result, s);
}
}
}
else if ( py_result == Py_None )
{
result = L0;
}
else
{
OBJECT *s = python_to_string(py_result);
if (s)
result = list_new(L0, s);
else
/* We have tried all we could. Return empty list. There are
cases, e.g. feature.feature function that should return
value for the benefit of Python code and which also can be
called by Jam code, where no sensible value can be
returned. We cannot even emit a warning, since there will
be a pile of them. */
result = L0;
}
Py_DECREF( py_result );
}
else
{
PyErr_Print();
fprintf(stderr,"Call failed\n");
}
return result;
}
module_t * python_module()
{
static module_t * python = 0;
if ( !python )
python = bindmodule(constant_python);
return python;
}
#endif
LIST * function_run_with_args( FUNCTION * function_, FRAME * frame, STACK * s );
/*
* evaluate_rule() - execute a rule invocation.
*/
@@ -516,14 +131,6 @@ evaluate_rule(
rule = bindrule( rulename, frame->module );
#ifdef HAVE_PYTHON
if ( rule->python_function )
{
frame->module = python_module();
return call_python_function( rule, frame );
}
#endif
if ( DEBUG_COMPILE )
{
/* Try hard to indicate in which module the rule is going to execute. */
@@ -654,7 +261,7 @@ evaluate_rule(
FUNCTION * function = rule->procedure;
function_refer( function );
result = function_run_with_args( function, frame, stack_global() );
result = function_run( function, frame, stack_global() );
function_free( function );
}

View File

@@ -166,6 +166,21 @@ typedef struct _jam_function
} JAM_FUNCTION;
#ifdef HAVE_PYTHON
#define FUNCTION_PYTHON 2
typedef struct _python_function
{
FUNCTION base;
PyObject * python_function;
} PYTHON_FUNCTION;
static LIST * call_python_function( PYTHON_FUNCTION * function, FRAME * frame );
#endif
struct _stack
{
void * data;
@@ -2516,9 +2531,17 @@ void function_location( FUNCTION * function_, OBJECT * * file, int * line )
*file = constant_builtin;
*line = -1;
}
#ifdef HAVE_PYTHON
if ( function_->type == FUNCTION_PYTHON )
{
*file = constant_builtin;
*line = -1;
}
#endif
else
{
JAM_FUNCTION * function = (JAM_FUNCTION *)function_;
assert( function_->type == FUNCTION_JAM );
*file = function->file;
*line = function->line;
}
@@ -2570,9 +2593,26 @@ FUNCTION * function_compile_actions( const char * actions, OBJECT * file, int li
return (FUNCTION *)result;
}
int is_type_name( const char * s );
static void argument_list_print( struct arg_list * args, int num_args );
/* Define delimiters for type check elements in argument lists (and return type
* specifications, eventually).
*/
# define TYPE_OPEN_DELIM '['
# define TYPE_CLOSE_DELIM ']'
/*
* is_type_name() - true iff the given string represents a type check
* specification.
*/
int is_type_name( const char * s )
{
return ( s[ 0 ] == TYPE_OPEN_DELIM ) &&
( s[ strlen( s ) - 1 ] == TYPE_CLOSE_DELIM );
}
static void argument_error( const char * message, FUNCTION * procedure, FRAME * frame, OBJECT * arg )
{
LOL * actual = frame->args;
@@ -3122,8 +3162,15 @@ FUNCTION * function_unbind_variables( FUNCTION * f )
else
return (FUNCTION *)func;
}
#ifdef HAVE_PYTHON
else if ( f->type == FUNCTION_PYTHON )
{
return f;
}
#endif
else
{
assert( f->type == FUNCTION_BUILTIN );
return f;
}
}
@@ -3134,12 +3181,19 @@ FUNCTION * function_bind_variables( FUNCTION * f, module_t * module, int * count
{
return f;
}
#ifdef HAVE_PYTHON
else if ( f->type == FUNCTION_PYTHON )
{
return f;
}
#endif
else
{
JAM_FUNCTION * func = (JAM_FUNCTION *)f;
JAM_FUNCTION * new_func = BJAM_MALLOC( sizeof( JAM_FUNCTION ) );
instruction * code;
int i;
assert( f->type == FUNCTION_JAM );
memcpy( new_func, func, sizeof( JAM_FUNCTION ) );
new_func->base.reference_count = 1;
new_func->base.formal_arguments = argument_list_bind_variables( f->formal_arguments, f->num_formal_arguments, module, counter );
@@ -3250,8 +3304,17 @@ void function_free( FUNCTION * function_ )
object_free( func->file );
}
}
#ifdef HAVE_PYTHON
else if ( function_->type == FUNCTION_PYTHON )
{
PYTHON_FUNCTION * func = (PYTHON_FUNCTION *)function_;
Py_DECREF( func->python_function );
if ( function_->rulename ) object_free( function_->rulename );
}
#endif
else
{
assert( function_->type == FUNCTION_BUILTIN );
if ( function_->rulename ) object_free( function_->rulename );
}
@@ -3286,28 +3349,6 @@ void function_run_actions( FUNCTION * function, FRAME * frame, STACK * s, string
stack_deallocate( s, sizeof( string * ) );
}
LIST * function_run_with_args( FUNCTION * function_, FRAME * frame, STACK * s )
{
LIST * result;
if ( function_->type == FUNCTION_BUILTIN )
{
BUILTIN_FUNCTION * f = (BUILTIN_FUNCTION *)function_;
if ( function_->formal_arguments )
argument_list_check( function_->formal_arguments, function_->num_formal_arguments, function_, frame );
return f->func( frame, f->flags );
}
if ( function_->formal_arguments )
argument_list_push( function_->formal_arguments, function_->num_formal_arguments, function_, frame, s );
result = function_run( function_, frame, s );
if ( function_->formal_arguments )
argument_list_pop( function_->formal_arguments, function_->num_formal_arguments, frame, s );
return result;
}
/*
* WARNING: The instruction set is tuned for Jam and
* is not really generic. Be especially careful about
@@ -3326,9 +3367,26 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
if ( function_->type == FUNCTION_BUILTIN )
{
BUILTIN_FUNCTION * f = (BUILTIN_FUNCTION *)function_;
if ( function_->formal_arguments )
argument_list_check( function_->formal_arguments, function_->num_formal_arguments, function_, frame );
return f->func( frame, f->flags );
}
#ifdef HAVE_PYTHON
else if ( function_->type == FUNCTION_PYTHON )
{
PYTHON_FUNCTION * f = (PYTHON_FUNCTION *)function_;
return call_python_function( f, frame );
}
#endif
assert( function_->type == FUNCTION_JAM );
if ( function_->formal_arguments )
argument_list_push( function_->formal_arguments, function_->num_formal_arguments, function_, frame, s );
function = (JAM_FUNCTION *)function_;
code = function->code;
for ( ; ; )
@@ -3590,6 +3648,8 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
case INSTR_RETURN:
{
if ( function_->formal_arguments )
argument_list_pop( function_->formal_arguments, function_->num_formal_arguments, frame, s );
#ifndef NDEBUG
if ( !( saved_stack == s->data ) )
@@ -4208,6 +4268,267 @@ LIST * function_run( FUNCTION * function_, FRAME * frame, STACK * s )
}
}
#ifdef HAVE_PYTHON
static struct arg_list * arg_list_compile_python( PyObject * bjam_signature, int * num_arguments )
{
if ( bjam_signature )
{
struct argument_list_compiler c[ 1 ];
struct arg_list * result;
Py_ssize_t s, i, j, inner;
argument_list_compiler_init( c );
s = PySequence_Size( bjam_signature );
for ( i = 0; i < s; ++i )
{
struct argument_compiler arg_comp[ 1 ];
struct arg_list arg;
PyObject * v = PySequence_GetItem( bjam_signature, i );
argument_compiler_init( arg_comp );
inner = PySequence_Size( v );
for ( j = 0; j < inner; ++j )
{
PyObject * x = PySequence_GetItem( v, j );
argument_compiler_add( arg_comp, object_new( PyString_AsString( x ) ), constant_builtin, -1 );
}
arg = arg_compile_impl( arg_comp, constant_builtin, -1 );
dynamic_array_push( c->args, arg );
argument_compiler_free( arg_comp );
Py_DECREF( v );
}
*num_arguments = c->args->size;
result = BJAM_MALLOC( c->args->size * sizeof( struct arg_list ) );
memcpy( result, c->args->data, c->args->size * sizeof( struct arg_list ) );
argument_list_compiler_free( c );
return result;
}
else
{
*num_arguments = 0;
return 0;
}
}
FUNCTION * function_python( PyObject * function, PyObject * bjam_signature )
{
PYTHON_FUNCTION * result = BJAM_MALLOC( sizeof( PYTHON_FUNCTION ) );
result->base.type = FUNCTION_PYTHON;
result->base.reference_count = 1;
result->base.rulename = 0;
result->base.formal_arguments = arg_list_compile_python( bjam_signature, &result->base.num_formal_arguments );
Py_INCREF( function );
result->python_function = function;
return (FUNCTION *)result;
}
static void argument_list_to_python( struct arg_list * formal, int formal_count, FUNCTION * function, FRAME * frame, PyObject * kw )
{
LOL * all_actual = frame->args;
int i, j;
for ( i = 0; i < formal_count; ++i )
{
LIST *actual = lol_get( all_actual, i );
LISTITER actual_iter = list_begin( actual ), actual_end = list_end( actual );
for ( j = 0; j < formal[i].size; ++j )
{
struct argument * formal_arg = &formal[i].args[j];
PyObject * value;
LIST * l;
switch ( formal_arg->flags )
{
case ARG_ONE:
if ( actual_iter == actual_end )
argument_error( "missing argument", function, frame, formal_arg->arg_name );
type_check_range( formal_arg->type_name, actual_iter, list_next( actual_iter ), frame, function, formal_arg->arg_name );
value = PyString_FromString( object_str( list_item( actual_iter) ) );
actual_iter = list_next( actual_iter );
break;
case ARG_OPTIONAL:
if ( actual_iter == actual_end )
value = 0;
else
{
type_check_range( formal_arg->type_name, actual_iter, list_next( actual_iter ), frame, function, formal_arg->arg_name );
value = PyString_FromString( object_str( list_item( actual_iter) ) );
actual_iter = list_next( actual_iter );
}
break;
case ARG_PLUS:
if ( actual_iter == actual_end )
argument_error( "missing argument", function, frame, formal_arg->arg_name );
/* fallthrough */
case ARG_STAR:
type_check_range( formal_arg->type_name, actual_iter, actual_end, frame, function, formal_arg->arg_name );
l = list_copy_range( actual, actual_iter, actual_end );
value = list_to_python( l );
list_free( l );
actual_iter = actual_end;
break;
case ARG_VARIADIC:
return;
}
if (value)
{
PyObject * key = PyString_FromString( object_str( formal_arg->arg_name ) );
PyDict_SetItem( kw, key, value );
Py_DECREF( key );
Py_DECREF( value );
}
}
if ( actual_iter != actual_end )
{
argument_error( "extra argument", function, frame, list_item( actual_iter ) );
}
}
for ( ; i < all_actual->count; ++i )
{
LIST * actual = lol_get( all_actual, i );
if ( !list_empty( actual ) )
{
argument_error( "extra argument", function, frame, list_front( actual ) );
}
}
}
/* Given a Python object, return a string to use in Jam
code instead of said object.
If the object is string, use the string value
If the object implemenets __jam_repr__ method, use that.
Otherwise return 0. */
OBJECT * python_to_string( PyObject * value )
{
if ( PyString_Check( value ) )
{
return object_new( PyString_AsString( value ) );
}
else
{
/* See if this is an instance that defines special __jam_repr__
method. */
if ( PyInstance_Check( value )
&& PyObject_HasAttrString( value, "__jam_repr__" ) )
{
PyObject* repr = PyObject_GetAttrString( value, "__jam_repr__" );
if ( repr )
{
PyObject * arguments2 = PyTuple_New( 0 );
PyObject * value2 = PyObject_Call( repr, arguments2, 0 );
Py_DECREF( repr );
Py_DECREF( arguments2 );
if ( PyString_Check( value2 ) )
{
return object_new( PyString_AsString( value2 ) );
}
Py_DECREF( value2 );
}
}
return 0;
}
}
static module_t * python_module()
{
static module_t * python = 0;
if ( !python )
python = bindmodule(constant_python);
return python;
}
static LIST * call_python_function( PYTHON_FUNCTION * function, FRAME * frame )
{
LIST * result = 0;
PyObject * arguments = 0;
PyObject * kw = NULL;
int i ;
PyObject * py_result;
FRAME * prev_frame_before_python_call;
if ( function->base.formal_arguments )
{
arguments = PyTuple_New(0);
kw = PyDict_New();
argument_list_to_python( function->base.formal_arguments, function->base.num_formal_arguments, &function->base, frame, kw );
}
else
{
arguments = PyTuple_New( frame->args->count );
for ( i = 0; i < frame->args->count; ++i )
{
PyTuple_SetItem( arguments, i, list_to_python( lol_get( frame->args, i ) ) );
}
}
frame->module = python_module();
prev_frame_before_python_call = frame_before_python_call;
frame_before_python_call = frame;
py_result = PyObject_Call( function->python_function, arguments, kw );
frame_before_python_call = prev_frame_before_python_call;
Py_DECREF( arguments );
Py_XDECREF( kw );
if ( py_result != NULL )
{
if ( PyList_Check( py_result ) )
{
int size = PyList_Size( py_result );
int i;
for ( i = 0; i < size; ++i )
{
PyObject * item = PyList_GetItem( py_result, i );
OBJECT *s = python_to_string( item );
if ( !s ) {
fprintf( stderr, "Non-string object returned by Python call.\n" );
} else {
result = list_new( result, s );
}
}
}
else if ( py_result == Py_None )
{
result = L0;
}
else
{
OBJECT *s = python_to_string( py_result );
if (s)
result = list_new( L0, s );
else
/* We have tried all we could. Return empty list. There are
cases, e.g. feature.feature function that should return
value for the benefit of Python code and which also can be
called by Jam code, where no sensible value can be
returned. We cannot even emit a warning, since there will
be a pile of them. */
result = L0;
}
Py_DECREF( py_result );
}
else
{
PyErr_Print();
fprintf( stderr,"Call failed\n" );
}
return result;
}
#endif
void function_done( void )
{
BJAM_FREE( stack );

View File

@@ -37,4 +37,10 @@ FUNCTION * function_unbind_variables( FUNCTION * f );
void function_done( void );
#ifdef HAVE_PYTHON
FUNCTION * function_python( PyObject * function, PyObject * bjam_signature );
#endif
#endif

View File

@@ -89,9 +89,6 @@ static RULE * enter_rule( OBJECT * rulename, module_t * target_module )
r->arguments = 0;
r->exported = 0;
r->module = target_module;
#ifdef HAVE_PYTHON
r->python_function = 0;
#endif
}
return r;
}
@@ -134,11 +131,6 @@ void rule_free( RULE * r )
if ( r->actions )
actions_free( r->actions );
r->actions = 0;
#ifdef HAVE_PYTHON
if ( r->python_function )
Py_DECREF( r->python_function );
r->python_function = 0;
#endif
}

View File

@@ -90,9 +90,6 @@ struct _rule
* the global module and be automatically
* imported into other modules
*/
#ifdef HAVE_PYTHON
PyObject * python_function;
#endif
};
/* ACTIONS - a chain of ACTIONs. */