1,591 karma · joined October 12, 2016
Researcher at https://www.sift.net/
Email is concat ["me@", username, ".com"]
- Implicit casts
It has the following coercions:
+ Subtyping, which is based on lifetimes, not inheritance -- e.g. I can use a global array somewhere an array with a shorter lifetime is required
+ unique references to shared references, unique references to mut pointers, shared references to const pointers, mut pointers to const pointers
&mut ---> &
| |
v v
*mut ---> *const
+ "deref coercion" -- basically, if you have a smart pointer (e.g. a reference counting one), you can get a reference out of it+ "unsizing coercions" -- if you have some pointer type that points to e.g. an array of known size, and you want to change it to a (bounds-checked!) pointer to an array of unknown size (a slice, in Rust parlance), that coercion occurs
+ function types to function pointer types
+ the ! type to any other type -- there are no values of the ! type, so this is sound (it's the type that e.g. exit() returns)
- loop keywords -- it's just for and while, not even do-while
- switch -- It has real ML-style pattern-matching, with extra goodies for pattern-matching on arrays more easily. This doesn't have the fallthrough problems of C, and is more expressive to boot.
- enum -- Again, the real ML-style design. Typesafe, and _far_ more expressive.
- _Generic -- Another ML-family design :) This time via traits, which are similar to typeclasses in languages that have those instead. Think, "interfaces, but don't require a vtable (unless the programmer requests one)"
- typeof -- Nope, though there's (ML-family-style again!) type inference, so the cases where it'd be necessary in e.g. C macros just aren't a problem.
- No explicit number of bits -- the builtin types are u8, i32, f64, etc. -- the only ambiguously-sized integers are isize/usize, which I believe are specified to be the same size as size_t; I don't know that there's a pointer-sized integer type for platforms with larger pointers than size_t's (e.g. ARM Morello and other CHERI CPUs)
Which language(s) do you like more for writing this kind of systems program?
And then, property tests are more likely to be possible, and IMO should be preferred!
> [...]
> - Security up through TLS 1.0 (SSL 3.1).
uhhhhhhhh, isn't this removed from Firefox for having security holes fixed in later versions of the TLS spec?
I think that's basically what the LLVM SafeStack pass does -- stack variables that might be written out of bounds are moved to a separate stack so they can't smash the return address.
: parse-digit ( u -- u -1 | 0 0 )
{ DUP $30 $3a WITHIN } { $30 - TRUE }
{ DUP $41 $5b WITHIN } { $37 - TRUE }
{ DUP $61 $7b WITHIN } { $57 - TRUE }
{ ." parse-digit 1: " TODO } 3 CASE ;
: add-digit ( u u -- u flag )
." add-digit 0: " TODO
;
: parse-digits-0 ( u addr len -- u flag )
{ OVER B@ -ROT { parse-digit } 2DIP ROT
{ { SWAP base B@ * + } 2DIP 1 /STRING parse-digits-0 } WHEN
} { DROP TRUE } ?COND ;
: parse-digits ( u addr len -- u flag )
{ parse-digits-0 } { DROP FALSE } ?COND ;
: parse-prefix-if-exists ( addr len -- addr len 0|1|2 )
DUP {
OVER B@
{ DUP $2d = } { DROP 1 /STRING 1 }
{ DUP $7e = } { DROP 1 /STRING 2 }
{ DROP 0 } 2 CASE
} { 0 } COND ;
: parse-base-if-exists ( addr len -- addr len base )
DUP {
OVER B@
{ DUP $23 = } { DROP 1 /STRING #10 }
{ DUP $24 = } { DROP 1 /STRING $10 }
{ DUP $25 = } { DROP 1 /STRING %10 }
{ DUP $5e = } { DROP 1 /STRING ^10 }
{ DROP 2DUP $3a SCAN DUP } {
1 /STRING { NIP - 1- 10 BASE B! 0 -ROT parse-digits } 2KEEP
ROT { ROT } {
." parse-base-if-exists 1: " TODO
} COND
\ ." parse-base-if-exists 2: " TODO
}
{ 2DROP base B@ } 5 CASE
} { base B@ } COND ;
: with-saved-base ( x*i { x*i -- x*j } -- x*j )
base B@ SWAP DIP base B! ;
: apply-prefix ( u 0|1|2 -- n )
{ } { NEGATE } { INVERT } 3 SWITCH ;
: parse-number ( addr len -- u -1 | 0 0 )
{ parse-base-if-exists base B! parse-prefix-if-exists
{ 0 -ROT parse-digits } DIP
SWAP { apply-prefix TRUE } { DROP FALSE } COND
} with-saved-base ;
(This being an incomplete rewrite of the bootstrapped text interpreter's number parser; as I said, nowhere near ready.)Like, are you proposing that the ideal semantics for `#embed "foo"` if foo contained 0x10 0x20 0x30 0x40 to be to expand to `16, 32, 48, 64, 0`? That seems more annoying than the opposite, given that:
> That said for binary embeds you almost always need the length embedded as well, which has been the case for every tool I've used to embed files in object code. You usually get something like
TFA demonstrated it by relying on sizeof() of arrays doing the right thing:
static_assert((sizeof(sound_signature) / sizeof(*sound_signature)) >= 4,
"There should be at least 4 elements in this array.");
You'd need to change this to subtract one every time, which sounds more annoying when embedding binary resources than adding the zero to strings would be.the posix_spawn mentioned in the article is effectively the equivalent of CreateProcess