[ Long email warning - some may find the low-level programming stuff at the
end interesting, others may want to avoid ]

----- Original Message -----
From: "Kerry Thompson" <[EMAIL PROTECTED]>
>
> As I said, the debate became rather acrimonious, to the point that some
> people, including MM engineers, left the list. Several people on the
> list now were around for the brouhaha--Alex de Franca remembers ^_^

I'm sure it was due to the shame of having to follow the party line on this
whole VOID=true business. That *is* what it comes down to - they are saying
that VOID is "undefined" when that is simply not true, except in a buggy
language implementation.

> > I might check the documentation
>
> Don't bother. Your search will return <void>.

:-)

> True, except when it's NULL ;-)
>
> x=NULL
> put x
> -- <Void>

AFAIK, NULL is simply a constant representation of the VOID type - the same
as TRUE in Lingo is actually the integer 1 and FALSE is the integer 0. Some
other loosely typed languages such as PHP actually have a boolean type, so
FALSE !== 0. TRUE is a more complex one than =1 or != 1, since TRUE is
generally represented by -1 since that is the bitwise inverse of FALSE (0).
At least, most C programmers do it that way, more out of convention than
anything (much like the convention to use the variable name "me" in Lingo
instead of the more traditional "this" in all other OOP).

> I can't reproduce it now either, on the systems I have. I wish I could.
> The bottom line, though, is that you should check for voidP before doing
> any Booleans, at least in Lingo.

That's a shame. At the very least, it is undesirable behaviour. I would
still regard it as a bug, even if Macromedia were too lazy to fix it that
week. What should happen in any aritmetic expression is that types should
follow a known order of implicit up-casting. For instance, VOID upcasts to
int, and int upcasts to float, wherever required to do so by an arithmetic
or logical operator. Not doing this somewhat limits the usefulness of any
scripting language.

There is no point in a scripting language that /requires/ type checking
before every statement. You might as well write all your code in C or Java
because at least then you'd know what the types are in advance.

> In another post, I mentioned that <void> was the absence of a value, and
> you said that it is a specific value. Actually, I think we're both
> correct. I don't have my Kernighan & Ritchie handy (we just moved, and
> boxes are everywhere), but C and Lingo do treat it differently. I was
> going by Macromedia's documentation, which says voidP "determines
> whether the variable specified by variableName has any value." Since
> this is a Lingo list, I was referring to <void> in Lingo. You're right
> in other contexts, though. Maybe we should all go back to twiddling bits
> in 6502 assembler.
-----
From: "Howdy-Tzi" <[EMAIL PROTECTED]>
>
> But void is not zero, any more than, in C:
>
>    int foo;
>
> makes foo a valid variable. You don't know what's in it and testing it
> without first stuffing a value into it:
>
>    int foo = 3;
>
> can lead to all kinds of weird problems.

Just to get the record completely straight on the different meanings of void
or VOID - the following is a lengthy and technical discussion of points that
you may all be aware of, but may also clear up a few ambiguities:

In C everything is typed. So, the declaration:

  int foo;

Allocates a 2-byte block of memory and "foo" is set as a static pointer to
that memory location. However, what that statement does not do, is put any
specific value in the 2-bytes of memory, so at runtime it could contain
anything. This is known as "undefined" - that is *not* a specific value
(unlike VOID), nor is it the absence of value either, it is the absence of
prior *knowledge* of what the value should be.

  int foo = 3;

Does exactly the same, except that it always starts with 0x0003 in the 2
bytes set aside for the variable foo, so we know what the value is.

The keyword "void" in C is also unlike VOID in Lingo. In C, this indicates
an unknown, or don't care value. There are 2 possible uses, one to indicate
that a function does not return a value, and another which is the void
pointer:

void *voidpointer = 0xb8000000;

This example is a base-address pointer to the colour text mode video memory
on the PC. Pointer aritmetic on a void pointer is performed in bytes, so
*( voidpointer + 100 ) means the value at the 100th byte in the video
memory. However, since the pointer is void, we don't know how many bytes to
read from that base address, so some casting is required (often done
implicitly by the compiler when the pointer is assigned to a variable, but
it depends on the "strictness" settings).

This is different to typed pointers like:

int *intpointer = 0xb8000000;

in which pointer arithmetic operations are automatically multiplied by the
size of the type. In this case sizeof(int) = 2, so (int)*( voidpointer +
100 ) is precisely equivalent to *( intpointer + 50 ). Internally that
compiles into (int)*( intpointer + (50<<1) ).

All of this is still working with *fixed types* - the void pointer allows
you to vary the type at runtime, but you still need to know what type you
want to be dealing with at any given time. Generally it is only used for
pointers into hardware memory, such as the video card.

Languages such a Lingo are not strongly typed. Loosely-typed variables are
actually tiny polymorphic objects. Variables are not allocated into static
regions of memory only large enough to hold the required value. Instead, a
much larger block is allocated. I'm not sure of the Lingo specifics, but
it's usually around 16 bytes. The first byte of this block is used to
determine the type of the following data. So, a 0x01 might mean that the
next 4 bytes are used, and the value is an integer. An 0x02 might mean the
next 8 bytes are used to hold an IEEE754 floating-point value. 0x00 would be
the logical choice to represent VOID.

So, if the entire 16 bytes is 0, that is VOID. In fact, if the first byte is
0, the rest can be anything you like and it is still VOID. That does not
mean that VOID is the same as "undefined". We may not know (or care) what
the physical value of the bytes after the lead-in are, but the logical value
is still VOID, which is (or should be) stricltly defined as part of the
language specification.

What I suspect is going on in the "not a bug" case is that the steps leading
up to the VOID do not cleanly set VOID as all zeros, but do set the
indentifying header as zero, marking the data as VOID. Then, at the boolean
stage, instead of correctly handling the VOID type as FALSE, what happens is
that VOID is incorrectly handled as an integer value. If cleanly set to
VOID, it will be set to all zeros anyway, and this would not matter.
However, if only the header is zeroed, and the body is left undefined, then
you may get a phantom nonzero value.

In my book - that is *definitely* a buggy implementation. As I have gone to
great lengths to point out, VOID is not an undefined value, nor is it like
NaN (which also has specific rules about propagation) - it is a very
specific *known* constant. VOID should be our friend, it is an integral part
of any loosely typed language. The fact that Macromedia are quite happy with
a broken implemementation IMHO, seriously undermines the credibility of
Lingo as a useful scripting language. Sorry to say it, but as a major
advocate of Lingo, this has put me off it slightly.

- Robert

PS: After writing this, I realised that my test-code probably wouldn't
demonstrate the bug. Most likely a "dirty" VOID is being returned by a
function, probably in an Xtra. In that case, the bug may well affect later
versions of Windows, as well as the one that demonstrated the problem
before, but it will only show up when the VOID contains a non-zero body.

[To remove yourself from this list, or to change to digest mode, go to 
http://www.penworks.com/lingo-l.cgi  To post messages to the list, email [EMAIL 
PROTECTED]  (Problems, email [EMAIL PROTECTED]). Lingo-L is for learning and helping 
with programming Lingo.  Thanks!]

Reply via email to