code logs -> 2017 -> Sun, 04 Jun 2017< code.20170603.log - code.20170605.log >
--- 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
code logs -> 2017 -> Sun, 04 Jun 2017< code.20170603.log - code.20170605.log >

[ Latest log file ]