2021-06-25 03:50:38 MrMobius: You can exit BEGIN..AGAIN with WHILE 2021-06-25 03:51:26 i.e. BEGIN .. cond WHILE .. AGAIN THEN 2021-06-25 08:36:47 hello 2021-06-25 09:33:24 -!- ChanServ changed mode/#forth -> +o Bogen85 2021-06-25 12:10:04 <+KipIngram> brainfunnel: Yes, sequencing is really a more suitable word, but the whole Forth community uses "threading," so... What would you call the list of pointers to words that gets executed? 2021-06-25 12:18:34 Yeah, I think so, or just "list." 2021-06-25 12:18:47 "definition list," or something like that. 2021-06-25 12:19:11 It functions as code, so "Forth code" would work too. 2021-06-25 12:19:33 I sometimes use the word "body" to refer to that part of a definition. 2021-06-25 12:19:44 As distinct from the "header." 2021-06-25 12:20:30 In a traditional FIG system the body immediately followed the header, so the header had a pointer to the code associated with the word and then the body came right after. 2021-06-25 12:20:50 In my system headers and bodies are in separate memory regions, so my header has the usual pointer to code and then a pointer to the body. 2021-06-25 12:21:43 That makes all words "re-vectorable." The list items in compiled definitions are pointers to headers. So by changing the body pointer of a header you can completely redefine that word, and all compile 2021-06-25 12:22:21 In FIG "vector words" were special - that extra level of indirection was added above and beyond the standard definition. But it's a "perk" of my architecture that I can do that to any word, any time. 2021-06-25 12:22:38 The penalty is that my headers are one cell larger than they would be in a FIG system. 2021-06-25 12:23:18 But by separating the pieces like that, my bodies are contiguous with one another, so execution can flow right from one body into the next body if I want it to. 2021-06-25 12:23:24 So words can have multiple entry points. 2021-06-25 12:58:45 proteusguy: hi 2021-06-25 14:28:54 KipIngram: Interesting. Do the bodies contain pointers to the headers, then? 2021-06-25 14:39:04 Yes, that's correct. Each body is a list of pointers to the headers of the component words. 2021-06-25 14:41:16 To the code field of the header, specifically. So the inner interpreter loads an item from the list, de-references it (so that now it's pointing to the code field of that word's header) and does a jump 2021-06-25 14:41:18 pointer just after the code pointer (still in the header), and that gives it a pointer to the first item of the new definition, which it just loads into IP (after saving IP on the return stack). 2021-06-25 14:41:47 So I can globally replace a word's definition by creating the new definition body and aiming that second pointer at the new list. 2021-06-25 14:42:46 One nuance - if the definition I replaced was a "second entry point" of some larger definition, then the fall-through from the earlier part would still use the old definition - it would have no way of k 2021-06-25 14:42:59 What I'm talking about here is this: 2021-06-25 14:43:12 : foo ... : bar ... ; 2021-06-25 14:43:29 I could change the definition of bar by doing that pointer replacement. 2021-06-25 14:43:45 But when foo executed it doesn't use that pointer to find bar - it just "flows through." So that wouldn't change. 2021-06-25 14:44:20 Separating headers and bodies means that the two ... sections in that example are immediately adjacent to each other, with nothing in between. 2021-06-25 14:44:45 In a FIG system you can't do that - the header for bar goes right after the end of foo, so foo would have to end with a ; or else you'd try to execute into a header. 2021-06-25 14:45:44 As a side note, once you're finished compiling references to a word, you no longer need the name string and the link field of the header. 2021-06-25 14:46:06 But that pair of pointers - the code pointer and the body pointer, must stick around; that part is critical to later execution. 2021-06-25 14:46:26 In my last system I was able to completely get rid of no-longer-needed portions of headers. 2021-06-25 14:46:43 In the new system I'm working on I'll just unlink those names from the vocabulary list, but the bytes will still be there in RAM. 2021-06-25 14:46:48 I see. I like to implement IS by poking a jump at the beginning of the code — I use direct threading, so it will always fit over the call to DOCOL 2021-06-25 14:46:57 Slightly wasteful, but RAM is cheap and it was much simpler to do it that way. 2021-06-25 14:47:11 Did you do something like a compacting GC before? 2021-06-25 14:47:14 Right - that absolutely works. 2021-06-25 14:47:41 was repointing all the code to the new positions of the headers feasible? 2021-06-25 14:47:57 No, I had a simpler memory manager that used fixed size blocks (4kB) so it didn't need to garbage collect. When I de-alloctaed a page it just went onto a free list, that I always checked before advanci 2021-06-25 14:47:57 how does it work if you can have arbitrary alloted data in the dictionary space? 2021-06-25 14:48:15 Allot just makes that space after the last-compiled body. 2021-06-25 14:48:32 Variables and constants appear in that same region as well, in order of compilation. 2021-06-25 14:49:00 Here's an interest trick I could do: 2021-06-25 14:49:11 : foo ...foo-code... 2021-06-25 14:49:24 variable bar 2021-06-25 14:49:30 : bam ...bam-code... ; 2021-06-25 14:50:01 Now I could store a pointer in bar, and when I executed foo it would execute foo-code, execute using the pointer I stowed in bar, and then execute bam-code. 2021-06-25 14:50:13 So it would be a word with a vectorable item within it, accessible by name. 2021-06-25 14:50:40 Because the "body" of bar is just that cell the variable value goes in, and it gets squashed in between the bodies of foo and bam. 2021-06-25 14:50:58 Obviously I'd have to initialize bar before executing foo. :-) 2021-06-25 14:51:49 The point here of course is that there's no ; after foo-code, so execution doesn't stop - just plows right on forward into bar and bam. 2021-06-25 14:53:15 If I didn't need to execute bam directly I could make it a disposable definition; I'd just use .: just before it instead of : and then later run .wipe to unlink bam from the linked list. 2021-06-25 14:53:29 But, I could just do this: 2021-06-25 14:53:35 : foo ...foo-code... 2021-06-25 14:53:38 variable bar 2021-06-25 14:53:47 ] ...bam-code... ; 2021-06-25 14:54:00 And there would never be a bam in the dictionary. 2021-06-25 14:54:10 Oh, I'm sorry. 2021-06-25 14:54:29 I need [ after ...foo-code... to get out of compile mode before declaring the variable. 2021-06-25 14:54:42 I suppose I could make variable immediate and not have to do that. 2021-06-25 14:55:25 Anyway, there's a lot of flexibility to be had by not sticking your headers in the midst of your bodies. 2021-06-25 14:56:12 In the assembly code I used section management to implement that - I have macros that make headers, and they first switch to the header section, make the header, and then switch back to the body section 2021-06-25 14:56:22 That's in nasmforth, but I suppose you could do it in any good assembler. 2021-06-25 14:56:31 I'm sorry - in nasm. 2021-06-25 14:56:39 nasmforth was just the name of my previous forth. 2021-06-25 14:57:23 I often use [ instead of ; when a word ends with an unconditional jump. 2021-06-25 14:57:33 No point in compiling a (;) after a jump. 2021-06-25 15:16:08 okay, but > In my last system I was able to completely get rid of no-longer-needed portions of headers. < 2021-06-25 15:16:08 wouldn't that move all the other headers? 2021-06-25 15:21:37 No, .: (my temporary compiling word) checked to see if a temporary table yet existed. If it did, it extended it; otherwise it allocated it. It made a full normal header in the temporary page, but also 2021-06-25 15:21:57 Later .wipe would drop the temporary page and adjust list linkages appropriately. 2021-06-25 15:22:11 Compilation using those words made sure to use the permanent copy of the pointers. 2021-06-25 15:22:26 So the pointer pair was the only part of the header that got placed in the permanent header region. 2021-06-25 15:22:42 It was more or less perfect - after you were done you had an optimal memory layout. 2021-06-25 15:22:59 But it was a bit involved making it all work, and it relied on having a memory manager of some kind. 2021-06-25 15:23:50 I could only have one 4kB page full of temporary headers; it wasn't capable of using multiple pages. But that was plenty for my use cases. 2021-06-25 15:24:28 NUMBER was a good example - my implementation wound up being 20-25 definitions, all but one of which were temporary, which were 35-40 characters long. 2021-06-25 15:24:50 So I did a whole bunch of .: definitions, then the one : definition (NUMBER itself), followed by .wipe. 2021-06-25 15:25:35 This time I just decided I didn't want to engrain a memory manager - even a simple one - so deeply into the foundation of my system. 2021-06-25 20:12:29 maw 2021-06-25 20:15:40 maw ate stomach to maw 2021-06-25 20:16:26 and did so raw 2021-06-25 20:16:53 why? no law