--- Log opened Sun Jun 04 00:00:34 2017 |
00:00 | | macdjord [macdjord@Nightstar-a1fj2k.mc.videotron.ca] has quit [Operation timed out] |
00:09 | | Kindamoody is now known as Kindamoody[zZz] |
00:22 | | Vornlicious [Vorn@Nightstar-8l6eja.sub-174-199-16.myvzw.com] has joined #code |
00:24 | | Vorntastic [Vorn@Nightstar-a2t6ba.ct.comcast.net] has quit [Ping timeout: 121 seconds] |
00:29 | <&ToxicFrog> | "Huh", sez I |
00:29 | <&ToxicFrog> | "None of my output functions are working" |
00:29 | <&ToxicFrog> | The problem, it turns out, is that I forgot to declare `}` immediate |
00:44 | <&McMartin> | Speaking of RPi3, got graphics acceleration working on Raspbian |
00:44 | <&McMartin> | Had to set "fake KMS" |
00:44 | <&McMartin> | I don't know what that means, but hurray for exhaustive search! |
00:50 | <&ToxicFrog> | #10031 0x00000000004014b8 in execute_word (word=<optimized out>) at stacks.c:52 |
00:50 | <&ToxicFrog> | ---Type <return> to continue, or q <return> to quit---q |
00:50 | <&ToxicFrog> | oops |
00:55 | <&ToxicFrog> | Ahahaha, I see what happened |
00:55 | <&ToxicFrog> | I wasn't ever updating word->execute at defn time |
00:55 | <&ToxicFrog> | So it was left pointing into the stack (which it probably shouldn't be ever, that's a leftover from earlier experimentation) |
00:56 | | Vornlicious [Vorn@Nightstar-8l6eja.sub-174-199-16.myvzw.com] has quit [[NS] Quit: Bye] |
00:56 | <&ToxicFrog> | Specifically, at the stack cell that held the Word* while it was being compiled |
00:56 | | Vorntastic [Vorn@Nightstar-uhn82m.ct.comcast.net] has joined #code |
00:58 | <&ToxicFrog> | Holy shit |
00:58 | <&ToxicFrog> | ] :double { 2 * } defn |
00:58 | <&ToxicFrog> | 0 |
00:58 | <&ToxicFrog> | ] 3 double . |
00:58 | <&ToxicFrog> | 6 |
01:02 | <&McMartin> | Power overwhelming |
01:07 | <&ToxicFrog> | Sadly it does not work on the AVR yet, although it does at least fail in an amusing way |
01:12 | | * McMartin swaps the Pi back over to RISC OS, copies some stuff off, confirms that so far ELF binaries only seem to work on the Pi and not in emulation. |
01:18 | <&ToxicFrog> | Now it fails in an unamusing way and I really miss gdb. |
01:32 | <&McMartin> | Aha, all right |
01:32 | | * McMartin gets SDL working on a simulated RPC610. |
01:33 | <&McMartin> | Though the graphics compromises are pretty severe. |
01:34 | <&ToxicFrog> | And it lives! |
01:34 | <&McMartin> | Also, what the fuck, RISC OS. |
01:34 | <&McMartin> | I don't blame you for not being a Unix system |
01:35 | <&McMartin> | But I feel like maybe I can blame your modern dev community for making me use some kind of mad equivalent of exe2bin.com |
01:35 | <&ToxicFrog> | That function definition above, btw, is not a lookahead parsing mode; `:double` pushes a string, `{` puts it into compile mode and allocates a partial word entry, `2 *` push opcodes onto the stack, `}` finalizes the word entry, pops the opcodes off the stack, links it into the dictionary as an anonymous word (so it can be found and freed later if it remains anonymous), and pushes a pointer to it |
01:35 | <&ToxicFrog> | And then `defn` pops the string and the Word* and associates them in the dictionary. |
01:36 | <&McMartin> | Very nice |
01:36 | <&McMartin> | And yeah. I've gotten the impression that this is a place where PS is cleaner than Forth |
01:36 | <&McMartin> | But I'm also seeing that Forth is really unduly smug about some construct I don't understand that seems to surround the parsing wackiness |
01:36 | <&McMartin> | I'm not sure what the story is there but I do want to know it. |
01:36 | <&ToxicFrog> | It also supports (although it is not well tested) nested {} blocks, which is necessary for flow control |
01:37 | <&McMartin> | Hmm |
01:37 | <&McMartin> | Full structured flow control doesn't *technically* require break/continue, but it seems like break/continue would be good things to have |
01:38 | <&ToxicFrog> | Yeah, I'm not actually sure how to implement those |
01:38 | <&ToxicFrog> | if/elseif is easy, as is while |
01:40 | <&ToxicFrog> | I mean, since `while` takes a function as one argument, `return` should be eqv to `continue`, but there's no `return`. I could implement it as a special form, though. |
01:41 | <&ToxicFrog> | (but you couldn't use it nested, so `return x if` would be valid but `{ foo return } x if` would not be) |
01:44 | <&McMartin> | ... shouldn't while take *two* functions as arguments? |
01:45 | <&ToxicFrog> | That...depends |
01:45 | <&ToxicFrog> | IIRC ps while takes a function and then just looks at the top of the stack on each iteration |
01:46 | <&ToxicFrog> | The assumption being that the loop body makes sure the top of the stack is the condition value as the last thing it does |
01:46 | <&McMartin> | Ah, I see |
01:46 | <&ToxicFrog> | Making it (body predicate -- ?) and then calling predicate each time around the loop is also a valid approach |
01:46 | <&McMartin> | I guess if you if-block out the remainder you get that. |
01:46 | <&McMartin> | Yeah |
01:47 | <&McMartin> | You hvae to do some juggling to make the predicate check be in the middle |
01:47 | <&McMartin> | Which, for all these languages, is the same as "at the beginning"~ |
01:47 | <&ToxicFrog> | The C implementation of the former is pleasingly straightforward: body = (Word*)pop(); while(pop()) call_word(body); |
01:48 | <&McMartin> | ... shouldn't that be a do-while |
01:48 | <&ToxicFrog> | Depends on whether you expect the stack to start off with something on it |
01:48 | <&ToxicFrog> | like, `true {...} while` vs `{...} do-while` |
01:49 | <&ToxicFrog> | Hmm. |
01:50 | <&ToxicFrog> | The next thing to make it *useful*, I think, is to define a shitload of constants useful for things like manipulating pins |
01:50 | <&McMartin> | I think my question here is "when should that not be 'true' |
01:50 | <&ToxicFrog> | But I'm already at 50% RAM usage once the builtin words are loaded, so I think the next *actual* step is moving all the builtin words into flash |
01:51 | <&ToxicFrog> | Well, I mean, in practice it's something like <condition expression> <function> while |
01:51 | <&ToxicFrog> | And if <condition expression> pushes false you don't execute <function> at all |
01:52 | <&ToxicFrog> | Just like in C where sometimes you want to execute the while loop zero times |
01:52 | <&McMartin> | This is sounding a whole lot like the two-argument while but you have to repeat yourself sometimes. |
01:52 | <&ToxicFrog> | the two-function version is sounding better, yes |
01:52 | <&ToxicFrog> | Especially since the body can leave whatever it wants on the stack for the predicate |
01:52 | <&ToxicFrog> | And then while and do-while have the same signature are almost the same implementation. |
01:52 | <&McMartin> | the do-while in C with "zero executions" is the one where you execute once and skip the "body" in the main part |
01:53 | <&McMartin> | Yeah |
01:53 | <&ToxicFrog> | "skip the body in the main part"? |
01:53 | <&McMartin> | So, the single-function while body where you test "in the middle"/at the beginning |
01:53 | <&McMartin> | is basically if (predicate) { body 1 } else { 0 } |
01:54 | <&McMartin> | So executing it "zero times" is executing body zero times but the whole body once, through predicate and the else clause |
01:55 | <&ToxicFrog> | I am deeply confused |
01:55 | <&ToxicFrog> | By do-while I just mean `do { ... } while (expr)` |
01:55 | <&McMartin> | OK, let's back up |
01:55 | <&McMartin> | I was suggesting that single function while be implemented as you wrote, but with do-while instead of while |
01:56 | <&McMartin> | You objected "what about the zero times case" |
01:56 | <&McMartin> | My answer is "that's covered, because the do-while's function argument looks as I quoted" |
01:56 | <&McMartin> | While in the one where where it's while, "predicate" appears *twice* |
01:56 | <&McMartin> | Once in the loop, for each check, and once again at the beginning to decide whether to run anything at all |
02:10 | <&ToxicFrog> | Ok, this is not at all what I was thinking |
02:11 | <&ToxicFrog> | Which is just that while is: body,p = pop(),pop(); while(p()) body(); |
02:11 | <&ToxicFrog> | And do-while is the same, except using do ... while |
02:13 | <&McMartin> | That sounds like the two-arg version yes |
02:14 | <&McMartin> | Everything in my previous speech was about how the one-arg version was technically adequate for both but incredibly clunky and required the person using the language to repeat themselves sometimes. |
02:14 | <&ToxicFrog> | Aah |
02:14 | <&ToxicFrog> | Ok, *now* it makes sense |
03:30 | | Jessikat` [Jessikat@Nightstar-abhvn4.dab.02.net] has joined #code |
03:31 | | Jessikat [Jessikat@Nightstar-aqb.jtr.132.82.IP] has quit [Ping timeout: 121 seconds] |
03:44 | <@himi> | TF: why are you implementing Forth again? |
03:44 | <@himi> | I can't recall what your reasoning was, aside from the inevitable "there's a CPU in front of me" |
03:53 | | celticminstrel is now known as celmin_of_nod |
04:02 | <&McMartin> | The existing Forths weren't working. |
05:47 | | Vornicus [Vorn@ServerAdministrator.Nightstar.Net] has joined #code |
05:47 | | mode/#code [+qo Vornicus Vornicus] by ChanServ |
06:12 | | Vorntastic [Vorn@Nightstar-uhn82m.ct.comcast.net] has quit [Connection closed] |
06:26 | < Jessikat`> | Someone told him to go forth and he took them literally |
06:26 | | Jessikat` is now known as Jessikat |
06:35 | | * Vornicus jessihats |
06:43 | | * Jessikat skritch |
06:54 | | Turaiel is now known as Turaiel[Offline] |
07:15 | | Alek [Alek@Nightstar-7or629.il.comcast.net] has quit [Ping timeout: 121 seconds] |
07:18 | | Alek [Alek@Nightstar-7or629.il.comcast.net] has joined #code |
07:18 | | mode/#code [+o Alek] by ChanServ |
07:37 | | * McMartin finishes fixing up an additional minor C64 project. |
08:51 | | Kindamoody[zZz] is now known as Kindamoody |
10:00 | | Jessikat` [Jessikat@Nightstar-ces9g8.dab.02.net] has joined #code |
10:03 | | Jessikat [Jessikat@Nightstar-abhvn4.dab.02.net] has quit [Ping timeout: 121 seconds] |
10:12 | | McMartin [mcmartin@Nightstar-rpcdbf.sntcca.sbcglobal.net] has quit [[NS] Quit: brb] |
10:21 | | McMartin [mcmartin@Nightstar-rpcdbf.sntcca.sbcglobal.net] has joined #code |
10:21 | | mode/#code [+ao McMartin McMartin] by ChanServ |
11:10 | | Kindamoody is now known as Kindamoody|afk |
12:36 | | Netsplit Deepthought.Nightstar.Net <-> Krikkit.Nightstar.Net quits: @PinkFreud, @ToxicFrog |
12:37 | | Netsplit over, joins: &ToxicFrog, @PinkFreud |
12:52 | <&ToxicFrog> | Hmm. |
12:52 | <&ToxicFrog> | Apparently I cannot assume that pointers into program memory are machineword-aligned. |
12:52 | <&ToxicFrog> | So much for that idea |
13:01 | <&ToxicFrog> | So, the problem here is that I want to move all builtin word definitions to flash. |
13:02 | <&ToxicFrog> | This means doing anything with them requires copying to RAM first, which in turn means I need to know whether the word I'm about to invoke or search is in flash or in RAM in the first place |
13:02 | <&ToxicFrog> | However, since the AVR is harvard architecture, they share the same address space and there is no way to tell this just from looking at the pointer |
13:03 | <&ToxicFrog> | For direct calls this isn't a problem, find_word() returns a pointer to a temporary buffer and we call via that |
13:04 | <&ToxicFrog> | But for compilation it's a major problem, because we compile a word by saving a list of Word* values that are then called |
13:05 | <&ToxicFrog> | And if the word interpreter doesn't know which memory space those point into we have a problem. |
13:05 | <&ToxicFrog> | So. |
13:06 | <&ToxicFrog> | We could use the lowermost bit as a sentinel value, but it turns out the AVR has no particular alignment restrictions, so we can't be confident things will always be at least 2-aligned. |
13:06 | <&ToxicFrog> | We could use the *uppermost* bit, but this will fail on larger atmegas that have те64K of flash. |
13:07 | <&ToxicFrog> | We could check at compile time, and store different *opcodes*. |
13:07 | <&ToxicFrog> | Hmm. |
13:07 | <&ToxicFrog> | That isn't a bad idea, actually. |
13:07 | <&ToxicFrog> | For calls into flash, rather than pushing the word address, push the *function* address. |
13:08 | <&ToxicFrog> | For calls into RAM, push WORD_CALLWORD followed by the Word* |
13:08 | <&ToxicFrog> | Stuff in flash will always be a directly callable function, because even words not implemented in C get precompiled into C for storage in flash. |
13:28 | | * ToxicFrog bangs head on desk |
13:28 | <&ToxicFrog> | next_word(w) doesn't work if w was originally in flash and was returned by find_word, because it's a pointer to the temporary buffer, not a pointer to the original array |
13:32 | <&ToxicFrog> | OTOH it looks like I can generate the correct pointers in the static initializer and it's not toooo ugly |
13:32 | <&ToxicFrog> | So maybe I can just get rid of NEXT_IN_ARRAY entirely |
13:35 | <&ToxicFrog> | Although this makes generating other wordlists on the fly a bit trickier. |
13:35 | <&ToxicFrog> | Each wordlist has to be told the name of the previous one, and the initialization code needs to be told the name of the last one |
13:36 | <&ToxicFrog> | ...idea |
13:36 | <&ToxicFrog> | In corewords.c, we do something like |
13:36 | <&ToxicFrog> | #define LAST_WORDLIST CORE_WORDS |
13:36 | <&ToxicFrog> | #include "userwords1.nf.h" |
13:36 | <&ToxicFrog> | #include "userwords2.nf.h" |
13:37 | <&ToxicFrog> | ... |
13:37 | <&ToxicFrog> | DICTIONARY = &LAST_WORDLIST[LAST_WORDLIST_SIZE-1]; |
13:37 | <&ToxicFrog> | And then each generated header starts with: |
13:38 | <&ToxicFrog> | const PROGMEM Word FOO_WORDS[] = { { (Word*)(&LAST_WORDLIST[LAST_WORDLIST_SIZE-1]), ... } ... } |
13:38 | <&ToxicFrog> | And ends with: |
13:38 | <&ToxicFrog> | #undef LAST_WORDLIST |
13:39 | <&ToxicFrog> | #undef LAST_WORDLIST_SIZE |
13:39 | <&ToxicFrog> | #define LAST_WORDLIST FOO_WORDS |
13:39 | <&ToxicFrog> | #define LAST_WORDLIST_SIZE n |
13:39 | <&ToxicFrog> | So the user doesn't need to worry about this, as long as they all get #included they'll automatically link together in whatever order they were included in. |
14:14 | <&ToxicFrog> | himi: to answer your question...I wanted a REPL on the arduino, but all the existing ones have problems |
14:14 | <&ToxicFrog> | FlashForth doesn't work out of the box and doesn't have any makefile or build instructions, YAFFI stores everything in RAM and thus leaves almost no room for the actual data |
14:45 | | * Vornicus pegs python's memory looking for a crazy counterexample. |
14:45 | <~Vornicus> | not every day you see an out of memory error |
14:51 | | celmin_of_nod is now known as celticminstrel |
16:30 | | Jessikat [Jessikat@Nightstar-jt7o7a.dab.02.net] has joined #code |
16:31 | | Jessikat` [Jessikat@Nightstar-ces9g8.dab.02.net] has quit [Ping timeout: 121 seconds] |
16:56 | | Jessikat [Jessikat@Nightstar-jt7o7a.dab.02.net] has quit [[NS] Quit: Bye] |
20:10 | | Turaiel[Offline] is now known as Turaiel |
20:43 | | * jerith glares at the slack API. |
20:43 | | * Tamber tightens it. |
20:51 | | Kindamoody|afk is now known as Kindamoody |
20:51 | <&jerith> | It's almost like this thing grew organically out of a bunch of people hacking in a dynamic language with a poor type system without much thought to proper architecture or design. |
20:54 | <&jerith> | And it has the sort of documentation that is both voluminous and lacking in useful detail. |
23:00 | | Kindamoody is now known as Kindamoody[zZz] |
23:58 | | himi [sjjf@Nightstar-v37cpe.internode.on.net] has quit [Ping timeout: 121 seconds] |
--- Log closed Mon Jun 05 00:00:36 2017 |