Frank Heckenbach wrote:
CBFalconer wrote:
Frank Heckenbach wrote:
... snip ...
and I strongly favor making these syntactical extensions functions (so they can be easily replaced in purely standard systems)
Sorry, but this discussion is not really about syntax. We want to be compatible with other compilers where that's easily possible, and several other compilers use such operators. This is just about the semantics which, in other compilers, after often only defined poorly (or accidentally, or for special circumstances).
If you make them available as standard procedures, you can then add code to call them with other syntax when emulating those other systems. Yet you preserve the ability to write new portable code using the operations.
and naming them asl, asr when they consider the sign. That allows clear distinction from lsl, lsr which insert 0 bits at one end or the other, and can be defined to never create an overflow by using modular arithmetic as in C unsigned.
As I wrote, this makes the operations dependent on the type size.
Not for asl, asr. They simply do whatever is needed for the multiply or divide by 2. Only asl can overflow. lsl does the same thing, but ignores overflow and works as if the representation were unsigned binary. lsr inputs a 0 bit, and is a special case.
That's why C needs to distinguish between a "short" and a "long" number 1 (and various other sizes), even for constants (`0L' etc.). I definitely don't want such semantics in GPC and prefer value-based identity (in accordance with the standards as far as arithmetics are concerned).
That's my main grief with C's "modular arithmetics"(*). While something like 3 * MaxInt would be an error in Pascal (though GPC doesn't currently detect it), the equivalent expression (on usual types) in C is *defined* to be equal to MaxInt - 2.
(*) BTW, it's not really modular arithmetics, as e.g. `/' is defined quite differently (e.g., modulo 16: 3 / 7 = 5, while in C arithmetics 3 / 7 = 0). Modular arithmetics is often claimed by C supporters who want to argue that C has much resemblance to mathematics, but it doesn't really apply.
One potential problem with shl is that it can easily produce overflows. Currently it's not a practical problem, as GPC doesn't do overflow checks, but when it does, we'll have to consider this case. We could define `shl' to "ignore overflows", but this would again make the semantics type-size-dependent. Of course, a
This is why the arithmetic and logical shift operations should be firmly separated. The logicals will be defined in terms of modulo arithmetic, just as C does.
Overflow can happen with signed and unsigned types just as well. I fail to see your point here.
Not when you say you will resolve an unsigned overflow by adding or subtracting the maximum + 1 of that unsigned entity until it fits. Remember this only applies to resolving the action of lsl and lsr, and making their operation overflow free. The C technique works. Range checks can still exist for storing the result.
Rotates are problematic since they indeed depend on the type size. I see no way to define them independently. I've had a discussion with Mirsad Todorovad about these, and we came to the conclusion that it's probably more trouble than it helps. E.g., if a is a constant and we use the term `a ror 4', suddenly the type of the constant becomes very important (not just for whether there's an overflow, but it would change the result completely) which is contrary to Pascal's rules.
Again, define them as functions, and let the function parameters include the size in terms of binary bit count:
FUNCTION ror(in : T, places, bits : int) : T;
This would be possible, but could easiy lead to less efficient code when places or bits is variable. I'm writing "or" because I'm not really sure which means what -- to me "places" and "bits" means basically the same in this context. Which one is the rotation count and which one corresponds to the "type size"?
Pick it. Maybe size is a better name than bits. There has to be a limit on the value such that the result can be represented in an integer. You really want still another, rorc and rolc (rotate through carry) but that may be awkward to implement and describe.