Probs with variant records

Emil Jerabek ejer5183 at artax.karlin.mff.cuni.cz
Wed Nov 20 14:10:49 CET 2002


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 at yahoo.com) (cbfalconer at worldnet.att.net)
>    Available for consulting/temporary embedded and systems.
>    <http://cbfalconer.home.att.net>  USE worldnet address!
> 
> 




More information about the Gpc mailing list