@@ -70,11 +70,11 @@ void pickle::step() {
70
70
71
71
static bool is_primitive_type (object* x) {
72
72
if (x == NULL ) return true ;
73
- size_t i = 0 ; while (primitives[i] != NULL ) { if (x->type == primitives[i]) break ; }
73
+ size_t i = 0 ; while (primitives[i] != NULL ) { if (x->type == primitives[i]) break ; i++; }
74
74
return primitives[i] != NULL ;
75
75
}
76
76
77
- int prim_cmp (object* a, object* b) {
77
+ int eqcmp (object* a, object* b) {
78
78
if (a == b) return 0 ;
79
79
if (a == NULL ) return -1 ;
80
80
if (b == NULL ) return 1 ;
@@ -88,15 +88,15 @@ int prim_cmp(object* a, object* b) {
88
88
object* assoc (object* list, object* key) {
89
89
for (; list; list = cdr (list)) {
90
90
object* pair = car (list);
91
- if (!prim_cmp (key, car (pair))) return pair;
91
+ if (!eqcmp (key, car (pair))) return pair;
92
92
}
93
93
return NULL ;
94
94
}
95
95
96
96
object* delassoc (object** list, object* key) {
97
97
for (; *list; list = &cdr (*list)) {
98
98
object* pair = car (*list);
99
- if (!prim_cmp (key, car (pair))) {
99
+ if (!eqcmp (key, car (pair))) {
100
100
*list = cdr (*list);
101
101
return pair;
102
102
}
@@ -171,37 +171,90 @@ void splice_match(pickle* vm, object* args, object* env, object* cont, object* f
171
171
// TODO(sm);
172
172
}
173
173
174
- static void count_pointers () {
174
+ static void make_refs_list (pickle* vm, object* obj, object** alist) {
175
+ again:
176
+ DBG ();
177
+ if (obj == NULL || obj->type != &cons_type) return ;
178
+ object* entry = assoc (*alist, obj);
179
+ if (entry) {
180
+ cdr (entry) = vm->make_integer (2 );
181
+ return ;
182
+ }
183
+ vm->push (vm->cons (obj, vm->make_integer (1 )), *alist);
184
+ make_refs_list (vm, cdr (obj), alist);
185
+ obj = cdr (obj);
186
+ goto again;
187
+ }
175
188
189
+ // returns zero if the object doesn't need a #N# marker
190
+ // otherwise returns N (negative if not first time)
191
+ static int64_t reffed (pickle* vm, object* obj, object* alist, int64_t * counter) {
192
+ object* entry = assoc (alist, obj);
193
+ if (entry) {
194
+ int64_t value = vm->unwrap_integer (cdr (entry));
195
+ if (value < 0 ) {
196
+ // seen already
197
+ return value;
198
+ }
199
+ if (value == 2 ) {
200
+ // object with shared structure but no id yet
201
+ // assign id
202
+ int64_t my_id = *counter++;
203
+ // store entry
204
+ cdr (entry) = vm->make_integer (-my_id);
205
+ return my_id;
206
+ }
207
+ }
208
+ return 0 ;
176
209
}
177
210
178
- void dump (object* x) {
179
- if (x == NULL ) printf (" NULL" );
180
- else if (x->type == &cons_type) {
181
- // Try to print a Scheme list
211
+ static void print_with_refs (pickle* vm, object* obj, object* alist, int64_t * counter) {
212
+ if (obj == NULL ) {
213
+ printf (" NULL" );
214
+ return ;
215
+ }
216
+ #define PRINTTYPE (t, f, fmt ) else if (obj->type == t) printf(fmt, obj->f)
217
+ PRINTTYPE (&string_type, as_chars, " \" %s\" " );
218
+ PRINTTYPE (&symbol_type, as_chars, strchr (obj->as_chars , ' ' ) ? " #|%s|" : " %s" );
219
+ PRINTTYPE (&integer_type, as_big_int, " %" PRId64);
220
+ PRINTTYPE (&float_type, as_double, " %lg" );
221
+ PRINTTYPE (&c_function_type, as_ptr, " <function %p>" );
222
+ PRINTTYPE (NULL , as_ptr, " <garbage %p>" );
223
+ #undef PRINTTYPE
224
+ else if (obj->type != &cons_type) printf (" <%s:%p>" , obj->type ->name , obj->as_ptr );
225
+ else {
226
+ // it's a cons
227
+ // test if it's in the table
228
+ int64_t ref = reffed (vm, obj, alist, counter);
229
+ if (ref < 0 ) {
230
+ printf (" #%" PRId64 " #" , -ref);
231
+ return ;
232
+ }
233
+ if (ref) {
234
+ printf (" #%" PRId64 " =" , ref);
235
+ }
236
+ // now print the object
182
237
putchar (' (' );
183
238
for (;;) {
184
- dump (car (x));
185
- x = cdr (x);
186
- if (x && x->type == &cons_type) putchar (' ' );
239
+ print_with_refs (vm, car (obj), alist, counter);
240
+ obj = cdr (obj);
241
+ if (reffed (vm, obj, alist, counter)) break ;
242
+ if (obj && obj->type == &cons_type) putchar (' ' );
187
243
else break ;
188
244
}
189
- if (x ) {
245
+ if (obj ) {
190
246
printf (" . " );
191
- dump (x );
247
+ print_with_refs (vm, obj, alist, counter );
192
248
}
193
249
putchar (' )' );
194
250
}
195
- else {
196
- #define PRINTTYPE (t, f, fmt ) if (x->type == &t) printf(fmt, x->f)
197
- PRINTTYPE (string_type, as_chars, " \" %s\" " );
198
- else PRINTTYPE (symbol_type, as_chars, strchr (x->as_chars , ' ' ) ? " #|%s|" : " %s" );
199
- else PRINTTYPE (integer_type, as_big_int, " %" PRId64);
200
- else PRINTTYPE (float_type, as_double, " %lg" );
201
- else PRINTTYPE (c_function_type, as_ptr, " <function %p>" );
202
- else printf (" <%s:%p>" , x->type ->name , x->as_ptr );
203
- #undef PRINTTYPE
204
- }
251
+ }
252
+
253
+ void pickle::dump (object* obj) {
254
+ object* alist = NULL ;
255
+ int64_t counter = 0 ;
256
+ make_refs_list (this , obj, &alist);
257
+ print_with_refs (this , obj, alist, &counter);
205
258
}
206
259
207
260
}
0 commit comments