|
|
|
|
|
|
|
|
|
|
|
|
|
#include "../lists.h" |
|
#include "../mem.h" |
|
#include "../native.h" |
|
#include "../object.h" |
|
#include "../strings.h" |
|
#include "../variable.h" |
|
|
|
|
|
|
|
|
|
|
|
LIST * add_pair( FRAME * frame, int flags ) |
|
{ |
|
LIST * arg = lol_get( frame->args, 0 ); |
|
LISTITER iter = list_begin( arg ); |
|
LISTITER const end = list_end( arg ); |
|
var_set( frame->module, list_item( iter ), list_copy_range( arg, list_next( |
|
iter ), end ), VAR_APPEND ); |
|
return L0; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
int list_index( LIST * list, OBJECT * value ) |
|
{ |
|
int result = 0; |
|
LISTITER iter = list_begin( list ); |
|
LISTITER const end = list_end( list ); |
|
for ( ; iter != end; iter = list_next( iter ), ++result ) |
|
if ( object_equal( list_item( iter ), value ) ) |
|
return result; |
|
return -1; |
|
} |
|
|
|
enum colors { white, gray, black }; |
|
|
|
|
|
|
|
|
|
|
|
|
|
void do_ts( int * * graph, int current_vertex, int * colors, int * * result_ptr |
|
) |
|
{ |
|
int i; |
|
|
|
colors[ current_vertex ] = gray; |
|
for ( i = 0; graph[ current_vertex ][ i ] != -1; ++i ) |
|
{ |
|
int adjacent_vertex = graph[ current_vertex ][ i ]; |
|
if ( colors[ adjacent_vertex ] == white ) |
|
do_ts( graph, adjacent_vertex, colors, result_ptr ); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
colors[ current_vertex ] = black; |
|
**result_ptr = current_vertex; |
|
( *result_ptr )++; |
|
} |
|
|
|
|
|
void topological_sort( int * * graph, int num_vertices, int * result ) |
|
{ |
|
int i; |
|
int * colors = ( int * )BJAM_CALLOC( num_vertices, sizeof( int ) ); |
|
for ( i = 0; i < num_vertices; ++i ) |
|
colors[ i ] = white; |
|
|
|
for ( i = 0; i < num_vertices; ++i ) |
|
if ( colors[ i ] == white ) |
|
do_ts( graph, i, colors, &result ); |
|
|
|
BJAM_FREE( colors ); |
|
} |
|
|
|
|
|
LIST * order( FRAME * frame, int flags ) |
|
{ |
|
LIST * arg = lol_get( frame->args, 0 ); |
|
LIST * result = L0; |
|
int src; |
|
LISTITER iter = list_begin( arg ); |
|
LISTITER const end = list_end( arg ); |
|
|
|
|
|
|
|
|
|
int length = list_length( arg ); |
|
int * * graph = ( int * * )BJAM_CALLOC( length, sizeof( int * ) ); |
|
int * order = ( int * )BJAM_MALLOC( ( length + 1 ) * sizeof( int ) ); |
|
|
|
for ( src = 0; iter != end; iter = list_next( iter ), ++src ) |
|
{ |
|
|
|
LIST * dependencies = var_get( frame->module, list_item( iter ) ); |
|
int index = 0; |
|
LISTITER dep_iter = list_begin( dependencies ); |
|
LISTITER const dep_end = list_end( dependencies ); |
|
|
|
graph[ src ] = ( int * )BJAM_CALLOC( list_length( dependencies ) + 1, |
|
sizeof( int ) ); |
|
for ( ; dep_iter != dep_end; dep_iter = list_next( dep_iter ) ) |
|
{ |
|
int const dst = list_index( arg, list_item( dep_iter ) ); |
|
if ( dst != -1 ) |
|
graph[ src ][ index++ ] = dst; |
|
} |
|
graph[ src ][ index ] = -1; |
|
} |
|
|
|
topological_sort( graph, length, order ); |
|
|
|
{ |
|
int index = length - 1; |
|
for ( ; index >= 0; --index ) |
|
{ |
|
int i; |
|
LISTITER iter = list_begin( arg ); |
|
LISTITER const end = list_end( arg ); |
|
for ( i = 0; i < order[ index ]; ++i, iter = list_next( iter ) ); |
|
result = list_push_back( result, object_copy( list_item( iter ) ) ); |
|
} |
|
} |
|
|
|
|
|
{ |
|
int i; |
|
for ( i = 0; i < length; ++i ) |
|
BJAM_FREE( graph[ i ] ); |
|
BJAM_FREE( graph ); |
|
BJAM_FREE( order ); |
|
} |
|
|
|
return result; |
|
} |
|
|
|
|
|
void init_order() |
|
{ |
|
{ |
|
char const * args[] = { "first", "second", 0 }; |
|
declare_native_rule( "class@order", "add-pair", args, add_pair, 1 ); |
|
} |
|
|
|
{ |
|
char const * args[] = { "objects", "*", 0 }; |
|
declare_native_rule( "class@order", "order", args, order, 1 ); |
|
} |
|
} |
|
|