Hacker News new | past | comments | ask | show | jobs | submit login
COMEFROM (wikipedia.org)
82 points by kick on Oct 19, 2019 | hide | past | favorite | 24 comments



My future programming language implements this and GO for better debugging, but the downside is the debugger is named “cotton eyed joe”.


Support ticket #39482: "The programming language is nice, but if it hadn't been for that piece of shit debugger, I'd have been married a long time ago..."


see you at the alter


Well done! XD


Hah, I got a kick out of that.


One of my favorite implementations of comefrom is in threaded interval. Multiple comefroms from the same target are treated as a fork and is the only way to create a new thread. The only way the new threads can communicate is by disabling statements.


The parent probably meant Threaded Intercal (https://en.wikipedia.org/wiki/INTERCAL).


COMEFROM is basically dependency injection. :)

I'm only sort of joking.

Think about it: When you inject a dependency (say Java spring @Autowired), then you are asking spring to run all sort of code, at the point where it injects your variable with autowired.

Spring needs to instantiate your requested object, and everything that it depends on - it might be a lot of code.


Isn't this just a Phi node?

</compilerdeveloperjoke>


Jokes aside, another possible use is to implement an internal cooperative multi-tasking similar to that used in Windows 3.x and classic Mac OS. If I remember correctly, long running tasks in Windows had to pepper their code with calls to yield() in order to be good Windows citizens, similar to label X when using COMEFROM X.

https://en.wikipedia.org/wiki/Cooperative_multitasking


This is a bit of a stretch. The way cooperative systems worked is that blocking or long-running calls tended to yield. Most of the time the explicit yields therefore weren't needed, you could just wait until the next blocking call.

You could replace the cooperative system with preemption and most people wouldn't notice the difference. That's exactly what Win32 did, the programming model and APIs were largely philosophically the same.

Today's preemptive multitasking systems also sometimes call the scheduler on syscalls, effectively doing the same as those cooperative systems did. And eg. Linux has sched_yield. It's pretty common even today to see that wherever you have something close to a busy loop.


Win16 programs just called GetMessage() in a loop. If there was a message for that window proc, then that call returned and once it did, that window proc had the CPU - and nothing could preempt it. Nothing else in the system would get CPU time unless that window proc completed its activity and looped back to call GetMessage() again, or alternatively, calls yeild(). That's it. Yield() was intended to be used where the window proc needed to do something long running, thus giving other processes a chance to process their window messages.

> You could replace the cooperative system with preemption and most people wouldn't notice the difference.

Oh yes we did notice! I beta-tested several MS OSes (Win3.0, Win3.1, WfW3.11, Win95, NT3.0, Win98). The difference between the cooperative multitasking on Win16 and the preemptive multitasking on Win32 was like chalk and cheese! Before that, a single misbehaving app could hang your entire system at any time. Needed a hard reset or power cycle. At least with Win9x, it took a misbehaving driver to hang your PC. A misbehaving app would (usually) only take out itself.

> philosophically the same

Diametrically opposed. In one model, the active process voluntarily relinquishes the CPU, and until it does, nothing else will run. In the other, the scheduler pulls the CPU out from under the running thread, to switch to another thread.

EDIT: spelling.


You are talking down to me in your technical explanations. I know how it worked.

My point is the cooperative model was an approximation of what you get with preemption. Eventually something yields. A casual user and even many programmers would most certainly not notice a huge difference outside of extraordinary circumstances. In many instances you write code the same way. In many instances a user sees more or less the same thing.

A busy loop without a yield or a hanging program is one of those exceptional circumstances. It didn't happen even a majority of the time.

If the model were radically different, then Win32 would look way more different than Win16 than it did. But you can change the model without throwing out most APIs. If it were anything like the joke "come from" proposals, that wouldn't be the case.


I can see this being used to perform print debugging or elisp-style function advice.

https://www.gnu.org/software/emacs/manual/html_node/elisp/Ad...


See aspect oriented programming and cross-cutting concerns.


defadvice is ugly elisp hack that implements just enough of CLOS that you need for some interesting subset of aspect oriented programming.


How? It allows you can add the jump to your code, but doesn’t provide a method to jump back to the original code.


If it takes a parameter, as mentioned it sometimes does, then the advising function can jump back to an address given by a parameter, +1.

Ie,

   comefrom 80
   ... stuff
   goto 81
You then design your methods to always have a NOP at the start, to allow comefrom to inject its jump.


What's the difference between COMEFROM and attaching a hander to an event?


COMEFROM doesn’t execute whatever is at the place where the jump to the COMEFROM happens, and doesn’t provide a way to return there.

(Aside: for a variation on COMEFROM, see Cobol’s ALTER (https://en.wikipedia.org/wiki/COBOL#Self-modifying_code).)


goto is one of those things that you're actively discouraged from using or ever thinking about without ever knowing why or having to read "Goto Considered Harmful." goto at least in C is the only way to implement exception handling in a way that properly separates the good path from the bad path without having many sets of nested conditionals after which most of the line becomes whitespace. It is also the only way to exit a deeply nested loop as well. It should be discouraged, especially jumping backwards, but it is necessary in some few cases, at least in C particularly.


I think goto in C with its labels, as a last resort where C's library of structured control flow constructs fail, is a much less bad thing than GOTO in BASIC with its line numbers and much more limited structured control flow.


You can implement sane exception handling in C by the means of few simple preprocessor macros. In fact, this is how exception handling is implemented in ObjectiveC and how it is done in Windows (and this hack is also the reason why Windows have three different ABIs wrt. exception handling)

And in fact, implementing Common Lisp style condition system that can be used from C code in reasonably straightforward way involves only 1kLoC of cpp magic, been there, done that ;)


I think Dijkstra would say that C is lacking some essential higher-level constructs, not that goto has its uses.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: