[M3devel] M3CG

Antony Hosking hosking at cs.purdue.edu
Wed Sep 5 22:41:43 CEST 2012


Jay, why don’t you just us a local subrange for your fields in the records and then simply assign to/from TypeUID values?

RECORD typeid: [-16_7fffffff-1 .. 16_7fffffff] END;

You won’t pay any penalty for range checks since the subranges are exactly the same.

On Sep 5, 2012, at 2:34 PM, Jay K <jay.krell at cornell.edu> wrote:

> I should really insert padding manually?
> I don't know if I like that or not.
>  
> 
> My code is/was something like:
> 
>   TYPE T1 = RECORD  
>     text: TEXT;  
>     typeid: TypeUID;  
>   END;
>  
> 
> and that errors on some platforms.
>  
> 
> I'm not using "Multipass" right now, but it does still hold possible value.
> We can remove multipass from m3makefile for nowif that helps.
>  
>  
> Given a similar problem in C, I would do something like:
>  
> /* TypeUID must fit in 32 bits, for some reason. */
> C_ASSERT(sizeof(TypeUID) <= sizeof(UINT32));
> Where C_ASSERT is in windows.h and looks like:
> /* compile time assert */ 
>  #define C_ASSERT(expression) typedef char __cassert__[(expression) ? 1 : -1];
>  or somesuch. The error message isn't great when it fails. 
>  
> People also name this "static_assert". It is popular.
>  
>  It doesn't prohibit it from having padding around it,  but it does assert it fits in 32 bits.
> 
>  I recall we can do similar in Modula-3. 
> 
>   TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; 
>   or to be more certain: 
>   TYPE assertTypeUIDFitsIn32Bits = ARRAY [0..-ORD(BITSIZE(TypeUID) <= 32)] OF INTEGER; 
> 
> I'm not sure 0..0 is illegal, but I think 0 .. 1 is.
> 
> (I sure do miss macros...this is too much syntax for a compile time assert...)
> 
> Can we just put <* ASSERT BITSIZE(TypeUID) <= 32 *> in the .i3 file? Or elsewhere?
>  
> 
>  - Jay
>  
> > From: hosking at cs.purdue.edu
> > Date: Wed, 5 Sep 2012 11:36:03 -0400
> > To: jay.krell at cornell.edu
> > CC: m3devel at elegosoft.com
> > Subject: Re: [M3devel] M3CG
> > 
> > As I recall you were having trouble with alignment, right?
> > 
> > In which case, why not pad your record type out to a reasonably aligned value? As in:
> > 
> > CONST PadRange = Word.LeftShift(1, BITSIZE(ADDRESS) - BITSIZE(TypeUID)) - 1;
> > RECORD
> > t: TypeUID;
> > pad: BITS BITSIZE(ADDRESS) - 32 FOR [0..PadRange];
> > END;
> > 
> > 
> > 
> > On Sep 5, 2012, at 11:18 AM, Antony Hosking <hosking at cs.purdue.edu> wrote:
> > 
> > > Remind me again why you can't use TypeUID as is?
> > > There is nothing in the language spec that prohibits packed types in records.
> > > 
> > > On Sep 5, 2012, at 10:50 AM, Jay K <jay.krell at cornell.edu> wrote:
> > > 
> > >> This seems quite wrong from a simple engineering/design/factoring/abstraction point of view.
> > >> 
> > >> 
> > >> Imagine I have a few of these things. They are subranges or enums. That fit in a smaller size.
> > >> Wouldn't it be nice, to just use the type directly and get the space savings? Opportunistically?
> > >> What if the type is a REAL or a LONGINT?
> > >> I want the type to be opaque/abstract where that is easy and cheap and this certainly seems like an easy/cheap place to have slightly valuable opacity.
> > >> Isn't it really good, more than "just nice" to let the type change and have a lot of code work just as well?
> > >> Because they didn't copy around knowledge of what the type is?
> > >> What if the type changes?
> > >> Anyone just copying it around by exact restated typename is unaffected.
> > >> Anyone who looked at and decided to restate the definition might type might be broken.
> > >> 
> > >> 
> > >> And again, really -- you want to sacrifice both performance and abstraction when both are easily kept better?
> > >> That is, I'm all for range checks to keep things "safe", safety is important, but in this case you can easily preserve safety w/o adding range checks.
> > >> 
> > >> 
> > >> We do have enums at this layer.
> > >> Would you suggest I take the ORD of all of those and store them in INTEGERs too?
> > >> 
> > >> 
> > >> I am really surprised.
> > >> 
> > >> 
> > >> - Jay
> > >> 
> > >> 
> > >> From: hosking at cs.purdue.edu
> > >> Date: Wed, 5 Sep 2012 10:33:58 -0400
> > >> To: dragisha at m3w.org
> > >> CC: m3devel at elegosoft.com; jay.krell at cornell.edu
> > >> Subject: Re: [M3devel] M3CG
> > >> 
> > >> Precisely.
> > >> 
> > >> 
> > >> On Sep 5, 2012, at 3:40 AM, Dragiša Durić <dragisha at m3w.org> wrote:
> > >> 
> > >> Why holding/passing of this value in INTEGER would be a problem? As long as range checks are passed on "assignment boundaries", it is all well.
> > >> 
> > >> It is how Modula-3 does things. 
> > >> 
> > >> --
> > >> Divided by a common language
> > >> 
> > >> Dragiša Durić
> > >> dragisha at m3w.org
> > >> 
> > >> 
> > >> 
> > >> 
> > >> On Sep 4, 2012, at 10:47 PM, Jay K wrote:
> > >> 
> > >> RECORD HoldsTypeUID:
> > >> typeuid: [FIRST(TypeUID)..LAST(TypeUID)];
> > >> END?
> > >> 
> > >> 
> > >> But what if I'm really just a holder/passer of this thing,
> > >> and I never interpret it. Now TypeUID can't be changed
> > >> to LONGREAL or somesuch. Ideally some code wouldn't care
> > >> and still be correct.
> > >> 
> > >> 
> > >> The idea is to hold the thing, pass it on, without knowing
> > >> what it is. I want a field with the same type.
> > >> 
> > >> 
> > >> Why does it matter if TypeUID is representable in 32 bits?
> > >> Isn't the range the interface?
> > >> If it wasn't for readability of all the F's, I think
> > >> TypeUID = [-16_7FFFFFFF - 1 .. 16_7FFFFFFF]; is best.
> > >> 
> > >> 
> > >> Do we really care about few or many bits that occupies?
> > >> 
> > >> 
> > >> Cstdint.int32_t I agree is a bit lazy.
> > >> Maybe something like Word.Shift(1, 31) .. Word.Not(Word.Shift(1, 31)) ?
> > >> A bit wordy but ok.
> > >> Maybe not correct. Not clear the start is negative.
> > >> Maybe needs to be more like:
> > >> 
> > >> (-Word.Not(Word.Shift(1, 31))) - 1 .. Word.Not(Word.Shift(1, 31)) 
> > >> 
> > >> 
> > >> But these bit twiddlings might then confuse people.
> > >> So maybe having to count F's is better.. :(
> > >> 
> > >> 
> > >> You know, what about being 32bits in size would be part of an interface?
> > >> I don't think much/anything, but maybe.
> > >> 
> > >> 
> > >> Do we do/allow things like bit operations on it? Index into it a certain number
> > >> of bits? Take the address and assume BYTESIZE == 4?
> > >> I could see those maybe occuring. Maybe.
> > >> 
> > >> 
> > >> But I'm pretty sure they values are fairly abstract/opaque and the best anyone can do
> > >> is format them as strings and compare them for e.g. sorting purposes, but must
> > >> assume they are fairly sparse.
> > >> 
> > >> 
> > >> Btw, whenever the matter of "portability to signed-magnitude" or one's complement
> > >> comes up, I admit I get a bit confused. Two's complement is very ingrained
> > >> in my world view.
> > >> 
> > >> 
> > >> I agree TInt.T suffices.
> > >> Just like CARDINAL isn't needed, INTEGER suffices.
> > >> Cardinal.T just disallows negative numbers earlier, or at lower level, etc.
> > >> If we had to use TInt.T and add checks in a few places that it >= 0, ok.
> > >> It seems a little nice to put the checking in.
> > >> 
> > >> 
> > >> - Jay
> > >> 
> > >> 
> > >> 
> > >> 
> > >> > Subject: Re: M3CG
> > >> > From: hosking at cs.purdue.edu
> > >> > Date: Tue, 4 Sep 2012 13:05:34 -0400
> > >> > CC: m3devel at elegosoft.com
> > >> > To: jay.krell at cornell.edu
> > >> > 
> > >> > On Sep 4, 2012, at 12:09 PM, Jay <jay.krell at cornell.edu> wrote:
> > >> > 
> > >> > > "BITS" seems to not provide any useful value. It only makes it so you can't put the type into a portable unpacked record, which is what I was doing. I either have to pack my record somehow (counting target-dependent bits??) or lay out the fields carefully in some way that all targets allow. The problem was that some targets didn't like the layout.
> > >> > 
> > >> > For M3CG.TypeUID the BITS 32 enforces that it is always representable in 32 bits. This is a fundamental invariant of the compiler and run-time system. Removing it might allow bug creep. You don't need to pack your record. You just need a field sufficiently large to hold the value of a type id. In this instance an INTEGER field would suffice, or you can use the same subrange.
> > >> > 
> > >> > > Given the stated range, that you'll get enough bits to store it, what is the point in giving the size too? Isn't providing just the range and no particular size, sufficient & more abstract? Granted, I went the other way.
> > >> > 
> > >> > Only if an implementation chooses to store a subrange in as few bits as necessary. Yes, CM3 does this, but it is not guaranteed by the language spec. Here the size is the critical invariant.
> > >> > 
> > >> > > I don't remember but guessing:
> > >> > > 
> > >> > > 
> > >> > > Cardinal.T would be, like CARDINAL vs. INTEGER: only slightly subtley useful: same as TInt.T, but disallows negative numbers.
> > >> > 
> > >> > But for what purpose. The target does not have CARDINAL. It only has a target integer.
> > >> > 
> > >> > > Most likely I ran into places where a host integer/cardinal did not necessarily suffice, and so a target type was called for.
> > >> > > 
> > >> > > 
> > >> > > I know we have places that need to use target types but don't yet. Specifically for the sizes of things like records & arrays. Otherwise we have hacks where 64bit systems declare 32bit limits.
> > >> > 
> > >> > Again, TInt.T suffices for all of these.
> > >> > 
> > >> > > 
> > >> > > 
> > >> > > - Jay (briefly/pocket-sized-computer-aka-phone)
> > >> > > 
> > >> > > On Sep 4, 2012, at 7:11 AM, Antony Hosking <hosking at cs.purdue.edu> wrote:
> > >> > > 
> > >> > >> Jay,
> > >> > >> 
> > >> > >> I've been looking over some of your changes to M3CG interfaces. You'll notice that I removed your import of Cstdlib.int into M3CG_Ops.i3. It does not belong there. The type as declared:
> > >> > >> 
> > >> > >> TypeUID = BITS 32 FOR [-16_7fffffff-1 .. 16_7fffffff];
> > >> > >> 
> > >> > >> is correct as is. It is a 32 bit value that encodes a particular subrange, REGARDLESS of target machine. It is improper to change that definition to rely on some C type.
> > >> > >> 
> > >> > >> I also have some other questions. Why did you add the type Cardinal.T? This seems entirely unnecessary, since targets don't have a Cardinal type. The only type they have is a target integer. All other Modula-3 ordinal types should be simulated in the compiler using TInt.T. I would advise that it be removed. Also, I don't understand why you changed descriptions of the primitive types to use this Cardinal.T instead of the original CARDINAL to hold information about the bit size, alignment, and byte size. There is no situation in which a host will need to emulate the behavior of CARDINAL for these values (all can be represented using CARDINAL no matter what the host).
> > >> > >> 
> > >> > >> I am concerned that these changes reflect a desire on your part to change the world to fit your specific needs (whether justified or not). The interfaces defined in M3CG were carefully designed and inherit from a long code-chain going back to the 1980's and have not see huge changes since then. I strongly advise against making changes unless you have good reason, because there are a number of tools that rely on M3CG (not just those in the public sources).
> > >> > >> 
> > >> > >> I am going to do a pass to revert some of your changes, since they are causing a number of my systems to fail to build. (cf. Niagara on tinderbox).
> > >> > >> 
> > >> > >> I strongly advise that you try to use a private branch when developing new functionality. We as a community can then go through a revision process to vet substantive changes before merging them into the trunk.
> > >> > >> 
> > >> > >> - Tony
> > >> > >> 
> > >> >
> > > 
> >

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20120905/ce4b7095/attachment-0002.html>


More information about the M3devel mailing list