Making all registers caller-saved around context switches is a neat insight, it's intuitive how that could potentially lead to needing fewer instructions to execute when switching contexts.
I haven't yet digested exactly how the stacks are made to work. I think fig 8 should be obvious, but I'm getting stuck on picturing how the system guarantees that frame 1 can't grow into frame 2.
EDIT: Ah, I think I understand. It seems that they're taking advantage of a large virtual address space to give each stack loads of space, rather than them being contiguous like I assumed from fig 8.
> As modern 64-bit address-space is big enough for the allocation of many large continuous stacks [...]
> `foo :: Semigroup a, Traversable t => t a -> a` I already know that whatever is passed to this function can be traversed and have it's sum computed. It's impossible to pass something which doesn't satisfy both of those constraints as this is a specification given at the type level which is checked at compile-time.
To add to your point, I don't think foo can even be implemented (more accurately: is not total) because neither `Semigroup a` or `Traversable t` guarantee a way to get an `a`.
I think you'd need either `Monoid a` which has `mempty`, or `(Foldable1 t, Traversable t)` which guarantees that there's at least one `a` available.
Yep, I missed it as I don't often work in haskell anymore but with the correction the rest of the above still stands (haskell syntax is still the most efficient I'm aware of for talking about this). Also, it being unimplementable is also a nice property of having such a type system as you can prove that your specification is impossible to implement (more applicable in Lean, ATS2, Idris, Agda) or make invalid states impossible to even write (consider state transition rules at the type level).
Uh, you are right. C is the right name. It throws.
I mixed it up with a similar compile-time constness check in some of my libraries, where I decided if const of not. gcc throws, only clang could give me a proper answer.
My main source was reading other source and sometimes asking questions in the Pi forum. The already linked kmscube shows how some of mentioned techniques work. It was then mainly following up on API calls names and parameters (DRM_MODE_ATOMIC_TEST_ONLY) to find other snippets of code that use them. Felt a bit more like code archeology :-)
> doesn't run against the grain of the entire language
Not an expert, but my gut says maybe it runs against zero values? As in, "what's the zero value for a non-nullable reference?" Maybe the answer is something like "you can only use this type for parameters", but that seems very limiting.
Half of the language is already non-nullable and is accomplished by allowing for zero values. Non pointer variables are guaranteed to be never nil.
What is missing is the ability to have pointer variables and have the compiler ensure that it will be never nil. I believe this was a design choice, not some technical limitation.
Like the sibling comment seems to be saying: a non-nil pointer would have to be set to some real (non-nil) pointer value anyway. So having a zero value does not seem to apply?
I think the person you're responding to is agreeing with you that you should optimize for languages other than English rather than for people naming a label "Bin" and then switching to the UK locale.
FWIW, that's not dependent typing, because the type doesn't depend on run-time values. A bool is either true or false, a [0...1] is either 0 or, ..., or 1.
I'd probably find the name Natural Seitan misleading (i.e. mistakenly buy it thinking it was vegan), but calling it "Animal Seitan" would be perfectly acceptable/clear to me .
Ok, but if you get "\t[space][space][space][space]", how do you know this wasn't supposed to be "\t\t"? That is, how do you know trailing spaces are for alignment and not for indentation?
A code formatter knows, so your editor and other tools can also know.
Most editors have code structure parsing of some kind built-in for tabbing already. E.g. pressing the <tab> key indents the current line to match the structure of surrounding code (or cycles between valid indents for something like Haskell or Python). So they know the difference between initial indentation (that people want to be able to configure visually) and alignment.
I haven't yet digested exactly how the stacks are made to work. I think fig 8 should be obvious, but I'm getting stuck on picturing how the system guarantees that frame 1 can't grow into frame 2.
EDIT: Ah, I think I understand. It seems that they're taking advantage of a large virtual address space to give each stack loads of space, rather than them being contiguous like I assumed from fig 8.
> As modern 64-bit address-space is big enough for the allocation of many large continuous stacks [...]