oh, oh wow
-
we've been calling the output routines variations on "emit", which is the historical Forth style, rather than "print" which is what every mainstream language created in our body's lifetime has used
yeah we definitely don't need the names peek/poke for anything else, because those operations (arbitrary memory access) are
@and!in Evocation, and more generally most Forths call them either that or fetch/store.also in the event we ever have users, it would only be confusing to people our exact age who had those childhood experiences, and most trans people our age are dead
-
yeah we definitely don't need the names peek/poke for anything else, because those operations (arbitrary memory access) are
@and!in Evocation, and more generally most Forths call them either that or fetch/store.also in the event we ever have users, it would only be confusing to people our exact age who had those childhood experiences, and most trans people our age are dead
so we're gonna call it "peek"
(the word that reads a character and properly consumes it is "key", by the way, also following historical Forth practice)
-
so we're gonna call it "peek"
(the word that reads a character and properly consumes it is "key", by the way, also following historical Forth practice)
C avoids having a
peek()operation by instead havingungetc()but that's terrible. we've always disliked that, it exposes too much implementation detail.
-
C avoids having a
peek()operation by instead havingungetc()but that's terrible. we've always disliked that, it exposes too much implementation detail.
okay, thinking it through... moving to using
peekas part ofwordwill only affect words that read strings, which is justs"and.". they'll both need to consume that character explicitly. that seems fine to us, though it does defy conventional Forth practice. we're gonna get way more blasphemous eventually, so that's fine. -
okay, thinking it through... moving to using
peekas part ofwordwill only affect words that read strings, which is justs"and.". they'll both need to consume that character explicitly. that seems fine to us, though it does defy conventional Forth practice. we're gonna get way more blasphemous eventually, so that's fine.it was quite frustrating debugging this, btw. we kind of got nowhere with bisecting how we introduced the problem, which in hindsight makes sense because we were doing that by commenting out lines, and doing so was having effects we didn't expect
-
it was quite frustrating debugging this, btw. we kind of got nowhere with bisecting how we introduced the problem, which in hindsight makes sense because we were doing that by commenting out lines, and doing so was having effects we didn't expect
we tried dropping back to
gdbwhich is how we debugged everything until Evocation's own debugging abilities got better, but that didn't tell us anything useful. we had to fall back to modding the interpreter to print every word before executing it, which did get us on the right track. -
we tried dropping back to
gdbwhich is how we debugged everything until Evocation's own debugging abilities got better, but that didn't tell us anything useful. we had to fall back to modding the interpreter to print every word before executing it, which did get us on the right track.the hardest bugs to find are the ones that are direct consequences of intended behavior

-
the hardest bugs to find are the ones that are direct consequences of intended behavior

okay so the current hierarchy of things is that the top-level word is
quit, which loops and callsinterpret, which callsword, which callskeyin its own loop, which callsmain-input-bufferto get the metadata pointer and passes that tokey-from. -
okay so the current hierarchy of things is that the top-level word is
quit, which loops and callsinterpret, which callsword, which callskeyin its own loop, which callsmain-input-bufferto get the metadata pointer and passes that tokey-from.so we want to split the behavior of
key-fromintopeek-fromandconsume-fromand have `key-from simplified to just call thoseand then we probably, as backfill, want to also implement
peekandconsumewhich callmain-input-bufferand invoke the*-fromvariants on it. we won't use those variants inwordbut user code might want to -
so we want to split the behavior of
key-fromintopeek-fromandconsume-fromand have `key-from simplified to just call thoseand then we probably, as backfill, want to also implement
peekandconsumewhich callmain-input-bufferand invoke the*-fromvariants on it. we won't use those variants inwordbut user code might want tothe responsibilities that
keyhave now are to check what input is present; to invoke a system call to read more if needed; to put the next byte of it on the value stack as a return value; and to advance the input buffer so that the same input won't be returned next time.so the simple way to do this would be to delegate those first three things to
peekand the last one toconsume -
the responsibilities that
keyhave now are to check what input is present; to invoke a system call to read more if needed; to put the next byte of it on the value stack as a return value; and to advance the input buffer so that the same input won't be returned next time.so the simple way to do this would be to delegate those first three things to
peekand the last one toconsumehowever we're realizing that this also bears on one of the big compatibility questions we've had in mind from the start, which is how to make sure it's not too annoying to deal with situations where the temporal behavior of input matters
-
however we're realizing that this also bears on one of the big compatibility questions we've had in mind from the start, which is how to make sure it's not too annoying to deal with situations where the temporal behavior of input matters
that's been a big frustration of ours in Rust (though it's been better since the Rust library
smolcame along, it was quite frustrating with several popular async libraries prior to that point)a stream isn't just a sequence of bytes, it's a sequence of bytes that arrive at some point in time and possibly in response to things happening in the world outside of the program
-
that's been a big frustration of ours in Rust (though it's been better since the Rust library
smolcame along, it was quite frustrating with several popular async libraries prior to that point)a stream isn't just a sequence of bytes, it's a sequence of bytes that arrive at some point in time and possibly in response to things happening in the world outside of the program
sometimes you care about the difference between "the next available byte" and "the next byte available right now"
-
sometimes you care about the difference between "the next available byte" and "the next byte available right now"
and we're just trying to make sure we don't paint ourselves into a corner with how we organize this functionality
-
and we're just trying to make sure we don't paint ourselves into a corner with how we organize this functionality
we don't need to add anything to deal with temporal behavior right this moment, but we want to make sure it's clear how we would
-
we don't need to add anything to deal with temporal behavior right this moment, but we want to make sure it's clear how we would
so the thing we're calling
peek, notionally, includes the responsibility of waiting, as part of that system call(see? you thought we were being overly pedantic in listing all that, above! admit it :D)
-
so the thing we're calling
peek, notionally, includes the responsibility of waiting, as part of that system call(see? you thought we were being overly pedantic in listing all that, above! admit it :D)
we disapprove of global mutable state, so whenever we do add a non-waiting variant, it would be a separate call with a separate name, not a flag we toggle
-
we disapprove of global mutable state, so whenever we do add a non-waiting variant, it would be a separate call with a separate name, not a flag we toggle
(at the kernel level, it's an
ioctl()that you do on the file descriptor, which persistently changes its behavior, but we can still organize our tooling to hide that fact, if we want, and we do)notionally it could have the same responsibilities but in a non-waiting version
or we could break the responsibilities down into even more granular pieces. hm hmmm. these are deep questions
-
(at the kernel level, it's an
ioctl()that you do on the file descriptor, which persistently changes its behavior, but we can still organize our tooling to hide that fact, if we want, and we do)notionally it could have the same responsibilities but in a non-waiting version
or we could break the responsibilities down into even more granular pieces. hm hmmm. these are deep questions
"peek" is already a really nice word for "look to see what's there but carefully don't change anything"
it's not immediately obvious what word we would use for "be even more careful than peeking, just make it really quick"
oh - "glimpse" lol... if we want to run with the visual metaphor. maybe we do.
-
"peek" is already a really nice word for "look to see what's there but carefully don't change anything"
it's not immediately obvious what word we would use for "be even more careful than peeking, just make it really quick"
oh - "glimpse" lol... if we want to run with the visual metaphor. maybe we do.
okay. fine. we aren't deciding on "glimpse" now, we just wanted to know there's at least one reasonable way forward before we proceed with "peek". there is, so we're going to proceed. yay
