mrgriffin
Joined 10 years ago
Joined 10 years ago
1. Only require that the programmer prove the variable is initialized before it's read. Riffing on Bill's example:
Object *x; // Fine
if (is_foo) {
x = &foo;
} else {
x = &bar;
}
x->a // Fine, was initialized by the time it was used.
Of course this is still a trade-off, your compiler has to work harder to prove that all paths that flow to each use are definitely-initialized. When you have initialization functions you now need to have type specifiers like 'in', 'out', and 'in/out' so that 'out' can take a pointer to uninitialized data, or something like MaybeUninit. This handles this example from Bill: Foo f;
Bar b;
grab_data(&f, &b); // Fine if 'grab_data(out Foo *, out Bar *)'.
2. Something like Rust's MaybeUninit to explicitly opt-in to wanting to deal with possibly-uninitialized data. Obviously also a trade-off, especially if you want to force all the maybe uninitialized stuff to be in an 'unsafe' block.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 [...]
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.
C here is asserting that the value inside is a constant and then evaluating to that constant.
I looked at DRM/KMS briefly earlier in the year and this is what made me abandon it in the end. Can you recommend any sources of information?
The atomic API and "test only commit" both sound really useful.
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.
As for which languages allow it. I'm not sure for floats, but Pascal let you do it for ints for sure. https://wiki.freepascal.org/subrange_types
<TAB><TAB>function name(arg1, arg2,
<TAB><TAB> arg3) map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (a:as) = f a : map f as
Personally I don't see any reason to use longer names than f, a, and as because you can't add any additional information.You might say "well I don't write code like that", and I don't have any answer for you. But I find I write a fair amount of generic code.
I would guess for the use-case of "I have a C project and I want to run it in Fil-C" the ability for this to be a warning + run-time panic is very helpful for quickly getting started. Reminds me of GHC's -fdefer-type-errors.
I agree that I wouldn't want to deploy a program where those panics are reachable*, but it's still handy for local development and/or maybe the developer knows they aren't reachable.
I haven't checked, but I'd guess there's a warning and a -Werror -style flag to opt-in to having a hard error for unsafe assembly?
* Obviously a panic is better than not. But guaranteed safeness is better than either of those.