2022-05-21 10:01:40 Regarding locals, I have found there to be a small number of situations where I needed to be able to work with more quantities on the stack than the normal words give good access to. For that purpose I created a "stack frame" system that lets me access a section of the stack directly. It massively reduced my use of "stack juggling" words. That's not quite the same thing as "locals," but it's closely 2022-05-21 10:01:42 related. 2022-05-21 10:02:04 I agree with Chuck in principle, but just found now and then I couldn't make it turn out well following his precepts religiously. 2022-05-21 10:03:31 In my setup, creating a new stack frame basically just sets a register to a particular point in the stack, and I can access cells relative to that register. Means I can get at parameters passed to me easily and reliably even if I've stakced several items on top of them. 2022-05-21 10:03:43 I use { and } for this purpose. 2022-05-21 10:03:53 And those are short, quite fast primitives. 2022-05-21 10:08:20 This doesn't provide any way of "naming" those parameters in a variable way. I always use the same little set of words to access the "parameter cells." 2022-05-21 10:08:45 It wouldn't be hard for me to extend this mechanism to allow actual "local variable" cells as well. 2022-05-21 10:09:00 I'd probably need to give { a parameter telling it how many cells to allocate for that. 2022-05-21 10:09:47 It would pull the stack pointer down by that much to leave space for those. So the parameters would be "deeper than the frame pointer," and the locals would be "shallower than the frame pointer," and then the regular stack operations would come on top of all that. 2022-05-21 10:10:11 I haven't really felt like there was a need to do that, though, so right now it just gets me at a word's incoming parameters. 2022-05-21 10:12:34 If such a word needs to return a result, I just put it in the deepest parameter cell and then leave that cell on the stack when I close the frame. 2022-05-21 10:13:47 A very handy "fringe benefit" of the setup is that } uses that frame pointer register to restore the stack pointer (I can provide an offset as well), so it doesn't matter how many "junk items" are on the stack when } runs - the stack always gets put back exactly right. 2022-05-21 10:14:14 So it offers a nice "cleanup and exit" functionality as well, though that wasn't really on my mind when I wrote it. 2022-05-21 10:15:36 That does create the need for careful testing, though - I had a stack imbalance bug in my EXPECT code for a while, and didn't realize it because } cleaned it up. I still spent a few hours chasing it down a week ago or so, though, just in the name of "having things right." 2022-05-21 10:17:06 pretty sure I ended up with a word at the bottom of the file that yells if there's anything left in the stack 2022-05-21 10:18:19 Well, that's the thing - even if the stuff inside { ... } leaves junk that wasn't intended, } will clean it off. So the error isn't as visible as it would be normally. 2022-05-21 10:18:54 for that maybe canary values and blow up if seen? 2022-05-21 10:19:06 Sometimes I consciously rely on that, but in the EXPECT case it was an inadvertent imbalance, such that the stack grew deeper on every keystroke. 2022-05-21 10:19:29 But my stack is big enough it didn't trigger an overflow, and } threw it all away, so I didn't see it for a while. Had to explicitly check. 2022-05-21 10:20:05 Most Forth's do some underflow and overflow checking, but generally that's done by the interpreter loop, so you don't get those checks during execution of an involved word. 2022-05-21 10:20:35 pForth likes to exit by segfault 2022-05-21 10:20:49 And if there was already some material on the stack, then having a word "underflow" might not get caught. Usually you figure it out pretty fast though, because things just don't work the way you expect them to. 2022-05-21 10:21:33 In the case of my EXPECT bug, if I'd tinkered around in an invoccation of EXPECT long enough (just kept typing around in the string), it eventually would have overflowed. 2022-05-21 10:22:06 The data stack would have grown into the return stack, and I'd have crashed. 2022-05-21 10:22:38 But it would have taken several hundred / a couple thousand keystrokes, inside one EXPECT call. 2022-05-21 10:24:33 I need to modify my system a little, so that SP0 is modified and restored by LOAD, so that I'm more likely to catch underflow within one LOAD operation. 2022-05-21 10:25:08 probably could have a test that throws 9,999 "a" at things 2022-05-21 10:25:12 Right now I set SP0 at start up and never change it, but I want LOAD to save the current value, set a new one (so that LOAD sees an "empty stack") and then puts it back at the end of the LOAD. 2022-05-21 10:25:28 Yes, some kind of test driver is probably feasible. 2022-05-21 10:25:49 I think I also want to just check for such things whenever I use { ... } as well, though. 2022-05-21 10:25:55 Just as part of normal development. 2022-05-21 10:26:11 I don't mean check forever - just check while I'm developing. 2022-05-21 10:26:32 Just needs a little word that inspects the stack that I can run before } 2022-05-21 10:26:57 I actually wrote a little word that prints the current stack pointer up in the top right of my screen. 2022-05-21 10:27:12 Then when I put that inside the main EXPECT loop it was absolutely obvious something was wrong. 2022-05-21 10:27:35 I was able to chase it down pretty well just by moving that word around in the code. 2022-05-21 10:28:58 Anyway, vms14, I haven't felt like there's been a need for actual "local variables." What kind of task are you doing that's making you want them? 2022-05-21 10:32:15 thrig: LOAD already saves the current value of BLK, sets a new one, and restores the old one. I'm thinking about having it do the same with SP0. And it's useful sometimes to be able to modify the vocabularly search setup, and it'd be nice to be able to restore that. So there's a list of such "environment variables" that we have occasion to save, change, and restore. 2022-05-21 10:32:53 I'm thinking of gathering all this up into a "config record" and just provide tools for saving and restoring that whole thing. Seems like that would be better than "special casing" all the different save/restore situations. 2022-05-21 10:33:29 Something like cfg! / cfg@; those would maintain a "stack of config records." 2022-05-21 10:34:02 Mostly used at compile time. I was thinking of having that stack reside in a disk block. 2022-05-21 10:34:06 turtle graphics has something like that, put the turtle back to here with settings... 2022-05-21 10:34:31 Right - it's a need that just shows up from time to time. 2022-05-21 10:35:10 So, cfg!, make any changes you like, use them, then cfg@. 2022-05-21 10:36:00 Or maybe env! / env@. 2022-05-21 10:36:34 Sure, sometimes you'd be saving things you didn't need to modify, but it would probably use CMOVE so moving the extra stuff would be pretty fast.