00:00:00 --- log: started forth/21.05.07 00:06:26 --- join: gravicappa joined #forth 01:51:43 --- quit: gravicappa (Ping timeout: 260 seconds) 02:04:40 Anyone else see the B tutorial on hacker news? https://web.archive.org/web/20060225195733/http://cm.bell-labs.com/cm/cs/who/dmr/btut.html 02:05:36 I think it's quite elegant in a way, learned a lot reading it 02:05:59 (For those that don't know B is the language that C is based on) 02:41:40 I'm starting to think word addressing is better than byte addressing 02:48:08 --- quit: rpcope (Ping timeout: 252 seconds) 02:49:35 --- join: rpcope joined #forth 03:09:18 Manual for B on PDP-11 actually describes how B was a "reverse polish threaded code interpreter" http://www.bell-labs.com/usr/dmr/www/kbman.html 03:10:01 So the output of B on a PDP-11 is pretty close to a Forth program 04:23:20 remexre: pausing the Forth formalization until after my real analysis and differential geometry finals, but chapters 8 and 10 of https://github.com/achlipala/frap look pretty relevant 04:23:37 so I need to give a simulation argument that two programs are equivalent iff they have the same "trace" 04:23:49 or that they pass through the same states 04:24:10 so this properly accounts for nonterminating programs, otherwise all nonterminating programs would be equivalent! 04:35:10 --- join: wineroots joined #forth 05:26:47 --- join: gravicappa joined #forth 05:58:09 i wrote a funky word 06:01:25 : myexecute ( xt --) lit [ here 0 , ] ! [ here swap ! 0 , ] ; 06:01:34 it's self modifying code ! 06:05:10 incredible 06:05:16 ' myexecute myexecute 06:06:04 ah that wouldn't work would it. it would underflow the stack 06:06:38 i thought execute had to be a primitive but then i was able to write it in forth ! 06:16:33 I think that's getting down to the details of specific implementations. My own execute is a primitive. I suppose you could slap an xt into a blank spot of a definition and run it in any Forth, most likely. 06:17:12 I would say, though, that that definition isn't really "execute." 06:17:23 It's just a word that runs a word, and you can change what that word is. 06:17:31 It functions as execute, but... 06:17:36 It's not that all by itself. 06:17:43 --- quit: Zarutian_HTC (Ping timeout: 260 seconds) 06:17:49 it wouldn't work for words that read from the execution stream 06:18:08 i would guess execute does? 06:18:16 Also, consider the null word. 06:18:37 If execute is a primitive, and if execute is called from the top level of the interpret loop, then this works for null: 06:18:48 : "" >r drop ; 06:19:00 But if your execute is itself a definition, that won't work. 06:19:11 You have to go deeper into the return stack, because execute has put something on it. 06:19:27 You'd want to NIP the return stack instead of drop it. 06:19:34 You have to leave the return from execute alone. 06:19:58 did you mean rdrop 06:20:49 Sure - if you have that it would be the same thing. 06:20:55 : rdrop >r drop ; 06:20:59 I'm sorry. 06:21:03 : rdrop r> drop ; 06:21:26 yeah i was confused about why you were pushing something to the rstack 06:21:35 Sorry. No caffeine yet. 06:22:01 The point is that the null word's implemenntation depends on how your execute works and also on the "structure" of your interpreter loop. 06:22:18 You've got an infinite loop going, popping words out of the input stream, and somehow null has to exit you from that loop. 06:22:24 By returning up out of it. 06:22:36 Of course you don't have to do it that way. 06:22:50 You could explicitly code a null check in the interpret loop - looking for null as DATA. 06:23:07 But FIG Forth did it as I descrite, where NULL is an immediate word that diddles the return stack to break the loop. 06:23:24 what is this purpose of this 06:23:37 In my system execute is a primitive, and it is on the top level of the interpret loop, so my definition is thus: 06:23:40 : "" ;; ; 06:23:43 Just a double return. 06:24:00 The purpose is to return you to another QUERY after you've exhausted all the words in an input line. 06:24:27 : QUIT QUERY INTERPRET OKAY QUIT ; 06:24:34 That's the QUIT loop. 06:24:41 Read, interpret, read interpret. 06:24:45 Then 06:25:05 : INTERPRET FIND INTERPRET ; 06:25:23 So there's another infinite loop, and null sends you from that one back to the QUIT loop. 06:25:27 So you can QUERY again. 06:26:20 wtf is query?? 06:26:39 Oh, sorry. It's a FIG word; it EXPECTS a line of input from the keyboard into the terminal input buffer. 06:26:49 It's how traditional Forth gets a line from the keyboard. 06:26:53 oh, you read a line at a time 06:26:58 Right. 06:27:13 so for each line (for each word (...)) 06:27:20 Right, exactly. 06:27:46 And if that (for each word) is just an infinite, nonterminating loop, then the only way out of it is to do a "return" to the next level up. 06:27:50 That's how mine is written. 06:27:58 cool 06:28:11 The (for each word) loop doesn't actually CHECK for end of line - end of line is actually an executable word. 06:28:57 But exactly how it works depends on these details we're discussing. 06:29:10 yeah i guess you have to have a line loop or else you'd prompt with OKAY between every word on a multi-word line from the user 06:29:22 That's right. 06:29:30 admittedly i've never written a forth repl, all of my incarnations have just read from a file 06:29:46 I have mine written so that if STATE = 0, the prompt is " ok" and if STATE = 1 (compiling) the prompt changes to " ..." 06:30:38 somebody should make a forth website called the ok corral 06:30:46 hahahahah 06:30:51 For sure. 06:31:17 --- join: Zarutian_HTC joined #forth 06:32:44 This is basically how I do most all of my looping - more often than not my loops are infinite, and I "return out of them." 06:33:03 If I want to do that return from a lower factored level, then the return has to be further. 06:33:21 So I have a whole family of conditional returns, and also a whole family of conditional double-returns, just for that purpose. 06:36:27 I try to be disciplined about it to avoid spaghetti code. If push that return down a level by factoring, I try to name the word that does it in a way that implies it's a "return word." Usually incorporate ; into its name. 06:36:55 So a one level one would look like this: 06:37:09 : foo ... 0=; ... foo ; 06:37:19 Tail optimization turns that into a loop. 06:37:30 But if I pushed the 0=; down, it might be this: 06:37:42 : foo ... ?bar; ... foo ; 06:37:50 : bar ... 0=;; ... ; 06:38:01 You see the two-level return in bar there. 06:38:12 And I fouled up the bar name in its definition - sorry. 06:38:15 Should have been 06:38:23 : ?bar; ... 0=;; ... ; 06:38:46 Anyway, I haven't taken it any deeper than that - I have no three-level return words. 06:38:58 Hasn't been required for the amount of factoring I've wanted to do. 06:43:26 Anyway, my code has definitely gotten shorter and tighter since I started using these words. 06:59:36 --- join: tech_exorcist joined #forth 07:03:03 siraben: How hard does it look like it would be to give the TI-84 Forth a right and proper interpreter loop? From what I could tell it looks like it just executes word by word. 07:06:40 So, I drafted CREATE last night, and supposedly the compie actions of the interpret loop are working. That gets me pretty close to doing : definitions. Another big missing piece is numeric output. I've been hobbling by EMITting single characters so far. 07:07:08 And then it seems like disk I/O would be in order, and at that point I think it's ready to start doing native development. 07:21:21 KipIngram: it is a proper interpreter loop 07:21:22 see the screesnhots 07:21:22 screenshots 07:21:52 Ok - I just saw some statement in there about getting ok after each executed word. 07:25:35 KipIngram: ah, that was the old behavior, and even then it was an interpreter loop 07:26:11 KipIngram: https://github.com/siraben/ti84-forth/blob/97162514f81dce267cafdbd021978efa181177d6/forth.asm#L2934 07:52:04 Anyone have any thoughts to share on handing strings? 07:52:38 I have it in mind I'll have a word, say str, that you'd use like this: 07:52:54 str 07:53:07 So, first non-blank char encountered is adopted as the delimiter. 07:53:17 COUNT can be used to pop a character from the front of a string, that is my hot tip for strings stolen from mark4 07:53:25 But any thoughts about what to do with the string? 07:53:31 Yes - I do that quite a bit. 07:53:50 Maybe I pass a buffer address. 07:54:04 Similar to EXPECT, except it will come from the input stream instead of the keyboard. 07:54:20 str 07:54:40 That seems consistent with other things. 07:54:57 Then if I felt like implementing a string stack or something, I could. But at this level the word is more generic. 07:55:22 I guess I'll go with that unless someone has something better. 07:56:56 The way I did output formatting last time was kind of c-like. That string I input with the word just discussed could contain format fields. 07:57:01 Then I could do 07:57:23 str "string with three format fields" 07:57:31 and it would output the items, formatted. 07:58:01 That worked pretty well last time, and was fun to implement. 07:58:25 I created a little "baby stack machine" and actually "interpreted" the format field chars with a little virtual machine. 07:58:49 Treated the format fields as little byte code sequences. 07:59:12 The "stack" lived in a regular stack element - each byte was an item of that stack. 07:59:25 So I could use it to parse numeric values from the format fields and so on. 08:00:50 So each % that I came to would instantiate an empty stack for the following chars to work on; eventually the last char of the format field commanded the output itself, using the parameters that had accumulated on the format stack. 08:01:31 The format field could specify the base to use for rendering the value. 08:01:57 As well as the usual width controlling stuff. 08:05:33 I guess I asked the question because I was contemplating a string stack, but I think I'll postpone that decision until later. Just specifying a buffer the same way EXPECT does seems like the right way to go for now. 08:08:44 Actually another option is just to say WORD - that would use pre-existing code to capture the string, and it would put it in the same place words usually go, just beyond the end of the dictionary. Then I could use it there or move it, as I saw fit. 08:09:43 My WORD takes a delimiter byte as a parameter. 08:10:08 I could modify it to take a buffer address as well, if I wanted to. 08:10:41 Nice thing about putting there in unallocated space is I don't have to worry about the length. Tons of unused RAM there. 08:11:20 I definitely want to use WORD. No point in duplicating that work. 08:20:14 --- quit: Zarutian_HTC (Ping timeout: 240 seconds) 08:24:37 i did not invent count being used to fetch each byte of a string in sequence and purists dont like it :) 08:25:48 Oh, I didn't realize it was suggested that you invented it. That's been around a long time. 08:26:08 I actually name it .c@++ in my system, for naming consistency with other fetch words. 08:26:08 --- quit: dave0 (Ping timeout: 245 seconds) 08:26:27 The . as usual means "keep a parameter," which in this case is the address. 08:27:58 I have a family of those, .w@++ .h@++ .@++ 08:28:19 I think that alternate naming should address the concerns of purists. 08:28:34 It makes it so the word is doing exactly what the name says it is. 08:29:24 .c@++ is 1) c@ is "fetch a char," 2) . is "keep the addr," 3) ++ is "suitably increment the addr." 08:30:04 Purists don't like using COUNT for that because it's exploiting a non-required side effect of the string implementation, right? 08:30:45 But .c@++ has no such issue. 08:32:15 I also have pre-increment and pre- and post- decrement versions. 08:32:47 You start to see what I mean when I say my implementation is "primitive heavy." Lots and lots of primitives. :-) 08:57:31 --- join: andrei-n joined #forth 09:08:04 KipIngram: you can also plug in headphones/speakers in the I/O port and play sounds with my Forth 09:08:22 https://github.com/siraben/ti84-forth/blob/master/programs/music.fs 09:15:16 :-) 09:19:21 Ok, so I'm going to go with just using WORD to pull the string and place it there just after the dictionary. Then I'll process it char by char, handling format fields as I find them, and will make an output string a little FURTHER beyond the dictionary. Then do whatever I want with that. 09:19:45 The only down side I see to that is that I wouldn't be able to have multiple threads processing strings at the same time, but I'll resolve that later if it becomes an issue. 09:20:07 Then when the dust settles I'll be able to do . something like this: 09:21:03 : . str "%d " type ; 09:21:38 Or maybe some other word - I might prefer type be "dumb." 09:22:10 : . str "%d " process type ; 09:22:22 "process" subject to renaming. 09:29:28 --- quit: proteus-guy (Ping timeout: 240 seconds) 09:33:07 --- join: Zarutian_HTC joined #forth 09:42:22 --- join: proteus-guy joined #forth 09:48:52 So I think the way this will go is I'll be copying characters from the input string to the output string one at a time, looking for a format char. When I find one I'll advance the pointer forward based on the field length and then build the field up in place. The information to do that properly should be available. Then when I come to the end of the format field I'll pick up from just after that new stuff 09:48:54 and resume copying. 09:52:41 I think I will "imaginen" a transient string stack there beyond the end of the dictionary. I have a word wbuf now that returns here+2 (the +2 is where the link will go, so that's the start of the name string region). So maybe I'll think of that as wbuf[0], and wbuf[1] will be 256 bytes further along, wbuf[2] 512, etc. 09:53:01 Then I'll have a well-defined home for the output string in this string-to-string processing. 09:55:38 One "feature" of my WORD is that it always ensures there's a null byte after the word string. It's a counted string, but it also has that byte just AFTER the string data. So I can choose whether to use the count to process it, or just start at str[1] and regard it as a null-terminated string. 09:56:16 I did that just by storing each char in it using w! instead of c!, so it's not an endian portable implementation. 09:56:37 What endian is ARM? 09:58:17 on some of them you can change endianess 09:59:41 How flexible of them. :-) 09:59:54 Promoting diversity like that. ;-) 10:00:27 Anyway, I regarded that w! thing as a "trick" and made sure I commented on it in my source code. 10:02:06 The only thing I use those parsed words for so far is dictionary search, which treates them as counted. But the option of the null is there if I want it for anything. 10:34:16 --- quit: Lord_Nightmare (Quit: ZNC - http://znc.in) 10:36:12 --- join: Lord_Nightmare joined #forth 11:16:02 siraben: yeah I also paused stuff for finals, but yours sound more intense than mine lol 11:16:57 unrelatedly, someone in another channel I'm in had the idea of a concatenative shell language 11:17:24 so same use-case as (ba)sh, but w/ a stack etc 11:17:43 and instead of pipes as an operator, commands push an fd to the stack 11:18:01 and pop one from it if they have stdin 11:18:42 seemed like a neat idea, though I don't really wanna write it -- dealing with signals on unix gives me headaches... 11:31:27 --- quit: rann (Ping timeout: 250 seconds) 11:32:20 --- quit: ovf (Read error: Connection reset by peer) 11:36:35 --- join: ovf joined #forth 11:36:36 --- join: rann joined #forth 12:13:07 --- quit: andrei-n (Quit: Leaving) 12:35:18 --- quit: tech_exorcist (Ping timeout: 268 seconds) 12:42:51 --- join: tech_exorcist joined #forth 13:25:59 --- quit: gravicappa (Ping timeout: 252 seconds) 13:35:33 --- quit: cheater1 (Ping timeout: 240 seconds) 13:58:13 --- join: mark4_ joined #forth 13:58:25 --- quit: mark4 (Ping timeout: 252 seconds) 14:02:22 --- join: mark4 joined #forth 14:03:13 --- quit: mark4_ (Ping timeout: 260 seconds) 14:09:54 --- join: cheater1 joined #forth 14:30:55 --- quit: tech_exorcist (Quit: tech_exorcist) 15:08:35 --- mode: ChanServ set +v mark4 15:19:11 --- join: dave0 joined #forth 15:19:29 maw 15:40:54 --- quit: proteus-guy (Ping timeout: 240 seconds) 15:41:17 Hey dave0. 15:43:31 hi KipIngram 15:53:13 --- join: proteus-guy joined #forth 16:57:10 --- quit: Zarutian_HTC (Read error: Connection reset by peer) 16:57:17 --- join: Zarutian_HTC joined #forth 17:03:51 --- quit: dave0 (Quit: dave's not here) 17:25:03 --- quit: proteus-guy (Ping timeout: 246 seconds) 17:34:54 --- join: LispSporks joined #forth 17:37:50 --- join: proteus-guy joined #forth 17:53:14 --- quit: LispSporks (Quit: My MacBook has gone to sleep. ZZZzzz…) 17:56:06 --- join: LispSporks joined #forth 18:42:51 --- quit: LispSporks (Quit: My MacBook has gone to sleep. ZZZzzz…) 18:46:54 --- join: boru` joined #forth 18:46:57 --- quit: boru (Disconnected by services) 18:47:00 --- nick: boru` -> boru 19:23:20 --- join: dave0 joined #forth 19:24:21 maw 19:27:38 remexre: oh neat, a concatenative shell language 19:30:20 I've thought about trying to make my Forth function as a Linux shell. 19:30:52 --- quit: sts-q (Ping timeout: 265 seconds) 19:30:58 --- join: LispSporks joined #forth 19:35:33 lol I didn't expect someone to actually figure out I lacked stack underflow reporting, heh: https://github.com/siraben/ti84-forth/issues/6 19:36:04 to ensure it doesn't blow up the OS, I do save SP on entry to the REPL and restore it on exit 19:37:33 So, does this Forth actually take over the TI-84, or does it run like an app in some calculator supported way? 19:38:01 I had presumed the former, but I'm now wondering if it's the latter. 19:38:08 It runs under TI-OS, did you manage to run it? 19:38:19 No, can't until I get my new computer. 19:38:27 one sec, i can elaborate a way to run it in your browser! 19:38:28 No USB writes on this Mac. 19:38:32 (using an emulator) 19:38:56 --- join: sts-q joined #forth 19:41:58 KipIngram: I will not link the ROM here, but you can use https://www.cemetech.net/projects/jstified/ to load the OS and my program 20:28:40 --- quit: lispmacs (Remote host closed the connection) 20:46:48 --- quit: proteus-guy (Ping timeout: 240 seconds) 20:51:55 --- join: gravicappa joined #forth 20:59:50 --- join: proteus-guy joined #forth 21:10:15 --- quit: LispSporks (Quit: Textual IRC Client: www.textualapp.com) 23:59:59 --- log: ended forth/21.05.07