lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

Peter Hill:
> At runtime the type (for variables _and_ objects) is stored in the code
> that accesses the data rather than in the object/variable itself.
> And stack objects carry exactly the _same_ amount of type information that
> variables do, so if you say that variables (lvalues) are typed then you
> must also say that objects (rvalues) are typed as well.
> I think I see where we disagree, at least. I wouldn't have said that a
> variable and an lvalue are the same thing.

Lvalues may be read from and assigned to (including read-modify-write
operations such as "++") which makes them variables in the computer science
(though not mathematical) sense. Ie, they respond to getting & setting of
'values'. In practical terms, a "variable" is anything that may be on the
left side of an assignment (as well as appear in expressions); how it is
implemented is irrelevant.

> Consider the following fragment
>   int a, b;
>   a = f(7);
>   b = g(a);
>   a = h(b);
> where f, g and h are arbitrary functions or perhaps expressions.
> Now a careful analysis of the code would reveal that a and b are never
> used at the same time. So there is no impediment to keeping them in the
> same location, and many optimising compilers will do so.

So? Basing the definition of a language construct on what an optimising
compiler might do is flawed. If something is not used then it may be removed
regardless of what it is... variable, value, function, code block.

So a Lua snippet:
    a = {123}
    a = 4

could have the first assignment completely optimsed out. Does that mean that
"{123}" is not a value in Lua because the optimiser removed it?

Moreover, optimisers are *not* a part of the language. When you are defining
elements of a language you should base it on the langauge itself, not on
some conversion that an optimiser might consider it equivalent to. Remember,
if your whole program has no input/output then an optimiser could remove all
of your code and replace it with a single empty statement... which tells you
nothing about the language.

> Suppose the first statement were a=7 instead of a = f(7). In that case,
> the compiler would know at compile time what the argument to g was, and
> would not need to store the 7 anywhere at all. Again, many optimising
> compilers will do this.
> That's what I meant when I said that a variable is just the name of a
> value.

An identifier is the compile-time name (with regard to subsequent accesses)
of a language object, whether that object has storage (ie, a variable), is a
function, is data (ie, a value), etc. In some cases (such as Lua globals)
the name itself is also stored as a runtime value (a literal) to be used in
indexing other data.

Conceptually (in a language sense) 'a' could respond to loading & storing of
data. Because you didn't use its full potential, and hence an optimising
compiler degenerated its nature, does not invalidate its nature as far as
the language is concerned. Otoh, if the *language's* documentation (not the
compiler's) stated that, "any identifier that is only assigned once will be
treated as a constant, and no compile-time storage will be allocated" then
it would be a different matter.

> OK, now we have the following:
>   void set(void* x, void* y)
>   {
>      *(void**)x = y;
>   }
> int a[1];
> float b[1];
> set(a, b);
> See? No types :)

I disagree. 'a' and 'b' both have types, and the compiler recognises this in
normal usage... ie, a[1] = b[1] would produce an automatic fraction
truncation during the assignment of the value. That the C language happens
to provide a mechanism of  'type free' assignment (ie, temporarily
overriding the inherent type with your own interpretation) in addition to
its other type operations does not invalidate the compiler's common usage of
types. It just puts *some* of the responsibility of type implementation on
to the programmer (ie, whenever such 'type free' assignment is used). In C,
the programmer also has a similar responsibilty when unions are involved (as
opposed to Pascal which fully controls the access of variants).

Eg, consider:
  int a, b;
  if (a>5) b=a;

In the statement "if (a>5) b=a" the compiler is well aware of the types
involved, performing an integer comparison of the contents of the variable
'a', followed by a possible integer copy. Of course 'a' may have data of
dubious meaning in it because of the previous 'typeless' initialisation.

As far as Lua goes the situation is this...

- In basic Lua, variables are of only one 'type'... the one-size-fits-all
union. This is basically like Visual Basic's Variant type.

- The addition of metamethods for "index" and "newindex" changes the
situation, as now both global variables, eg:
    a = 5

and indexed variables, eg:
    z.a = 5

can alter their behaviour, responding differently to different types etc.
Local variables, eg:
    local a
    a = 5

have failed to keep up with this ability.

Peter Hill.