<lisbeths>
MrMobius: the problem with the krivine machine guy is he was against contatentaive programming in the first place. he seemed to believe that we only programmed concatenatively becuase that was the only way we had figured out to make it so small, and that is why he wanted to convince us to use a krivine machine. It did not occur to him that we like the advantages concatenative programming gives.
<lisbeths>
siraben: what I mean is that lambda calclulus on its own is not able to have arrays, only linked lists. so to get any kind of speed at all you would have to take a machine + an expression and compile it to something which does use arrays. And of course you'd want it to be concatneative.
<siraben>
lisbeths: right, but I think being concatenative is a notational choice, consider (S (K S) K) for instance, compiled it would look something like PUSH S; PUSH K; PUSH S; APP; APP; PUSH K; APP when compiled
<siraben>
If you take functional + pointfree style all the way, heh you end up with category theory, only talks about arrows between types and composing them, rather than specific values.
<siraben>
I mix pointfree and pointwise all the time in Haskell, for instance, depending on what better conveys the meaning.
<siraben>
lisbeths: yes, λ-calculus when implemented naïve only has linked lists, so there's work on efficient representation of lexical environments as arrays and compilation techniques (lambda lifting, closure conversion, etc.) to make it more efficient on hardware.
<siraben>
s/naïve/naïvely
<siraben>
sts-q: I think web searches would be best, it depends on your background
<siraben>
Personally I'm looking for proofs of compilation correctness with respect to those machines
gravicappa has quit [Ping timeout: 246 seconds]
dave0 has joined #forth
gravicappa has joined #forth
TCZ has joined #forth
lisbeths has quit [Ping timeout: 260 seconds]
TCZ has quit [Quit: Leaving]
sts-q has quit [Ping timeout: 240 seconds]
TCZ has joined #forth
sts-q has joined #forth
f-a has joined #forth
dave0 has quit [Quit: dave's not here]
jsoft has quit [Ping timeout: 240 seconds]
TCZ has quit [Quit: Leaving]
djinni has quit [Ping timeout: 240 seconds]
djinni has joined #forth
f-a has quit [Ping timeout: 265 seconds]
f-a has joined #forth
WickedShell has joined #forth
<crest>
ware there any reasonable standards compliant forth tcp/ip stacks?
<crest>
or would it make more sense wrap something like the lwIP stack with a forth interface?
gravicappa has quit [Ping timeout: 246 seconds]
gravicappa has joined #forth
<MrMobius>
you mean wrap C code in forth?? *gasp*
TCZ has joined #forth
<sts-q>
Not necessarily C. As there are lots of small OS around nowadays, it would be fun to make a forth on top of OCaml (MirageOS), Rust (RustOS), C++ (HelenOS) or something in order to obtain a tcp/ip stack.
<sts-q>
Right?
clog has quit [Ping timeout: 240 seconds]
gravicappa has quit [Ping timeout: 260 seconds]
f-a_ has joined #forth
f-a has quit [Ping timeout: 265 seconds]
f-a_ has quit [Client Quit]
f-a has joined #forth
<FUZxxl>
I was thinking about making some sort of Forth/LISP hybrid
<FUZxxl>
the idea was to take Forth-like stack semantics, but implement them using linked lists
<FUZxxl>
this way, we can do all sorts of crazy functional things while having a language that is still very Forth like
<FUZxxl>
plus it would be garbage collected and a bit more flexible when building data structures
dave0 has joined #forth
<MrMobius>
what would the syntax look like for example?
TCZ has quit [Quit: Leaving]
<FUZxxl>
MrMobius: very similar to Forth
<FUZxxl>
I thought about using { and } to make subobjects
<FUZxxl>
a.g. you can write { 1 2 3 } to push a list containing the numbers 1, 2, and 3 on the stack
<cmtptr>
the problem i've always faced with a garbage-collected forth is that not everything is tracked on the stack
<cmtptr>
you might manipulate an object and then write it to memory
<cmtptr>
so you can't simply assume that once a thing is gone from the stack that it's no longer reachable
<FUZxxl>
true
<FUZxxl>
so basically, there are three user-visible global variables: the stack pointer, the return pointer, and the dictionary root
<FUZxxl>
everything reachable from one of these is reachable
<cmtptr>
I suppose so, yes
<FUZxxl>
doesn't that solve the problem?
<FUZxxl>
if you obtain a pointer to something, that pointer must be stored somewhere, so the pointee wouldn't get collected
<cmtptr>
so i obtain a pointer and then i write it to a variable
<cmtptr>
because the variable isn't typed, what's stored is just a raw address
<cmtptr>
when you read it later, how do you know to update the reference count or whatever it is you're using to determine lifespan
<FUZxxl>
I would use a conservative garbage collector
<FUZxxl>
i.e. it always assumes that a number could be a pointer
<FUZxxl>
alternatively, I'd use some rudimentary form of typing
<cmtptr>
i'd be interested in this if you could make it work
<FUZxxl>
we have a lisp-like structure but the right element of each tuple must be a pointer
<FUZxxl>
I thought about tagging in it if the left element is a number or a pointer
f-a has left #forth [#forth]
<cmtptr>
i'm actually considering getting into forth again after a 2-ish-year hiatus because it was getting to be an unhealthy obsession
<cmtptr>
but i've recently had a similar idea (tagging types, etc.) that i've been playing around with in my head and i think i might have to actually try it out before i can let it go
clog has joined #forth
<FUZxxl>
I also thought about a fully typed forth
<FUZxxl>
but that never went anywere; the programming style would be quite a bit different
TCZ has joined #forth
<MrMobius>
Im working on a small forth for a calculator that is garbage-collected
<MrMobius>
if you do ' to get an address it stores the pointer to the word, an offset of 0, and the sum of the pointer and offset
<MrMobius>
then if you add to the pointer it adds to the offset and recalculates the base+offset
<MrMobius>
and when you garbage collect, search for any occurence of that pointer as base and change the base then update the base+offset
<MrMobius>
but it requires a type system keep garbage collectable pointers separate from regular old hex numbers since those shouldnt be modified
<MrMobius>
and something like @ and ! work on the base+offset
<cmtptr>
MrMobius, how do you manage type metadata? are only things on the stack typed, or do things written to the dictionary also get metadata written with them? and if so, how does that not break assumptions about memory contiguousness?
<MrMobius>
metadata is easy each 8 byte stack element has a 9th bit to store type
<MrMobius>
and the thread is tokenized, so anything in a word that needs to be adjusted can be recognized by the preceding token
<MrMobius>
like if you have a token for pushing that type of pointer on the stack in a word, you know that the next 6 bytes contain the pointer data that needs to be adjusted since you know any time that token is found its followed by 6 bytes of data
<MrMobius>
*9th byte
<FUZxxl>
the cool thing about static typing
<FUZxxl>
is that you can get away with not having to add tags to the stack when running non-interactive words
<cmtptr>
so you do var x <some-word-to-produce-a-type-foo> x ! x @ (is the type preserved here?)
<MrMobius>
cmtptr, this is where it diverges from classic forth
<MrMobius>
: foo 3.5 $ABCD ' bar ;
<MrMobius>
numbers are floats, anything starting with $ is a 16 bit hex value, and the value produced by ' is the complicated type with base and offset
<MrMobius>
so in your case, var x 3.5 x ! x @
<MrMobius>
it would see that 3.5 is a float and tag that when it's put on the stack
<MrMobius>
and ! would write 9 bytes to x and @ would restore 9 bytes
<MrMobius>
where 8 bytes are float data and 1 byte is metadata
<MrMobius>
FUZxxl, ya you can lay down a different token for each type and not gave to store the type byte
<MrMobius>
and even have several tokens for the same type like if you have a 1 digit float number, only store one byte instead of 8 and have a special token that loads 1 byte and fills the next 7 bytes with zeroes
<FUZxxl>
not really what I mean
<FUZxxl>
rather, if you have static typing, the compiler can type check words as they are being compiled and then run them without attaching type information
<FUZxxl>
as all components will do the right thing
<MrMobius>
hmm, I dont see how you can do that reliably
<FUZxxl>
basically, each word has a defined stack effect
<MrMobius>
IF float_val ELSE int_val THEN @ +
<FUZxxl>
there are no words like pick with undefined stack effect
<FUZxxl>
that kind of code would be forbidden
<FUZxxl>
the compiler would reject it during type checking
<MrMobius>
right
<MrMobius>
there is a lot you need to forbid to do that type of optimization
<MrMobius>
IF 5 THEN
<FUZxxl>
or, depending on the type system, it would coerce the float value into an integer
<FUZxxl>
I though about calling this a "shape system" instead of a "type system"
<FUZxxl>
since we only really care about how the data is organised, i.e. which words are pointers to data of what shape
<FUZxxl>
it doesn't really matter what type the non-pointer words have
<MrMobius>
but then youre back to keeping the metadata to do the coercion since that IF statement could have been preceded by another IF so there could be any combination on the stack before +
<FUZxxl>
nope
<FUZxxl>
the coercion doesn't generate any code, it just means that int and float are effectively the same type
<MrMobius>
so then would you have separate words like d+ and f+ or just one +?
<cmtptr>
MrMobius> and ! would write 9 bytes to x and @ would restore 9 bytes
<FUZxxl>
yes, you would have separate words
<FUZxxl>
I mean really, it depends on how exactly you'd do it
<cmtptr>
where i struggle with this is that if i'm trying to write a binary structure to the dictionary, then you've interleved type data in there and screwed up my data structure
<cmtptr>
my thought was that it should be that x (the variable) is what's typed, so anything retrieved through x or some offset from x inherits that type. that would be analogous to how c works
<MrMobius>
cmtptr, actually I take back what I said. I have a different word called STO like this that writes 9 bytes: var x 3.5 x STO
<MrMobius>
and ! just writes a 16 bit value
<cmtptr>
ah, okay
<FUZxxl>
does that O stand for octo (for very large values of 8)?
<cmtptr>
so you solved it with just explicitely different words - some for writing/reading raw memory, and others for working with tagged objects
<MrMobius>
you can also check that x is actually a variable as well so you dont store the value in a word accidentally
<MrMobius>
cmtptr, right
Zarutian_HTC has joined #forth
<MrMobius>
so the hope is you can stick to a known set of words for calculator stuff and never crash the calculator which is much more castrophic than crashing a PC forth program
<MrMobius>
and you still have ! and @ to use at your own risk
<MrMobius>
octo? nah just short for STOre
<MrMobius>
following historical calculator usage :P
<cmtptr>
presumably the inverse is called LOD?
<MrMobius>
you could use RCL for recall
<cmtptr>
ah
<MrMobius>
or let STO work like ' and have the name of the variable just return its value
<MrMobius>
like 5 STO foo
<MrMobius>
then foo just returns 5
<cmtptr>
yeah that makes sense
Zarutian_HTC has quit [Remote host closed the connection]