2023-08-18 03:42:45 Don't show this to KipIngram! https://starlabs.systems/pages/starlite?shpxid=f793d1ef-0d11-4efe-9483-44190ea9e394 2023-08-18 04:20:28 Wait... is PAD offset from HERE a little so that it enters exactly where the name in a new definition is needed? 2023-08-18 04:59:59 Oh, god. Took me a bit to figure out how tick works at all. TIB + >IN points at the space trailing tick when tick executes! 2023-08-18 05:00:08 Well, at least while you're interpreting. 2023-08-18 05:00:38 Not sure how that'd work in compiling mode... 2023-08-18 05:02:35 Interesting. SmithForth's CHAR implementation allows the trailing word to be more than a character long. Is that normal? 2023-08-18 05:03:53 So "CHAR ABC" will put 0x41 on the stack, and the input pointer sits right after ABC. 2023-08-18 05:23:02 xelxebar: gforth does the same 2023-08-18 05:23:33 That's standard behavior 2023-08-18 05:23:45 So that BL WORD or similar can be used to parse the character 2023-08-18 05:24:19 ANS 6.1.0895: "Skip leading space delimiters. Parse name delimited by a space. Put the value of its first character onto the stack." 2023-08-18 05:24:50 Ah, you're too fast! :P Beat me by 10 seconds. 2023-08-18 05:26:18 If it's a standard forth, then tick doesn't 'do' anything when it's compiled, it just gets compiled 2023-08-18 05:27:43 And then there's ['] which is immediate and will find an execution token *now* for a colon def and compile that literally into the definition 2023-08-18 05:28:25 i.e. ' DEF and : TMP ['] DEF ; TMP produce the same result 2023-08-18 05:29:04 TIB is the terminal input buffer 2023-08-18 05:29:17 and >IN is the current input offset in the buffer 2023-08-18 05:29:59 Sure, but then "' BLAH" doesn't give you the execution token of BLAH at runtime. If you wanted that at compile time, I guess you'd want to do [ ' BLAH , ] ?? 2023-08-18 05:30:16 Oh, ['] I see. 2023-08-18 05:30:22 Yup 2023-08-18 05:32:23 Are tick and comma characters that get used in other words, too, with some convention on meaning? 2023-08-18 05:32:49 Comma means "put it in the dictionary" 2023-08-18 05:32:58 Tick means "get me the address of this thing" 2023-08-18 05:33:09 Tick is sort of like prefix & in C 2023-08-18 05:33:38 Tick at the front of the word means "get me the address", at the end of a word it just means "alternative version" 2023-08-18 05:34:09 Like T and T' are T and the alternative T. This is a very mathsy thing, you see it in Haskell but I believe I'm not the only person doing this with Forth defs 2023-08-18 05:34:26 But 'T would usually mean "address of T" somehow 2023-08-18 05:35:52 Ah, so trailing tick is just "prime" like you see on variables all the time. 2023-08-18 05:36:39 Okay, so the characters themselves are not really visually punning on anything? I'm just curious why ' and , instead of other names? 2023-08-18 05:37:20 One character non-letter names are really limited, so I'd expect them to be used for really frequent actions. 2023-08-18 05:37:44 Does that mean that getting addresses and shoving bytes in the dictionary are bread and butter Forth? 2023-08-18 05:37:45 , because an array looks like this: CREATE MY-ARRAY 0 , 1 , 2 , 3 , 2023-08-18 05:37:58 Oh... Lol. That's nice. 2023-08-18 05:38:33 The tick is probably from some old language? Or arbitrary symbol for something important? 2023-08-18 05:38:49 I would wonder what ALGOL/COBOL/Fortran do 2023-08-18 05:39:02 There's a few names from those languages in Forth 2023-08-18 05:40:43 Nobody minds answering these questions, but I recommend reading something like Starting Forth to learn Forth 2023-08-18 05:41:33 Will give you a bit more appreciation for what it all "means" beyond what the words literally do 2023-08-18 05:42:30 Yeah, you're probably right. When I first tried, though, it's verbosity completely killed my motivation. Not sure why, though. 2023-08-18 05:43:21 Maybe after decyphering everything in SmithForth, I'll give it another try. 2023-08-18 05:43:26 It's not your fault, lots of people are put off by the style 2023-08-18 05:43:40 There are other Forth tutorials but I don't know a good alternative, Starting Forth worked for me 2023-08-18 05:44:31 Yeah, probably worth getting over any stylistic qualms, considering how much the book is lauded. 2023-08-18 05:46:19 Well maybe just skim the initial chapter or something 2023-08-18 05:46:50 It gets technical quite quickly, but there's stuff in there like "this is what a number looks like to a computer!!!" for non-programmers that you'll need to skip 2023-08-18 05:46:57 It's aimed at brand new programmers 2023-08-18 07:02:26 Cute. : D= ROT = -ROT = AND ; 2023-08-18 07:20:21 Oof. This one confused me a bit : D< ROT >R >R < 2R@ = AND 2R> < OR ; 2023-08-18 07:22:05 Didn't immediately notice that >R >R ... 2R> reverses the bytes, so thought it was a bug. 2023-08-18 07:22:43 xelxebar: Well, the "primary" word is the one the user actually *uses* - the longer named word is generally "under the hood" out of sight. 2023-08-18 07:23:05 I do think the primary usage is in the definition process. 2023-08-18 07:23:48 BTW, that's why I added that "needs an offset" bit to my headers. I made my compiler smart enough to handle those words so that I wouldn't HAVE TO do that immediate/non-immediate pair dance for every single one of those conditional looping words. 2023-08-18 07:24:34 veltas: I think PAD is usually higher up, but yes, it is common for WORD to put its result right where the new name will need to go if it turns out you're compiling. 2023-08-18 07:26:13 xelxebar: When you are compiling and use ' (if it's smart enough to be compileable), then when it executes in that definition, the address on the return stack is pointing to the word that came right after '. You use that to scoop the value up and put it on the data stack, and you bump the return stack value over it so that execution continues from the cell after. 2023-08-18 07:27:00 It WILL be the XT of BLAH that's pointed to by the return stack value at runtime. That's how you get at it. 2023-08-18 07:30:27 Anyway, when you interpret ' it has to use WORD to get the next word from the input stream. When you compile it, then it runs at RUN TIME and does the same thing, getting the next word from the input stream. I think. And then as noted above ['] just compiles at compile time, and at run time will use the return stack to get the XT from the following cell. 2023-08-18 07:30:59 In Forth [ switches you from compiling to interpreting, and ] switches you back. So, ['] is kkind of a shortcut meant to represent [ ' ] 2023-08-18 07:32:21 I'm sorry - the first part of all that was confusing. I tend to lose track of some of these vs. [] functionalities. 2023-08-18 07:32:32 Ah, right. It's mainly mnemonic, because [ ' ] would just grab the xt of ] . 2023-08-18 07:32:41 Right. 2023-08-18 07:34:58 I think something like this is close: 2023-08-18 07:35:03 Ooh. Nifty. Just grokked what you were meaning by the return stack business with tick. That's interesting. 2023-08-18 07:35:28 : ['] r@ @ r> cell + >r ; 2023-08-18 07:36:10 The r> cell + >r advances the return stack item forward, skipping that next cell in the definition. 2023-08-18 07:36:46 This is the kind of thing I was getting at yesterday when I waxed on Forth's access to the return stack offering a lot of opportunities. 2023-08-18 07:37:22 I mentioned COMPILE, but it all applies to ' as well. 2023-08-18 07:37:31 You have COMPILE and you have [COMPILE]. 2023-08-18 07:38:04 Instead of leaving the XT on the stack, though, those add it to the dictionary. 2023-08-18 07:39:08 : [COMPILE] r@ @ , r> cell + >r ; 2023-08-18 07:39:45 Sometimes I have the feeling that r> cell + >r warrants a primitive. 2023-08-18 07:40:03 Notice that this would NOT work: 2023-08-18 07:40:14 : r>cell+>r r> cell + >r ; 2023-08-18 07:40:28 Because at the time it executed there'd be an unintended item on the return stack. 2023-08-18 07:42:49 xelxebar: : T [ ' NAME ] LITERAL ; can be used instead of : T ['] NAME ; 2023-08-18 07:43:38 veltas: Surely you mean [ ' NAME , ] ? 2023-08-18 07:43:39 LITERAL is immediate and compiles code to push the literal value from top of stack into the current definition 2023-08-18 07:43:47 I sometimes mention that my earliest programming experience was on an HP calculator which was stack-based. So I'm really really comfortable with the data stack. But even now I still find that I sometimes overlook these return stack opportunities - the HP calc did NOT give me return stack access, so I didn't hone those skills from the outset. 2023-08-18 07:43:49 Oh. Nevermind. 2023-08-18 07:44:55 [ ' NAME , ] on some forths will actually compile NAME to be executed normally into the current def 2023-08-18 07:45:08 On other forths it would be nonsense 2023-08-18 07:45:28 KipIngram: You just made me realize that the return stack is basically used the same as a C stack. 2023-08-18 07:45:49 Yes; it's just that C doesn't generally "let you at it" in the same way. 2023-08-18 07:46:12 But it's functionally exactly like "the stack" in most languages. 2023-08-18 07:46:16 The data stack is more like the 'registers', and return stack is more like your hardware stack 2023-08-18 07:46:18 Yeah, it's hidden behind the compiler. 2023-08-18 07:47:00 The name "return stack" just made me think we're abusing the space for xt addresses. 2023-08-18 07:47:33 It's more like C "abuses" the stack for passing parameters and results. 2023-08-18 07:47:41 It's REAL purpose is to hold return addresses. 2023-08-18 07:47:48 Forth does the same though 2023-08-18 07:48:38 veltas: Oh, okay. So comma doesn't always just blindly shove bytes into your data area. Hrm... 2023-08-18 07:48:43 And moving those parameters onto and results off of the stack - that's all under the hood code in C that contributes to call/return overhead. 2023-08-18 07:48:52 xelxebar: It does always shove bytes into your data area 2023-08-18 07:48:53 Forth cuts that out, by having you manage all that on the OTHER stack. 2023-08-18 07:49:06 xelxebar: Not all Forths use the same format for compiled words 2023-08-18 07:49:34 That's where the threading model comes in. Different threading models have entirely different "things" in definitions. 2023-08-18 07:50:03 It can be actual code, pointers to actual code, or pointers to pointers to actual code. 2023-08-18 07:51:36 Oh, right. Either way, an xt just boils down to an address that eventually gets called, right? 2023-08-18 07:51:46 Or it can be 'instructions' for a tokenised forth 2023-08-18 07:53:34 Oh, so instead of 4- or 8-byte addresses, you use smaller-sized tokens? 2023-08-18 07:53:49 Or a combo, in the tokenised zenv build it contains big endian execution tokens (at least 0x8000) or instructions (under 0x80) 2023-08-18 07:54:34 Yeah a tokenised forth tends to have a set of byte opcodes for different basic operations, and some way of compiling other words 2023-08-18 07:59:43 xelxebar: Right, an xt ultimately just specifies a word's execution action. Gives you a roadmap to it. 2023-08-18 08:00:37 For variables, constants, and so on, it routes you to both 1) code that knows how to impelement "variable" / "constant" etc. AND 2) the actual data of that particular variable or constant. 2023-08-18 08:01:00 For a definition, it routes you to 1) code that knows how to "start up" a definition and 2) the actual definition data itself. 2023-08-18 08:01:16 There are always these two facets: the "per object" stuff and the "generic object handling" stuff. 2023-08-18 08:01:40 Should have stated those in the other order in that last, to be consistent with the earlier bits. 2023-08-18 08:02:15 in my system an xt points to a pointer that points to the handling code, and immediately adjacent to that pointer is another pointer that points to the per-word data. 2023-08-18 08:02:32 So my XTs are "pointers to a pointer pair." 2023-08-18 08:02:58 Primitives are the exception - my primitive words are missing one of those pointers, since just a slug of code is all that is needed for a primitive. 2023-08-18 08:03:16 My header format makes the second pointer optional. 2023-08-18 08:03:52 xt's are usually optimised first for EXECUTE, and second for stuff like >BODY or PFA (get the data) 2023-08-18 08:03:59 In old FIG systems, the xt pointed to a code pointer, and the per-word stuff (var/const value, definition, etc.) was RIGHT THERE next to it. 2023-08-18 08:05:14 So a FIG definition is laid out ... 2023-08-18 08:05:58 I instead have a second pointer that points to my items somewhere else. 2023-08-18 08:06:10 In a completely different region of ram. 2023-08-18 08:06:55 In a FIG system, this code: 2023-08-18 08:07:02 : foo ... ; 2023-08-18 08:07:06 : bar ... ; 2023-08-18 08:07:16 Just goes into contiguous ram: 2023-08-18 08:07:32 [foo header][foo def][bar header][bar def] 2023-08-18 08:07:49 So the definition cells for adjacent words are not themselves adjacent - headers are interspersed. 2023-08-18 08:07:57 In my system I'd get 2023-08-18 08:08:05 [foo header][bar header] 2023-08-18 08:08:15 and those headers would contain pointer pairs that pointed to 2023-08-18 08:08:21 [foo def][bar def] 2023-08-18 08:08:23 somewhere else. 2023-08-18 08:08:42 So if I leave out the ; between to definitions, one can just execute right on into the next one. 2023-08-18 08:08:55 : foo ... : bar ... ; 2023-08-18 08:08:59 works just fine in my system. 2023-08-18 08:10:10 So I really just construct a big wall of code, and my headers just provide entry points into it here and there. 2023-08-18 08:10:47 Somewhere else, in a third ram region, is the machine code that knows how to treat all that as vars, consts, defs, etc. 2023-08-18 08:10:59 And the headers point into that code too. 2023-08-18 08:42:54 xelxebar: If you nose around in the Forth literature, you can find a lot of articles on "object orienteD Forth." To some extent Forth's architecture supports this cleanly, since it associates those two things with each word. 1) How to handle words of this type and 2) Data specific to this particular word. That's kind of like the "methods" and "private data" of objects in OOP. 2023-08-18 08:43:22 But OOP lets you associate as many methods with an object as you wish, whereas Forth naturally supports tying just one run-time functionality to a word. 2023-08-18 08:43:34 Object oriented Forths are attempts to break that limitation. 2023-08-18 08:44:17 The common "object types" in Forth are variables, constants, definitions, and vocabularies. But Forth's create / does> mechanism lets you add new kinds of things. 2023-08-18 08:44:48 That basically lets you specify the item 1 type functionality in my list of two things via Forth code, for a class of words. 2023-08-18 08:46:25 So in a kind of way Forth words are like objects that have only one method. 2023-08-18 08:47:11 And in some cases the idea is that the private data specifies A Forth definition and the "method" is "execute it, with the ability to return back where you came from." 2023-08-18 08:48:33 In the case of a primitive, the "private data" is the primitive's machine code, and that code promises to end with a code bit that will properly move you on to the next operation. 2023-08-18 09:07:19 Oh, dang. I stepped away for a bit and you dumped details on me! Give me a bit to catch up. 2023-08-18 09:11:36 At this point I have to assume KipIngram isn't offended if you don't read everything he writes :P 2023-08-18 09:18:43 Certainly not. :-) I apologize for firehosing now and again - I assume people will just jump over stuff they're not interested in. 2023-08-18 09:19:26 I try not to be someone who takes offense at every little thing. The world has enough of those people already. 2023-08-18 09:27:46 if i have `20 " hello!"` Forth will know that i'm pushing into the stack an integer and a string, but if i have `20 apples` here 'apples' is a word, so, if it doesn't exist i get error. but i also saw this: `20 apples !` <- here how Forth can know that 'apples' is a string, and the real word to execute is `!` ? 2023-08-18 09:30:00 There apples is a word that puts an address on the stack 2023-08-18 09:30:07 And ! puts 20 in that address location 2023-08-18 09:33:15 veltas, wait, you mean that here apples has been already defined previously? 2023-08-18 09:33:27 In that example yes 2023-08-18 09:33:36 ok, i see 2023-08-18 09:33:54 Either that Or BASE is set to some big number and APPLES happens to be the correct address in that base :) 2023-08-18 09:34:08 :) 2023-08-18 09:34:45 so, if i'm implementing a Forth lexer, for every literal (e.g. number or strings) i put them into the stack, for every word i must check if it exists in the words hash table, and if so, execute it 2023-08-18 09:36:32 Yes, if a word's in dictionary it's executed, if not then it's interpreted as a number 2023-08-18 09:36:39 If it's not a number it will complain 2023-08-18 09:37:45 a string `Hello World!` is declared as: `" Hello World!"` ..in this case the initial `"` is a Forth word? or its more of a lexer trick? 2023-08-18 09:39:55 That's exactly it: " is the word 2023-08-18 09:40:11 And that word parses the content following the space delimiting the word and up to the next '"' character 2023-08-18 09:40:57 There isn't really a 'lexer' in forth, words are collected one at a time, and some words can parse or do arbitrary operations on the source code as they see fit 2023-08-18 09:41:24 So there's no regular expression or context free grammar, it's contextual 2023-08-18 09:45:48 i see 2023-08-18 09:45:54 in gforth " doesn't work tho :( 2023-08-18 09:51:48 S" or s" is the normal name 2023-08-18 09:52:39 i see 2023-08-18 10:01:37 36:apples . 647846308 2023-08-18 10:02:11 A lot of Forths don't offer a way to put a string onto the stack. 2023-08-18 10:02:29 You can put a string into a definition for later printing with ." - that's common. 2023-08-18 10:02:50 But you often don't find a word like " that lets you say " apple" and get a string pointer on the stack. 2023-08-18 10:03:00 The problem is that most Forths don't have any ready place to put that string. 2023-08-18 10:03:01 36: ? 2023-08-18 10:03:03 what's that? 2023-08-18 10:03:25 In my system my numeric input uses : 2023-08-18 10:03:29 It's non-standard. 2023-08-18 10:03:33 oh i see 2023-08-18 10:03:38 KipIngram, did you wrote a Forth system? 2023-08-18 10:03:52 I can also say x: for hex and b: for binary, but that's just shorthand for 16: and 2: 2023-08-18 10:04:06 I can go up to 62 (0-9, A-Z, a-z) 2023-08-18 10:04:15 Up through 36, letters are case insensitive. 2023-08-18 10:04:21 that's very interesting 2023-08-18 10:04:31 But starting at 37 you need the lower case letters to be different. 2023-08-18 10:04:34 i'm planning something similar in my Forth system 2023-08-18 10:04:50 for instance: `#u32 1122` and i have a unsigned 32bit integer 2023-08-18 10:05:11 62:apples . 33746713018 ok 2023-08-18 10:05:12 62:APPLES . 9536776540 ok 2023-08-18 10:05:37 I have variablel BASE, but it's used for numeric output only. 2023-08-18 10:06:59 I found that numeric input code to be pretty hard to get all the bugs out of. 2023-08-18 10:07:09 yeah 2023-08-18 10:07:19 And it required a fair bit of code, too. 2023-08-18 10:07:25 KipIngram, my system also supports integer literals as 0xFFFF 2023-08-18 10:07:34 Of course, I also had it able to process floating point numbers. 2023-08-18 10:07:42 can i ask you in which lang did you wrote that? 2023-08-18 10:11:48 Oh, it's written in my Forth. 2023-08-18 10:12:04 I mean, I put it in my nasm source code, but the NUMBER code was hand-compiled Forth. 2023-08-18 10:12:42 As in, when I get to the point where my system will re-compile itself, I already have the necessary source for NUMBER. 2023-08-18 10:13:04 In the nasm file I put the Forth in comments, and then hand-compile it below using some macros that I wrote. 2023-08-18 10:13:14 it's pretty clean - kind of like this: 2023-08-18 10:13:24 ;;; : foo bar bam ; 2023-08-18 10:13:33 def "foo", foo 2023-08-18 10:13:42 run bar, bam, dosem 2023-08-18 10:14:31 and for primitives: 2023-08-18 10:14:38 code "prim", prim 2023-08-18 10:14:43 2023-08-18 10:14:45 next 2023-08-18 10:15:43 The def and code macros handle all of the hocus pocus of constructing the dictionary properly. 2023-08-18 10:16:16 If it's a primitive that will need an offset compiled after it it 2023-08-18 10:16:28 code "prim", prim, LOOP 2023-08-18 10:16:48 I'm pretty impressed with nasm's macro facility. 2023-08-18 10:31:53 KipIngram, that's very interesting 2023-08-18 10:32:37 If I recall, my NUMBER involved like 23-24 of my 40-50 char definitions. 2023-08-18 10:32:48 All of them except one defined with that .: temporary word mechanism. 2023-08-18 10:33:23 It's basically a state machine - I drew it out as a state machine first. 2023-08-18 10:34:12 It builds a stack frame with the base initialized to 10, and the accumulator to 0, and starts accepting digits. Accumulator builds up a base 10 number. 2023-08-18 10:34:43 Then if it sees a : it puts the current accumulator into the base field and zeroes the accumulator, so goin forward from there it accepts digits in the new base. 2023-08-18 10:35:24 A good bit happens if it sees a . 2023-08-18 10:36:19 It continues to build up the number, but from there it starts coutning digits so I know how many decimal places there were. If it sees an e, it makes a new frame to convert a base 10 exponent into. And then at the end if it's a float it goes through a rigamarole with the FPU to get it into IEEE format. 2023-08-18 10:36:59 One of the FPU instructions required only works for arguments between 0 and 1, and handling that was a pain. 2023-08-18 10:36:59 i see 2023-08-18 10:38:21 One issue it doesn't handle is "too many floating point digits." You could type as many as you want after the decimal point, but if it's too many then the whole conversion winds up giving the wrong answer. 2023-08-18 10:38:27 And it doesn't check for or detect that. 2023-08-18 10:39:42 But... it takes a LOT of digits to triger that. 2023-08-18 10:47:15 I think it would even do something sane if I put base specifiers in a floating point number, but no one ever does that, so... 2023-08-18 10:47:59 You do run into a problem with using e or E as a digit in such a case - its going to see that and try to process an exponent. 2023-08-18 10:49:01 yeah i think so 2023-08-18 10:49:48 KipIngram, what about the philosophy of clearing the stack if a word is not found? does your system clear the stack? 2023-08-18 10:52:57 I don't agree with that at all. 2023-08-18 10:53:17 My system restores the stack to the state it had before anything on the error-containing line executed. 2023-08-18 10:53:29 The idea is to be able to up-cursor back to the line, fix the typo, and hit Enter. 2023-08-18 10:53:36 So I need things to be in the right state for that. 2023-08-18 10:53:39 so, 2023-08-18 10:53:41 1 2 3 2023-08-18 10:53:49 4 5 6 baggle + . 2023-08-18 10:53:53 baggle isn't found. 2023-08-18 10:54:05 Stack will have 1 2 3 on it, even though the 4 5 6 processed successfully. 2023-08-18 10:54:34 Because when I repeat that whole line after fixin it, 4 5 6 will get re-issued. 2023-08-18 10:55:00 My g key seems uncooperative this morning. 2023-08-18 10:55:07 I'm not really trying to sound Southern. 2023-08-18 10:56:05 I think error recovery should clear the RETURN stack. 2023-08-18 10:56:25 Because you're going back to the infinite loop of the interpreter - there's nothing to do with anything on the return stack at that point anyway. 2023-08-18 10:56:41 I have a structure like this: 2023-08-18 10:56:48 : warm sp0 @ sp! 2023-08-18 10:57:01 : quit rp0 @ rp! 2023-08-18 10:57:26 Error recovery recovers my stack snapshot and goes to quit 2023-08-18 10:57:54 Actually the rp0 @ rp! is inside the loop. 2023-08-18 10:58:37 I'd rather have the system do nothing to the data stack on error than clear it. 2023-08-18 10:58:47 Then at least you could inspect it. 2023-08-18 10:59:08 I give up that ability too, but at least I think I'm doing something "sane." 2023-08-18 10:59:37 What if you've spent several minutes running lines of input that have your stack just so. 2023-08-18 10:59:46 and it just tosses all that because of a typo??? 2023-08-18 10:59:56 That's nuts - I disapprove very strongly. 2023-08-18 11:00:56 This approach I take uses a lot of RAM. I don't just snapshot the stack - I snapshot my whole system. Stack, dictionary, all my variables, etc. - it all gets restored to the pre-line state on error. 2023-08-18 11:01:04 And that takes RAM, and is slow. 2023-08-18 11:01:12 But not so slow as to be noticeable. 2023-08-18 11:01:28 So it's really an approach that's only suitable on a destop - in a limited RAM micro I couldn't do it. 2023-08-18 11:01:57 But even on a micro I will probably snapshot the stack. 2023-08-18 11:12:21 My error recovery handles some things for me I'd have to handle explicitly otherwise. Consider, for example, that you start typing a : definition and you make an error in it. 2023-08-18 11:12:52 Well, the system sees the : and it creates the new dictionary entry. But when you get an error you need to unwind that, or else every aborted definition attempt you make will eat up your dictionary space. 2023-08-18 11:13:08 My full system restore just fixes that, a long with a whole pile of other things. 2023-08-18 11:13:34 Even if I'm loading a block - same deal. The snapshot is made out at the interpreter, before I ever see LOAD. 2023-08-18 11:13:52 So even if I've compiled a whole big long block, if I've got an error on the last line it all gets undone. 2023-08-18 11:14:18 Because what I'll want to do is fix the error and then LOAD the whole block again, and I don't want two copies of all the stuff that worked. 2023-08-18 11:14:41 So, any Forth system has to be able to revert all the changes that have occurred compiling a block if the block winds up containing an error. 2023-08-18 11:38:21 KipIngram, let me read and analyze 2023-08-18 11:39:55 hmm i see.. 2023-08-18 11:41:00 KipIngram, so, if i got it right, `1 2 3\n4 5 6 bangle` <- after this only 1 2 3 will be into the stack, but `1 2 3 4 5 6 bangle` <- the stack will be empty, `1 2 3 4 5 6\nbangle` <- the stack will contain 1 2 3 4 5 6 ? did i get this right? 2023-08-18 11:58:24 Yes - precisely right. Once a line is finished successfully, a new snapshot is taken in preparation for the next line, so that prior snapshot is gone. 2023-08-18 11:59:09 In a sense this is like journaling. 2023-08-18 12:00:09 In our SSD product at work, there is a table that tells us where we've put each logical pae written in physical flash. The "LPT" (logical page table). When we re-write a page, we put the new data somewhere new and update the LPT. But we also make a journal entry documenting that change to the LPT. 2023-08-18 12:00:39 That journal is written to flash. Periodically, when we run out of room to journal, we snapshot the entire LPT to flash and empty the journal. 2023-08-18 12:01:14 The idea is that if we have a power failure, we don't have time to save the LPT before power drops. Later, we can read in the last snapshot of the LPT, and then apply any existing journal entries to it to recover the desired LPT. 2023-08-18 12:01:30 once we do a fresh save of the whole LPT, we don't need the journal entries anymore. 2023-08-18 12:01:49 Similarly, once I reach the end of a line without error, I don't need the pre-line snapshot anymore. 2023-08-18 12:03:05 If any and all changes to the system in Forth could be 'undone,' then a journal approach would work. On error I could just undo using the journal entries. 2023-08-18 12:03:07 KipIngram, wait, SSD product? what is an SSD ? 2023-08-18 12:03:13 But some changes can't be reverted. 2023-08-18 12:03:32 you mean SSD hard drives? 2023-08-18 12:03:36 Solid State Drive. That's what my group at IBM does - we design an SSD product. 2023-08-18 12:03:39 ok ok, i see 2023-08-18 12:04:02 You can't go out and buy one - they're used only in large rack mount storae systems that we sell. 2023-08-18 12:04:30 oh, they are sold only to big businesses then 2023-08-18 12:04:58 The final system level product, yes. 2023-08-18 12:05:09 We don't sell the bare drives. 2023-08-18 12:05:21 oh, i see, pretty interesting 2023-08-18 12:05:47 They're VERY interesting - the stuff that goes on inside one of those is a lot more fascinating than I'd have ever thought before starting to work with them. 2023-08-18 12:05:55 a little off topic question: since you work i such an interesting field, do you have a your personal opinion on what SSD are best at consumer level? e.g. the ones we buy on Amazon 2023-08-18 12:06:18 Ultimately, the NAND flash chips we use are pretty crap. Significant bit error rate, all kinds of data retention issues, etc. 2023-08-18 12:06:29 yeah 2023-08-18 12:06:29 We have to design around all of that to get a high reliability result. 2023-08-18 12:06:49 I tell people that we make armor out of tissue paper. 2023-08-18 12:07:03 it works with glue 2023-08-18 12:07:30 :-) 2023-08-18 12:08:10 I don't actually do any of the development myself, but I do have a very good front row seat - I get to hear about and work closely with a lot of the things they do. 2023-08-18 12:08:31 :) 2023-08-18 12:08:49 https://mythbusters.fandom.com/wiki/Paper_Armor_Myth 2023-08-18 12:09:07 And I'm able to grok most of their methods, given my prior experience with other kinds of electronics. 2023-08-18 12:09:16 returning back to the Forth discussion, gforth doesn't follow that line \n-reset, it just rests the full stack on error, why? 2023-08-18 12:10:26 I have no idea - I didn't realize that and as I noted I disapprove highly. 2023-08-18 12:10:37 I think it's a HORRIBLE approach. 2023-08-18 12:11:06 Almost angering, if I angered easily. 2023-08-18 12:11:20 If I had to use GForth regularly, that would make me nuts. 2023-08-18 12:14:57 In fact, if you'd asked me about it earlier, before I found out, I'd have bet money that it didn't do that, just because it seems ridiculous to me. 2023-08-18 12:15:11 Does the standard say anything about this? 2023-08-18 12:16:15 I guess I feel like it's ok if the "operational mode" that's envisioned is loading blocks as the "standard work." 2023-08-18 12:16:39 But it's downright offensive if what's on your mind is a highly interactive workflow. 2023-08-18 12:17:46 It's as though they're taking the attitude that the stack is nothing more than a very short-term scratchpad. 2023-08-18 12:17:54 What if I want to keep something on it for a while? 2023-08-18 12:18:27 Something that it took a couple dozen lines of interaction to prepare? 2023-08-18 12:25:51 yes i agree 2023-08-18 12:34:54 I'm sad to say that learning this has lowered my opinion of GForth. I've always perceived it as an implementation that's very "feature rich," but this is just a real oversight if you ask me. 2023-08-18 12:35:31 And it is a DESKTOP Forth, where the user can be expected to have lots and lots of resources. Plenty of opportunity for them to do better. 2023-08-18 12:37:24 Oh, one thing my error recovery does not do is try to unwind changes to disk blocks. In order to even be able to do that in theory you'd need a revertible storage system. My disk buffers live in a separate area of RAM, outside of the snapshot region. 2023-08-18 13:05:58 KipIngram, yes i agree with your point 2023-08-18 13:06:46 well, is Forth used for its simplicity on very low powered hardware still today? for instance where? 2023-08-18 13:08:30 In a desktop system with a journaling file system I could see extending this so it unwound disk operations too. Basically, only error free lines / blocks would leave permanent changes in your system. For that matter, if you wanted to, with desktop resources at hand, you could save a history of snapshots and offer a full "undo" facility. 2023-08-18 13:08:56 Of course, on a micro you don't have resources for that and you're also probably poking at hardware, and those actions aren't necessarily undoable. 2023-08-18 13:09:38 Really snapshots are the only way to do it, because you can't necessarily tell by looking at a line of Forth what it's going to do. 2023-08-18 13:09:43 It might change anything. 2023-08-18 13:18:12 render: I don't really know how widely Forth is used. I definitely intend to use it for any hardware tinkering I do in the future. 2023-08-18 13:18:38 My goal here is to put this system together for the MAX32655THR board, and just plunk one of those onto the larger circuitboard for anything I do. 2023-08-18 13:19:00 Just drop it on, and I'll have my "environment," complete with support for all the peripheral features it offers. 2023-08-18 13:19:25 It's got Bluetooth onboard, and I want to be able to make a console connection to it via Bluetooth. 2023-08-18 13:19:35 I'll start out with a serial connection, though. 2023-08-18 13:20:19 But it's got digital I/O pins, analog to digital conversion, uSD slot, serial ports, Bluetooth, several different serial protocols, digital audio, a microphone input, etc. 2023-08-18 13:20:22 It's "loaded." 2023-08-18 13:20:27 Costs about $30. 2023-08-18 13:20:50 Once I confirmed I was going to be able to make this work, I went and bought a few of them, just to have on hand. 2023-08-18 13:21:16 Oh, it's got a fair amount of power management flexibility, and handles battery charging too. 2023-08-18 13:21:24 That's a lot to get onto a project with one shot. 2023-08-18 13:21:41 Means when I do a project I'll be able to focus on the project specific aspects. 2023-08-18 14:45:20 Oh, that little board also has a suite of counters/timer gadgets, pwm generator, and some thins like that. 2023-08-18 19:42:14 KipIngram: Interesting comment about the dictionary oragization. SmithForth's layout is contiguous | header | def | heaer | def | ... | like what you say about FIG. 2023-08-18 19:42:57 Though, since the header contains a Code pointer to the def, in principle, they could be different memory locations. 2023-08-18 19:44:10 You make me realize that such a change would simply need some small revisions to : and ; 2023-08-18 19:48:29 Huh : WITHIN OVER - >R - R> U< ; 2023-08-18 19:49:33 So if ( x y z -- flags ) is the stack effect, then flags holds y≤x Pretty nice how U< just works. 2023-08-18 20:05:06 next4th: Another useful thing to memorize: o c z cz s p os osz. That the order of flags checked for the groups of conditional instructions: CMOVcc (0F 4x), Jcc (7x, 0F 8x), and SETcc (0F 9x) 2023-08-18 20:05:57 Well, that's for the even-number ones, odd numbered ones are just inverted checks of the evens. 2023-08-18 20:07:25 Have to think about what checking OF, CF, ZF, etc. means, but the combo flags become obvious once you get used to it. 2023-08-18 20:40:25 xelxebar: here is a riddle for ya: how do you implement < on an architecture that does not have a status register with flags? 2023-08-18 20:42:22 xelxebar: That FIG/SmithForth contiguous layout is the most compact and a hair better performance, because it doesn't have to follow another pointer to get to the data / definition / etc. And it was "the original" way of doing it, so it kind of has tradition behind it. 2023-08-18 20:43:49 The pointer is to the common/shared bit of code that handles all definitions, or all variables, etc. - a different bit of code for each kind of word. The contiguous part is the word-specific stuff, the def or the variable storage location or the constant value. 2023-08-18 20:44:44 Usually the definition cells immediately follow the pointer to the "handling code." For definitions, that handling code saves IP to the return stack and aims IP at the definition. 2023-08-18 20:45:01 And then runs the same little bit of NEXT code that all primitives finish with. 2023-08-18 20:52:26 Zarutian_iPad: Subtract and bit shift? Depends exactly what you want the result of < to be though. 2023-08-18 20:54:16 KipIngram: Aren't the number of indirections the same? It's just a matter of where the Code pointer goes, right? 2023-08-18 20:55:22 I'm 100% beholden to SmithForth at the moment, so my mental model of the header is | Code pointer | Link pointer | Length/flags | Name | 2023-08-18 20:55:54 Wher it just happens that | Code pointer | has the address right after | Name |. 2023-08-18 20:56:12 But it could point anywhere, of course. 2023-08-18 20:56:35 Either way, the number of dereferences is the same. 2023-08-18 20:56:40 Are you thinking something different? 2023-08-18 21:24:48 Zarutian_iPad: like mips or risc-v? 2023-08-18 21:36:15 or excamera J1 2023-08-18 22:23:05 xelxebar: No, the FIG model saves an indirection. What you pick up from the definition is an XT. It points to a cell that has a pointer to the generic word class code. In the FIG model, the definition begins RIGHT AFTER THAT, so no further indirection is required to reach the defiinition - you just increment the XT value you got from the calling def, and you're now pointing to the called def. 2023-08-18 22:23:36 In my model, when I do that increment (except it's a decrement for me), that gets me to a POINTER to the def - that's the extra level of indirection I refer to. 2023-08-18 22:24:37 So, using C style references, in FIG (*xt)++ points to the called definition; in mine *((*xt)--) points to the called definition. 2023-08-18 22:25:23 Having *xt point to a pointer - that's indirect threading. 2023-08-18 22:25:44 In direct threading *xt IS code. 2023-08-18 22:26:52 So we're talking about two different things here a little. direct vs. indirect threading relates to how you reach the generic word class code. Then there's the ++ or -- that gets you to either the word-specific definition or a pointer to the word specific definition. There's no standard terminology for discussing that. 2023-08-18 22:27:02 Ah, so FIG just has the code entry point sitting at xt+4 (or +2 or whatever) 2023-08-18 22:27:13 I'm s orry - I feel like I'm doing a terrible job explaining it. :-( 2023-08-18 22:27:18 Yes, correct. 2023-08-18 22:27:25 If it's a primitive, that's machine code there. 2023-08-18 22:27:34 If it's a definition, it's a list of xt's. 2023-08-18 22:27:37 That's kind of nice. 2023-08-18 22:27:46 It's very slick how it all works out. 2023-08-18 22:27:53 Very "clean." 2023-08-18 22:28:10 And in a CODE threaded system, the definition IS machine code. 2023-08-18 22:28:13 No list of xt's. 2023-08-18 22:28:50 And that gives you the opportunity to either call a component word's code or, if it's short like say 1+ or @, just "inline" it. 2023-08-18 22:29:09 Yeah, SmithForth is code threaded, so non-prims are just a bunch of call instructions 2023-08-18 22:29:30 Right. Code threading is pretty popular because it's regarded as faster. 2023-08-18 22:29:40 I think it probably is faster, but maybe not as much so as people think. 2023-08-18 22:29:54 I don't think it's just a slam dunk, but I do think it likely wins most of the time on speed. 2023-08-18 22:30:25 Seems like a ton of indirection, though. I'd imagine that application level words end up jumping through several calls before getting down to real code. 2023-08-18 22:30:25 But I know I encountered at least one processor long ago - can't remember which one - where it wasn't; that process had rather poor performance on calls. 2023-08-18 22:30:44 jumps were a lot faster, and direct and indirect threading can do it all with jumps. 2023-08-18 22:31:49 Yes, Forth philosophy says "factor, factor, factor," so you end up with a good bit of nesting. 2023-08-18 22:32:02 But, those calls don't require preamble and postamble code like in C. 2023-08-18 22:32:09 It's JUST a call and a return. 2023-08-18 22:32:14 Good point. 2023-08-18 22:32:31 So not nearly as bad as someone well-heeled in C might think. 2023-08-18 22:33:05 Could also imagine inlining. Is that common? 2023-08-18 22:33:30 I've played around on paper with an FPGA-based hardware Forth engine; Xilinx Spartan 6. A big part of what I thought about was how to mimimize / mitigate the performance impact of threading through those nesting levels. 2023-08-18 22:33:51 Returns were free in my design - the hardware could "see them coming" and basically pre-execute them. 2023-08-18 22:34:17 And calls only took one clock cycle. 2023-08-18 22:34:58 Also, I had an opcode fifo, so I tried to load it up enough so the execute unit could be running already found opcodes while the fetch unit worked ahead through the call hierarchy. 2023-08-18 22:35:03 Wait... How? Assuming your instructions are already sitting near the execution units somewhere? 2023-08-18 22:35:18 Opcodes were packed several to a cell, so it was pretty easy to "get ahead" in that race. 2023-08-18 22:35:28 Except where conditional jumps made you dump your pipeline. 2023-08-18 22:35:50 Yes - already in the fifo between fetch and execute. 2023-08-18 22:36:02 Ah, okay, so you had an icache that was typically well-primed. 2023-08-18 22:36:03 Fetch just found opcodes, slammed them into the fifo, and kept oing. 2023-08-18 22:36:09 Right. 2023-08-18 22:36:52 Worked really well for straight nested words. The only rub was not knowing which way to pre-fetch on branches. 2023-08-18 22:37:51 I'd be prouder of it if I'd ever actually implemented it in a chip. 2023-08-18 22:38:08 But it was a paper game. I knew the Spartan 6 architecture really well, though, so I do think it was "realistic." 2023-08-18 23:06:07 xelxebar: that's helpful, thanks. actually i'm standing away from those scaring jC insts..