<dje42>In 2.0.9 smobs automagically inherit from <class> [I wouldn't necessarily call it proper inheritance, but if I print a smob type I see, e.g. $1 = #<<class> <gdb:value> 1cafb40> ] <dje42>I'm not seeing the same behaviour in git head. <dje42>Are there specific plans for what's changing here? <dje42>The behaviour I see in git head is that <gdb:value> (and all my smob types) are now undefined. <dje42>It's not critical or anything, just interested to know where things are heading. <mark_weaver>I wasn't aware of intentional changes along those lines. <mark_weaver>btw, it's more proper say that smob _types_ inherit from <class> <dje42>I can too when the situation calls for it. :) <mark_weaver>linas: it's a fluid. To get its value: (fluid-ref %default-port-encoding) <linas>oh, duh ok; I could have sworn that last time it printed the ref string directly <davexunit>mark_weaver: thanks for the review again. hopefully I'll have some time to fix things up tonight. <wingo>mark_weaver: it's correct, though i would rather it did a case on the car as validate-credentials does <wingo>but it is correct to apply it *mark_weaver looks at validate-credentials <wingo>that whole module is in need of `match' :) <ArneBab_>davexunit: my big one is just over 3 ☺ — finding hacking time mostly got harder when the little one learned to walk ☺ ***mario-go` is now known as mario-goulart
<linas>so .. ctrl-C in my bash terminal doesn't kill my program any more, when I use the REPL shell server ... <linas>how do I stop that? Its very anoying <davexunit>linas: I've noticed that as well, but haven't investigated further. <mark_weaver>well, that's just a consequence of the way Ctrl-C is handled. It's handled by the kernel, not by Guile. <wingo>take a look in (ice-9 top-repl) <wingo>see if call-with-sigint is doing the right thing <wingo>ah your program isn't running a main repl? in that case perhaps ctrl-c is being handled by the shell <wingo>the shell spawned in the separate thread... <mark_weaver>wingo: huh? what shell spawned in the separate thread? it's just I/O with the socket. <mark_weaver>The kernel only sends signals for Ctrl-C for terminal devices, not for bare sockets. <linas>My main is a C program .. it does a call-with-input-string or thereabouts every now and then. <mark_weaver>I think we'd need to allocate a psuedo-tty if we wanted job control in our REPL servers. <wingo>mark_weaver: sorry, when i said shell i meant repl <linas>As long as I don't use-modules repl server etc then ctrl-C from bash, to the main C process works fine. <mark_weaver>but psuedo-ttys are a pain, because at least on some systems, you have to arrange for some setuid helper to chown the tty devices over to you, etc. <davexunit>linas: am I understanding this: you start your main application which runs a repl server, then you press C-c in that tty, and nothing happens. correct? <wingo>linas: it seems that the repl server is catching sigint <wingo>perhaps it shouldn't do that ***sethalve_ is now known as sethalves
<wingo>check (system repl server) line 90 <linas>yes, the repl serve seems to be catching the sigint <davexunit>wingo: oh yeah, I did noticed that bit. can you think of why it's doing that? <wingo>davexunit: dunno, could be various reasons ;) my knowledge there is paged out :) <mark_weaver>linas: where are you typing Ctrl-C? are you trying to type Ctrl-C in the telnet session that's talking to the REPL server over a socket? <davexunit>since I've been in the repl modules lately, I also found a case where I can cause guile to segfault via the repl server. :( <davexunit>mark_weaver: I think linas is pressing Ctrl-C from tty that he used to start the process that spawned the REPL server. <linas>ctrl-C in the bash terminal, (and not in the repl telnet session) <mark_weaver>hmm. works for me, although I'm running this from within emacs. <linas>yeah, emacs almost aurely installs it's own signal handlers <linas>the order in which they run depends on how tthey're isntalled <mark_weaver>can you give me more precise instructions to reproduce the problem? <mark_weaver>I'm launching guile from within bash, in an xterm, then ,use (system repl server), then (spawn-server), then telnet from another terminal and get a REPL, then in the xterm I (sleep 10) and Ctrl-C interrupts it successfully. <linas>I start a C process, it ddoes a bunch of stuff, and then calls as C scm_whatever_from_string("(blah blah)"); <wingo>mark_weaver: $ meta/guile --listen -c '(let lp () (sleep 1) (lp))' <mark_weaver>I think wingo is probably right that the problem is 'call-with-sigint' in server.scm. <linas>I finally found system repl server and indeed, I see lines 70-90 which install a SIGINT handler ... and I can't imagine why that would be needed. <linas>and that is surely the root cause of what I'm experiencing. <wingo>i think they are there because the main thread repl installs a sigint handler -- so cargo culting <wingo>otoh it could be that ctrl-c in a main-thread repl could kill the off-thread listener... <linas>Well, ther would be a certain desired behaviour: if the user hits ctrl-C in the telnet session, you want to pull those bytes off the socket, and convert them into a real SIGINT or something, and halt some out-of-control scheme expr <wingo>otoh i think we have the ability to dispatch to the correct thread... <wingo>or at least to a thread that is listening for sigint <mark_weaver>if it's our signal handler that gets the signal, then yes, we do that. we write some bytes to a pipe, which gets read by a signal-handler thread, which queues an async for the desired thread. <linas>Hmm? You want the thread listening to the socket to notice some telnet RFC bytes that mean "interrupt", and then generate interrupt to the gone-wild thread. <wingo>i was just thinking about the case where you have a repl both on the main thread and server thread. <mark_weaver>linas: that sounds good, but it's hard to implement for several reasons. <linas>Maybe I've gone off topic, I started talking about something else <mark_weaver>first of all, I'm not aware of a portable way to send a signal to single thread, except by setting the signal masks for every thread in the process such that the signal can only be delivered to that one thread. <wingo>mark_weaver: i think in guile only the signal thread has its sigmasks set <mark_weaver>and iirc, a thread signal mask can only be set by the thread itself. <wingo>ah, humm, perhaps not then ;) <linas>I just meant that, perhaps the user just created some inf loop from that socket session, and now the user wants to kill it. <mark_weaver>linas: the other problem is that the same thread that's gone-wild is the thread that reads from the socket, so it can't very well watch for Ctrl-C. <linas>oh. So, indeed, that woudn't work. <mark_weaver>If we want to handle Ctrl-C, I still think the most sane approach is to actually allocate a psuedo-tty. <mark_weaver>if we want to handle Ctrl-C within REPL servers, I mean. <mark_weaver>but unfortunately that's a huge portability pain, dealing with the fact that the psuedo-tty devices have to be chown'd, which requires a setuid helper in the general case. <linas>I don't understand what a pseudo-tty has to do with it <mark_weaver>Ctrl-C is converted to a signal by the kernel. that's how it's usually done. <mark_weaver>but the kernel only recognizes Ctrl-C (and a few other job control keys) for terminal devices. <linas>mark_weaver, you're misunderstanding me on several levels <mark_weaver>a socket is not a terminal device. it doesn't support that kind of thing. <linas>right, a socket is not a terminal, and when telnet sees a ctrl-C, it converts it into some short byte sequence, according to some RFC <linas>so all that the guile socket-listening repl server would see is a few odd bytes. <linas>0xf4 or 0xf5 0x16 according to my notes. <mark_weaver>ah, that's an additional complication I didn't know about. <linas>It would be *nice* if the system repl server noticed those bytes, and stopped whatever guile thread was running. <linas>but that is a very distinct problem from my initial complaint. <mark_weaver>If telnet actually sent the bare ^C over the socket, then a psuedo-tty pair on the server-side could detect the Ctrl-C and cause the kernel to send a SIGINT to Guile. <linas>yes, that would be one solution I suppose. But as you say, it seems complicated, olde-fashioned, and might not really do what is wanted, anyway <mark_weaver>well, I suppose another way would be to introduce a layer of indirection, where we would have a thread that just passes bytes to the thread really doing the work, but intercepting those special bytes. <linas>when all the user wanted was an "oops please top my inf-loop" <mark_weaver>but there's still the problem of how to send a SIGINT to a specific thread, as opposed to the whole process. <mark_weaver>portable POSIX signals aren't really flexible enough to send a signal to a specific thread, alas. <mark_weaver>well, it can be done if you decide in advance which thread will receive SIGINT. <mark_weaver>and if every thread in the system cooperates by setting its thread mask appropriately, so that only one thread can receive SIGINT. <linas>I see no reason for it to be an actual signal. <linas>maybe the guile VM sometimes polls something somewhere ... the goal would only be to get the VM's attention <mark_weaver>well, if it's scheme code that's in a loop, then you can set a system async for that thread. <mark_weaver>but if the thread is blocked on a system call, or stuck in C code, then an async won't interrupt it. <linas>anyway, I've wandered very very far off-topic. <mark_weaver>if it's blocked in a system call, then signals are the only way I know of to force the system call to return EINTR which then causes Guile to check for asyncs. <linas>oh right, yes if its blocked, OK. never mind, lets abandon this idea. <linas>I was just guessing that perhaps that was the logic behind wingo 's "cargo cult" comment ... <mark_weaver>okay, so back to the question of "why do we need this awful 'call-with-sigint' thing... <mark_weaver>I have a guess that it might not be needed anymore in the stable-2.0 branch, thanks to a fix to 'accept' that Ludovic recently applied. <mark_weaver>Until recently, 'accept' did not automatically retry in the case of EINTR. <mark_weaver>Ludovic fixed that in December: 032a16fced2128626e13e6964ea39f1c8fe44091 <mark_weaver>oh, well, I don't even see how 'call-with-sigint' would have helped with that, now that I think about it. *mark_weaver looks at the git logs to see who wrote this code. <linas>"cargo cult" may be a really good explanation <mark_weaver>I'm tempted to just remove it and see how things work without it. <mark_weaver>wingo: from the git logs, it seems that you're the one who put wrapped that 'call-with-sigint' around the call to 'accept', in 2010. <madsy>Heh.. EINTR is one of the weirdest Linux quirks I think :) <wingo>mark_weaver: i don't doubt it :) but i don't know why either <madsy>Yes, it's a Unix thing. But people use Linux now, not the original Unix <linas>well, presumably macosx does eintr too .. no clue what windows does <mark_weaver>I'm going to boldly remove that cruft and see what happens. <wingo>mark_weaver: actually the revision is attributed to top-repl.scm <wingo>so it was a copy-and-paste thing <mark_weaver>'call-with-sigint' exists in top-repl.scm, yes. but wrapping it around the call to 'accept' surely didn't come from top-repl.scm <wingo>sure, probably it was a read in top-repl... <mark_weaver>in top-repl, it's wrapped around the entire REPL (start-repl) <mark_weaver>anyway, I'm not complaining, just trying to figure out how to fix things now. I'm amazed at the quantity and quality of your contributions, as always :) <wingo>hehe, there is some hopefully correct code and also a bunch of bogus code ;) <tupi>heya! everytime i have to 'play' with regexp, it seems i forgot absolutely everything [which isn't much really :) i use to know about it, how frustrating :) <tupi>do we have a way to take a command line (reg)expression and convert it to something make-regexp accept? <tupi>mark_weaver: such as "*.png", "mosaic-tiles-*.eps" ... <mark_weaver>those aren't regexps, those are shell glob patterns. <linas>thanks wingo, mark_weaver. Sometimes, writing code is like juggling and you are so busy trying tnot to drop something that some strange things happen... <tupi>yes, tx, shell global patterns then? <mark_weaver>linas: I think simply removing the 'call-with-sigint' is the right thing. it fixes your problem, and from playing with it a bit, I don't see any new problems. <linas>Yes, I tried that, it seems to fix things. Got a warning about code newer than compiled cache, even! <mark_weaver>tupi: I'm not aware of anything that does that conversion off-hand. <tupi>ok, that's what i tought, tx <mark_weaver>wingo: I'm thinking of boldly removing that 'call-with-sigint' from stable-2.0. Any objection? <dje42>mark_weaver: for gdb+guile (and possibly other guile-embedding apps) IWBN if guile could use the app's SIGINT handler, and guile provide a signal-safe routine to record the SIGINT with guile. <dje42>Something akin to what python provides would be nice. <wingo>tupi: i had code for that at some point... <mark_weaver>dje42: I'll look into it, though I'm not sure it'll be easy to fix in 2.0. <wingo>(gnome gw support slib) has glob:make-matcher <dje42>Python provides two routines: one to record the sigint and one to see of the sigint is set (clearing it in the process). <mark_weaver>I looked deeply into guile's handling of signals a few months ago, and have some thoughts about how to improve things. <tromey>it would suffice to have an async-signal-safe way to schedule a scm async <tromey>the scm async could check the gdb flag <tupi>wingo: nice! i should have it here then, looking <mark_weaver>right now, we use a single global mutex to protect every thread's list of pending asyncs. <mark_weaver>I already want to change things to allow queuing of an async directly from the signal handler, so that we can avoid the "writing via pipe to the dedicated signal handling thread" thing we currently do, with its associated latency that causes various problems. <dje42>I still need to look into what guile provides today with 2.0.0. <mark_weaver>tromey: each thread has its own list of pending asyncs. do you need an async-signal-safe way to schedule an async for an arbitrary thread, or would it suffice to schedule an async for the same thread the signal handler interrupted? <mark_weaver>well, I suppose the more general problem can be solved given a solution to the simpler one. <tromey>I think gdb generally wants to control sigint and have it always go to the main thread <mark_weaver>you could schedule an async for the current thread which, when run, uses a mutexes as needed to schedule an async for an arbitrary thread. <mark_weaver>tromey: well, iirc, that requires that all other threads in the process have blocked SIGINT, no? <tromey>yeah. of course in ordinary gdb there are no other threads <tromey>with python there might be but IIRC python forwards all signals to the main thread <mark_weaver>I think what you want is doable, but it will be a big change to the data structures for asyncs. <mark_weaver>I hadn't really been considering such a big change for 2.0. <mark_weaver>but if it's important enough, I suppose it might be doable. <mark_weaver>what are the consequences of not having this feature? <tromey>I am not sure. I didn't read the new threads yet <tromey>I guess C-c not working properly with gdb+guile, though I don't know the exact failure mode <dje42>The main problem is handling the transition across gdb->guile->gdb->python or whatever. <wingo>by default guile doesn't install a sigint handler iirc <mark_weaver>it's an ugly hack, but I wonder if something like this would help: have a global variable that indicates whether guile code is currently being run. install a signal handler for SIGINT that checks that variable and calls either the Guile signal handler or GDB's. <wingo>so unless you run a repl or something, guile shouldn't bother you... <dje42>If a signal is left queued in one and not forwarded, and something later installs its own handler, the earlier queued signal can magically appear much later. <wingo>perhaps i am reading partial conversations and just making noise tho <dje42>wingo: We may have sufficiently long running scheme code that we want it interruptible. we certainly don't want to preclude that anyway. <wingo>sure; you could schedule an async in that case <dje42>mark_weaver: we have said global variable today <mark_weaver>wingo: the problem is we don't have a way to schedule an asyncs from a signal handler. <wingo>to schedule asyncs in an async-signal-safe way... *wingo prints out posix, sets it on fire <tromey>you have to use the scm sigaction wrapper <mark_weaver>I thought about it in depth a few months ago, and seem to recall coming up with a reasonable way of doing it, but now I've forgotten the details. <dje42>yes, I've found scm sigaction <mark_weaver>obviously it involved careful use of sigatomics in the data structure. <mark_weaver>I seem to recall thinking that I might need a thread-local 'critical section' flag that would be checked from the signal handler, and maybe in that case the signal handler would put the new async somewhere else, and the main code would check for that after the critical section, or something terrible like that. <mark_weaver>alas, it's all down the memory hole now. I'll have to rethink it again. <mark_weaver>one serious complication is that this method would assume that each thread's async queue could only be accessed by that thread, period. so we'd need a way to schedule asyncs for another thread by somehow sending it a message by another means. <dje42>It's fast enough to test a flag, the SIGINT handler could set that. And have whatever calls "check for asyncs" check that flag? <tromey>SCM_TICK acquires a mutex - that seems pretty heavy <wingo>can a signal handler use atomic operations? <mark_weaver>so we could use libatomicops, which we already depend on via libgc anyway. <wingo>i think thr->pending_asyncs is the flag to set <wingo>it's the flag checked by the vm anyway (on backwards jumps and function calls) <wingo>who knows if it is being set properly though... <dje42>it's checked by the vm anyway <wingo>yes but probably there should be barriers around it, or just use atomic ops <mark_weaver>yeah, we have to be careful of one thread seeing writes by another thread in a different order. <wingo>or not seeing a write at all <mark_weaver>I thought that cache systems were supposed to make a best effort to propagate writes in some reasonable time frame. <dje42>x86 is much better in this regard, in general though ... <dje42>can only the main thread check this flag? (maybe it needs to be a different flag) that could suffice for many embedding apps <linas>cache write-back logic on modern cpus is crazy-complex. Don't know about x86, but know some others. <dje42>plus, or reference sake, we don't care if several SIGINT's get squashed into one. (we do care about losing one a bit) <mark_weaver>I remember that x86 has at least one very helpful feature in its weak memory model. I forget the exact details, but it has to do with data dependencies. <ArneBab_>wingo: do you need some unlimited bandwidth hosting? <mark_weaver>something along the lines of this: if thread A initializes a data structure and then writes its pointer somewhere, and then thread B reads the pointer, normally you have to use barriers to ensure that thread B sees the initialized structure before it sees the updated pointer. <ArneBab_>slow, crappy features, unlimited bandwidth, a few GiB still free ☺ <wingo>i have a linode and it's fairly cheap and works <mark_weaver>with x86 there's some kind of automatic dependency checking that allows one or more of these barriers to be eliminated, or made much cheaper, or something like that. <mark_weaver>very smart of intel. it means that most code that works anywhere will work on intel, whereas lots of code that works on intel will subtly break on other systems if not written competently. <mark_weaver>dje42: I'm reluctant to hack in something like that into our async system, but I dunno, if I can't come up with something better, maybe something to consider for 2.0. <dje42>I dunno. It's still very sketchy, but I think there's something that needn't be a hack at all. :-) <tromey>this signal delivery thread seems like trouble <mark_weaver>dje42: well, essentially what we're talking about is making a single async job that's handled specially, such that it can be queued by setting a flag instead of adding to the queue. <mark_weaver>I confess that in the end, it's more important to have something that gets the job done. but it's distateful. <dje42>A signal handler can't do much. We have to build on that. <mark_weaver>but why should SIGINT be privileged? what about all the other signals? <dje42>No suggestion that it need be. For one it's an important one, but I'm also using it as a proxy for things like it. <mark_weaver>anyway, I'll think on it and see if something better is feasible in 2.0. <mark_weaver>well, how would you handle multiple signals using a single flag? <mark_weaver>I suppose we could have one flag for each signal number, and another flag that's set no matter which signal it is. <dje42>That's one thing that came to mind. <mark_weaver>well, even that's no good, because if the signal is delivered to any thread other than the main thread, then you'll have memory ordering issues again, and then multiple flags becomes more tricky. hmm. <dje42>Well, let's get back to enumerating the things a signal handler is allowed to do. <mark_weaver>ah, right, libatomicops should be usable from the signal handler, yes. <mark_weaver>so okay, that takes care of the memory ordering problem. <dje42>[you don't have to do it now ... I'm not trying to take anyone away from something they'd rather be working on at the moment] <mark_weaver>I guess it's doable. the signal handler would set the per-signal flag first, then a memory barrier, and then set the main flag. <mark_weaver>the async checker would atomically test-and-clear the main flag, memory barrier, then scan the per-signal flags. <mark_weaver>we already have this dedicated signal-handling thread in guile that reads from a pipe. <mark_weaver>guile-established signal handlers write to the pipe. <mark_weaver>we could provide an API that works by writing to the same pipe. <mark_weaver>and extend the signal-handling thread to handle the new messages. <wingo>that's for handling signals, not waking up, right? <wingo>isn't the problem interrupting other threads, not the signal thread? <mark_weaver>right, but the signal thread can safely queue asyncs, because it can lock mutexes. <mark_weaver>its job is basically to queue asyncs on the appropriate thread that run the user-specified signal handler. <mark_weaver>well, I remember verifying that that was recognized as safe. <mark_weaver>indeed, that's a common method for escaping the limits of a signal handler: just write to a pipe that's read by a dedicated handler thread. <dje42>Is the pipe cleared on return from things like scm_with_guile? [just checking] <dje42>Hmmm, that's probably not sufficient. <mark_weaver>it's cleared whenever Guile's signal-handling-thread is scheduled by the kernel. <mark_weaver>my answer was based on the probably mistaken assumption that meant "drained". <dje42>I think you understood correctly. I'm just wondering about the case of a SIGINT being queued, and then guile returning to gdb. <mark_weaver>dje42: btw, you could implement this kind of technique even for existing versions of guile 2.0. <mark_weaver>dje42: you could create your own dedicated thread, with its own pipe, that does what I'm describing. <tromey>the scm async can just check quit_flag and do nothing if it is already clear <mark_weaver>certainly, I think we should provide an easier way of doing this. <mark_weaver>fyi, 'signal_delivery_thread' in scmsigs.c is the code for our current signal-handling thread. <mark_weaver>I see that it reads from the pipe outside of guile mode. not sure off-hand why, but it's probably best to emulate that. <dje42>Still not sure how to handle gdb calls guile, SIGINT -> pipe, guile returns, gdb SIGINT handler now in control, SIGINT, gdb processes SIGINT, gdb calls guile <dje42>mark_weaver: seeya, and thanks <tromey>the guile async has to check quit_flag <mark_weaver>actually, it's probably no longer necessary to read outside of guile mode. at some point in the past, a blocked thread in guile mode would block GC, but no longer. <mark_weaver>dje42: if you're worried that a SIGINT, delayed by the pipe+thread, might interrupt the wrong guile evaluation, then you could have a global (wrapping) counter, incremented each time gdb calls guile. <mark_weaver>when you want to interrupt guile, you could write the value of that counter into the pipe. <dje42>naw, the signal handler just has to set the flag and write to the pipe. <mark_weaver>and when the async runs, it could check to make sure the counter is the same. <dje42>I was thinking about the counter idea though. :) <mark_weaver>if you do that, just make sure it's an unsigned counter, so that wrapping is well-defined and handled properly. (always check with == not < or >) <tromey>I don't think a counter is needed <tromey>it's not really possible, I think, to interrupt the wrong guile computation <tromey>if something else handles the sigint then the flag will have been cleared <tromey>if not, then you want to handle it asap anyway <mark_weaver>sorry this is such a pain. I'll see about getting a better solution into Guile soon. <mark_weaver>it's the "soon" at the end of the sentence, which he interprets as his name. <mark_weaver>and then, the "is" in the sentence made him think I was asking him to store an entry into his association table. <sneek>Its been said that fire is hot <mark_weaver>I guess he has a couple of different names he responds to. <mark_weaver>it's dsmith's bot, but he's not around now apparently., <taylanub>mark_weaver: Hi, apparently my memory was faulty re. the supposed R6RS/R7RS implementation: Sagittarius claims to conform to R6 and 7RS, but jcowan hasn't been able to build it to test that claim. (jcowan only implements Chibi, which is R5RS/R7RS, apparently he has nothing to do with Sagittarius.) He also hinted that supporting both R6 and 7RS' usages of | should be possible because R7RS symbols can't start with a number, though Guile <taylanub>symbols can so I guess that doesn't help. <mark_weaver>Is jcowan a significant contributor to Chibi? I thought it was mostly written by Alex Shinn. <mark_weaver>well, wait. the issue is not parsing symbols, but rather parsing numbers followed by a pipe-quoted symbol without intervening space. <taylanub>Wait, sorry, I think I confused that again. :\\ He often talks about Chibi so I keep confusing it. <taylanub>(In any case he's not implementing an R6RS/R7RS reference implementation.) <mark_weaver>My impression is that jcowan isn't a very experienced coder. <taylanub>mark_weaver: The R6RS uses | only for specifying a mantissa width, as in <n>|<m> where <m> is a number, no ? So |<m> can't possibly begin a symbol ? <taylanub>I also kind of got the impression that he just took (or was given) the coordinative/social role in R7RS-small standardization, but I don't know anything about him outside of the scheme-reports ML. <mark_weaver>I think R6RS says that 10|10 is a number, and then comes the string "|". <mark_weaver>I think R7RS says that 10 is a number, followed by the symbol |10 "| <taylanub>Well an R7RS symbol can't start with a digit, so that can't be. <taylanub>(From my understanding of what jcowan meant.) <taylanub>Hrm, let me just check what R7RS actually says re. syntax ... <taylanub>You're right, an <identifier> can be <vertical line> <symbol element>* <vertical line>, where <symbol element> can be <any character other than <vertical line> or \\> <mark_weaver>the good news is that, in practice, people actually put spaces between items in a list. <mark_weaver>btw, guile in git now supports |...| symbol syntax, if you (read-enable 'r7rs-symbols) and (print-enable 'r7rs-symbols) <mark_weaver>and the r7rs-wip branch passes the Chibi R7RS test suite. <mark_weaver>although 'equal?' is not yet conformant. The test suite doesn't test that. <mark_weaver>(and you need to set some read and print options to make 'read' and 'write' conform) <mark_weaver>I was hoping to get this all into 2.0.10, but I think it will have to wait until .11. <mark_weaver>alas, our methods of extending 'equal?', 'read', and 'write' to user-defined objects are not sufficient to support cycle-detection properly. <mark_weaver>in all three cases, there needs to be an additional 'context' that gets passed down the hierarchy. <taylanub>Ah, I thought the remaining issues were due to bytevectors, were those resolved ? <mark_weaver>it can sort of be hacked for 'read' and 'write' by associating the context with the port, but for 'equal?' I'm at a loss. <mark_weaver>well, there's a solution for bytevectors in the r7rs-wip that's workable but perhaps not ideal. <mark_weaver>I'm not entirely sure what's the best solution there. <mark_weaver>so yeah, for all these reasons, better to push R7RS to .11 than to rush these decisions, I think.