1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
/* Copyright Vladimir Prus 2004. Distributed under the Boost */
/* Software License, Version 1.0. (See accompanying */
/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
#include "../native.h"
#include "../lists.h"
#include "../strings.h"
#include "../newstr.h"
#include "../variable.h"
/* Use quite klugy approach: when we add order dependency from 'a' to 'b',
just append 'b' to of value of variable 'a'.
*/
LIST *add_pair( PARSE *parse, FRAME *frame )
{
LIST* arg = lol_get( frame->args, 0 );
var_set(arg->string, list_copy(0, arg->next), VAR_APPEND);
return L0;
}
/** Given a list and a value, returns position of that value in
the list, or -1 if not found.
*/
int list_index(LIST* list, const char* value)
{
int result = 0;
for(; list; list = list->next, ++result) {
if (strcmp(list->string, value) == 0)
return result;
}
return -1;
}
enum colors { white, gray, black };
/* Main routite of topological sort. Calls itself recursively on all
adjacent vertices which were not yet visited. After that, 'current_vertex'
is added to '*result_ptr'.
*/
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);
else if (colors[adjacent_vertex] == gray)
; /* This is loop. Not sure what to do... */
}
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( PARSE *parse, FRAME *frame )
{
LIST* arg = lol_get( frame->args, 0 );
LIST* tmp;
LIST* result = 0;
int src, dst;
/* We need to create a graph of order dependencies between
the passed objects. We assume that there are no duplicates
passed to 'add_pair'.
*/
int length = list_length(arg);
int** graph = (int**)BJAM_CALLOC(length, sizeof(int*));
int* order = (int*)BJAM_MALLOC((length+1)*sizeof(int));
for(tmp = arg, src = 0; tmp; tmp = tmp->next, ++src) {
/* For all object this one depend upon, add elements
to 'graph' */
LIST* dependencies = var_get(tmp->string);
int index = 0;
graph[src] = (int*)BJAM_CALLOC(list_length(dependencies)+1, sizeof(int));
for(; dependencies; dependencies = dependencies->next) {
int dst = list_index(arg, dependencies->string);
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;
tmp = arg;
for (i = 0; i < order[index]; ++i, tmp = tmp->next);
result = list_new(result, tmp->string);
}
}
/* Clean up */
{
int i;
for(i = 0; i < length; ++i)
BJAM_FREE(graph[i]);
BJAM_FREE(graph);
BJAM_FREE(order);
}
return result;
}
void init_order()
{
{
char* args[] = { "first", "second", 0 };
declare_native_rule("class@order", "add-pair", args, add_pair, 1);
}
{
char* args[] = { "objects", "*", 0 };
declare_native_rule("class@order", "order", args, order, 1);
}
}
|