On Tue, Nov 19, 2002 at 04:55:47PM -0500, CBFalconer wrote:
"J. David Bryan" wrote:
On 19 Nov 2002 at 12:00, CBFalconer wrote:
This particular error is **very** hard to detect at run-time in any efficient manner.
I'm not sure I understand this. Is it not a matter of checking, before each component access, whether the variant selector (or selectors) is in the range of the corresponding case-constant-list? Isn't that a simple range check, e.g., equivalent to that performed before an assignment?
No. Let's consider
TYPE r = RECORD CASE a : integer OF 0: ( onebyte : 0..127); 1: ( twobyte : -5..512); END;
(BTW, one of these ENDs is spurious, I think.)
END;
VAR rcd : r; .... r.twobyte := something; (* something may be an integer *)
The compiler tables hold something describing the location of r, and offsets from there to a, onebyte, and fourbyte. It also holds acceptable ranges for each value. It can generate code (for a stack machine) something like:
LDCA r (* address of r *) LDC offsetof twobyte ADD (forming address of twobyte, or maybe onebyte *) LOD something (* whatever is to be stored *) CHK minval, maxval (* which may cause an exception *) STI 1 (* putting it away *)
Now, where is the compiler going to get the values of minval and maxval? To do so it would have to read a, and translate that somehow into minval and maxval at run time. Where are those tables stored? Nothing insists that a be a valid initialized value before storing something in onebyte. Remember, onebyte and twobyte have the same offsets. They can store different subranges. a may have been set in another procedure far, far away.
Don't understand this. The problem was to check that the component accessed is valid, which is as simple as ``r.a = 1?'' in your example. Anyway the range check which you seem to be talking about is also easy: the code stores something into r.twobyte, hence the value should be range-checked against the definition of twobyte, i.e. minval = -5 and maxval = 512. These bounds are known at compile time, and they have nothing to do with the current value of r.a.
In addition, the compiler knows that it is storing a twobyte value. If it got it from something of appropriate type it knows it need not do a check on this store, and can totally elide the CHK operation. No such efficiencies if we have to read and translate the a value first.
Without that check the only differences for storing onebyte and twobyte are the (known at compile time) values of minval and maxval, and quite possibly the operand of STI, which specifies the size of the thing to be written.
In other words full checking here is a monstrous can of worms.
Checking that the variant selector is in range never enters into it (except when storing that value at some other time). The names
Yes, it does. Here, the ``range'' was 1 .. 1, but the ISO 10206 standard permits a general range (or list of ranges) in such a situation.
type R = record case A: Integer of 0 .. 24, 29: (OneByte: 0 .. 127); 25, 30 .. 42: (TwoByte: -5 .. 512); otherwise (MoreByte: Real) end;
in the different variants are known to be disjoint (standard specified) so that the name used specifies the variant desired. Also there is no default "otherwise" clause in this flavor of a CASE statement AFAIK.
See above.
Emil
-- Chuck F (cbfalconer@yahoo.com) (cbfalconer@worldnet.att.net) Available for consulting/temporary embedded and systems. http://cbfalconer.home.att.net USE worldnet address!