1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
Comparisons of different syntaxes w.r.t. usability
==================================================
Integer types
-------------
int vs. int
byte byte # common case
int8 int<-127..128>
int16 int<-32768..32768> # maybe a bit too long?
int32 int<0..9> # custom range with constant bounds
int64 int<0..len> # custom range with a (immutable) variable
wuint uint<.., .wrapping> # allows specifying an overflow mode,
# e.g.:
# .bounds_checked(the default),
# .wrapping, .saturating, invalidating
How about having both?
Regarding arithmetic with wrap-around:
# Alternative 1: (LRL style, i.e. SLULs predecessor)
# + most concise
# - might be confusing if wuint is used in a function param!
# (on the other hand, it can also make expressions very concise)
wuint x = (a + 1) shr 1
uint y = ((a + 1) as wuint) shr 1
# Alternative 1b:
int<0.. .uintmax, .wrapping> x = (a + 1) shr 1
uint y = ((a + 1) as int<0.. .uintmax, .wrapping>) shr 1
# Alternative 1c:
uint<.., .wrapping> x = (a + 1) shr 1
uint y = ((a + 1) as uint<.., .wrapping>) shr 1
# Alternative 2: "wrap" pseudo-function
# + can be extended with "saturate" etc.
uint x = wrap((a + 1) shr 1)
uint y = wrap(a + 1) shr 1
# Alternative 3:
wrapping {
uint x = (a + 1) shr 1
uint a1 = a + 1
}
uint y = a1 shr 1
# Alternative 4: special operations (what other languages seems to be using)
# * should shr and shl trap or discard bits on overflow?
uint x = (a %+ 1) %shr 1
uint y = (a %+ 1) shr 1
Regarding non-power-of-two integer bit-sizes (e.g. int24):
* Some languages like Zig have them.
* But how should it work w.r.t. alignment?
- uint16 typically has an alignment of 16 bits.
- what alignment would uint15 have?
- what alignment would uint17 have?
* I think it is better to have a dedicated bitfield type instead.
Regarding signed/unsigned types:
* Java only has signed types. But there are some problems:
- For bytes, it requires a lot of casts.
- For integers larger than 2^63 it is necessary to use BigIntegers.
* Slul's predecessor LRL had "eint" which has the common subset of
values in int and uint. I.e. the range is 0..SIGNED_INT_MAX.
- e = "either" (can be either signed or unsigned, i.e. common subset)
- Can be useful for ambiguous expressions, e.g. 127 can be an eint8.
- Could be useful for lengths (e.g. "esize" = 0..2^63).
|