diff options
author | Samuel Lidén Borell <samuel@kodafritt.se> | 2024-06-02 21:20:48 +0200 |
---|---|---|
committer | Samuel Lidén Borell <samuel@kodafritt.se> | 2024-06-02 21:20:48 +0200 |
commit | 580bf6130632f6855fddeea7b07c8401c56108f2 (patch) | |
tree | 4bd5e7cdb68408c52ad8df030f7f887c7d97def0 /notes/comparison_semantics.txt | |
parent | db73835b12f41be8766384a1cdcc34a0848354dc (diff) | |
download | slul-main.tar.gz slul-main.tar.bz2 slul-main.zip |
Diffstat (limited to 'notes/comparison_semantics.txt')
-rw-r--r-- | notes/comparison_semantics.txt | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/notes/comparison_semantics.txt b/notes/comparison_semantics.txt new file mode 100644 index 0000000..44ed548 --- /dev/null +++ b/notes/comparison_semantics.txt @@ -0,0 +1,78 @@ +Comparison semantics / typing +============================= + +In most other proglangs, the terms get assigned types, and then the outer +expressions are recursively assigned types. This means that deciding the +integer type sizes/signedness in comparison operations is trivial there. + +In SLUL, it works the other way around: First the outermost expression is +assigned a type (i.e. boolean for a comparison expression), and then the +types of the integer expressions have to be inferred somehow. + + +Options: +* Always require either that both sides to have an unambiguous type, or that + the left side has an unambiguous type and the right side is a literal. +* Use the largest type of any term, and report an error for mixed signedenss + within one side. (Literals get promoted to this type, and an error is + reported if the literal value is not in range). + - Will easilly trap with small types such as bytes. +* Use the type of all terms, i.e. require all terms to have exactly the same + type. + - Will easilly trap with small types such as bytes. +* Like either of the above, but never use types smaller than int/uint. + + +Ortogonally, there is also the question whether if and how comparisons with +mixed signedness should work: + +* Forbid +* Forbid, but allow if the signed operand is never negative. +* Promote to unsigned (like C). But this is confusing. +* Compare by value, i.e. out-of-range values are handled specially + (and always return true/false depending on the side and operator). + + +Revise type detection/promotion entirely? +----------------------------------------- + +There is a performance and usability problem with the current system for +type detection. For example, given the following expression: + + [3]byte a = ... + byte b = a[0] + a[1] + a[2] + +Currently, each addition has to be performed as a byte, and range-checked. +That is both annoying (because it could overflow and/or give range errors +at compile time) and also slow, because the compiler needs to insert +instructions to range check and/or to remove excess bits. + +It would be better if it was computed as an uint/int. + +To avoid confusion, maybe the byte/int16 types should only be allowed +in structs/arrays? (and maybe in function parameters). + +If calculations are done with higher bit-width, then there are some edge +cases that need to be tested: + + var byte u8 + var wuint16 w16 + var uint u + + u = w16 = (u8 * u8 * u8) + +The multiplications could yield a larger number than "w16" can hold. +In that case, "u" should still receive the non-truncated value. + + +How other languages handle integer promotion +-------------------------------------------- + +* C: + - Promote to larger + - Promote to unsigned + - This leads to strange behaviour in mixed-signedness comparisons +* Hare: + - Promote to larger (but limited for uintptr/size types) + - Mixed signedness is an error + - This also solves the comparison issue |