Skip to content

Commit 4c4d3ef

Browse files
jgarzikclaude
andcommitted
Implement recursive repr detection for lists
Add global repr_stack (64-entry fixed array) that tracks objects currently being repr'd. list_repr checks this on entry and returns "[...]" for self-referential lists instead of infinite recursion. This fixes: a=[]; a.append(a); repr(a) → "[...]" And: a=[0,1,2]; a.append(a); a.append(3); repr(a) → "[0, 1, 2, [...], 3]" Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 9c33aba commit 4c4d3ef

1 file changed

Lines changed: 70 additions & 0 deletions

File tree

src/repr.asm

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,51 @@ extern str_type
2929
extern str_repr
3030
extern fat_to_obj
3131

32+
; Recursion detection for container repr
33+
; Simple fixed-size stack of object pointers currently being repr'd.
34+
section .data
35+
align 8
36+
repr_depth: dq 0 ; current depth (number of entries)
37+
repr_stack: times 64 dq 0 ; up to 64 nested containers
38+
39+
section .text
40+
41+
; Check if ptr is in repr_stack. Returns 1 in eax if found, 0 if not.
42+
; Does NOT clobber rdi.
43+
repr_check_active:
44+
mov rcx, [rel repr_depth]
45+
test rcx, rcx
46+
jz .rca_not_found
47+
lea rax, [rel repr_stack]
48+
.rca_loop:
49+
dec rcx
50+
cmp [rax + rcx*8], rdi
51+
je .rca_found
52+
test rcx, rcx
53+
jnz .rca_loop
54+
.rca_not_found:
55+
xor eax, eax
56+
ret
57+
.rca_found:
58+
mov eax, 1
59+
ret
60+
61+
; Push ptr onto repr_stack
62+
repr_push:
63+
mov rax, [rel repr_depth]
64+
cmp rax, 64
65+
jge .rp_full
66+
lea rcx, [rel repr_stack]
67+
mov [rcx + rax*8], rdi
68+
inc qword [rel repr_depth]
69+
.rp_full:
70+
ret
71+
72+
; Pop from repr_stack
73+
repr_pop:
74+
dec qword [rel repr_depth]
75+
ret
76+
3277
; Internal buffer struct (on stack):
3378
; [rbp-8] = buf ptr
3479
; [rbp-16] = buf used (length of content)
@@ -76,6 +121,16 @@ DEF_FUNC list_repr, 24 ; buf ptr, used, capacity
76121

77122
mov rbx, rdi ; rbx = list
78123

124+
; Recursion check: if already repr'ing this list, return "[...]"
125+
mov rdi, rbx
126+
call repr_check_active
127+
test eax, eax
128+
jnz .lr_recursive
129+
130+
; Push onto repr stack
131+
mov rdi, rbx
132+
call repr_push
133+
79134
; Get count
80135
mov r13, [rbx + PyListObject.ob_size]
81136

@@ -156,6 +211,21 @@ DEF_FUNC list_repr, 24 ; buf ptr, used, capacity
156211

157212
pop rax ; return str
158213
mov edx, TAG_PTR ; ap_free clobbers rdx
214+
215+
; Pop from repr stack
216+
call repr_pop
217+
218+
pop r13
219+
pop r12
220+
pop rbx
221+
leave
222+
ret
223+
224+
.lr_recursive:
225+
; Return "[...]" for recursive reference
226+
CSTRING rdi, "[...]"
227+
call str_from_cstr_heap
228+
mov edx, TAG_PTR
159229
pop r13
160230
pop r12
161231
pop rbx

0 commit comments

Comments
 (0)