lua-users home
lua-l archive

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


Luiz wrote:

> It will be interesting to see whether the particular semantics of 
> Lua fits other languages. Please report any results here.

I really like Lua's bytecodes. In fact, I'm rewriting my own interpreter 
(wxBasic), and am using Lua's bytecodes as the model for much of it. Java's 
bytecodes aren't general enough, and since wxBasic only has variant 
datatypes, Parrot wasn't really that useful.

I pretty much rely on 'luac -l' to see how Lua handles stuff, rather than look 
at the code (although that can be tricky, since Lua does a good job 
optimizing things away).

As for the differences, there are a number of places where I've had to differ 
from Lua. The FOR loops is one of them.

For one thing, Lua seems to do some magic with FOR loops that I haven't yet 
grokked. Neither FORPREP or FORLOOP actually references the loop index, so 
how do they know what variable to reference? (I'm too lazy to read the 
source.) I suspect that some information is being left on the stack, since 
'break' generates a POP 3 before the JMP. Oddly enough, a RETURN from a 
function from within several loops also only generates a POP 3, instead of a 
POP 6. Curious...

 A 'break' also generates an unreachable PUSHNIL 3 after the JMP, another 
puzzlement:

     1  [1]     PUSHINT         1
     2  [1]     PUSHINT         10
     3  [1]     PUSHINT         1
     4  [1]     FORPREP         9       ; to 14 <-- No reference to loop var
     5  [3]     GETGLOBAL       0       ; print
     6  [3]     GETLOCAL        0       ; i
     7  [3]     CALL            3 0
     8  [4]     GETGLOBAL       1       ; a
     9  [4]     JMPF            3       ; to 13
    10  [5]     POP             3 <-- What's being popped here?
    11  [5]     JMP             2       ; to 14
    12  [5]     PUSHNIL         3 <-- How can this be reached?
    13  [6]     FORLOOP         -9      ; to 5 <-- No reference to loop var
    14  [8]     END

Another wrinkle is that *any* variable in BASIC can be a loop variable. When a 
loop is declared, Lua sets aside three locals to hold (I assume) the loop 
index, end value, and step value. Since my interpreter is a single pass 
interpreter, I allocate a seperate cache for these in the locals, and end up 
having to add a parameter to FORPREP and FORLOOP, indicating where the end 
and step values are cached.

And since globals can be loop variables, there has to be FORLOOPLOCAL and 
FORLOOPGLOBAL. (Actually, I cheated and decided to use negative indices for 
GLOBALs).

In BASIC, you can even allow an indexed variable to be a loop variable. I 
decided to make life easy for myself and disallow that in my interpreter - 
you can imagine the havoc it would play with the bytecode!

So in my implementation, FORPREP and FORLOOP have two additional parameters, 
something like:

    13  [6]     FORLOOP  0  1 -9  ; local i, range cache at locals 1 & 2, to 5 

Arrays are another places where Lua and BASIC differ. Since BASIC supports 
arrays with multiple indexes, instead of something like:

   a[1,10] = 12

generating:

     1  [1]     GETGLOBAL       0       ; a
     2  [1]     PUSHINT         1
     3  [1]     GETTABLE
     4  [1]     PUSHINT         10
     5  [1]     PUSHINT         12
     6  [1]     SETTABLE        3 3

evaluation of the array indexes is deferred until SETTABLE:

     1  [1]     GETGLOBAL       0       ; a
     2  [1]     PUSHINT         1
     3  [1]     PUSHINT         10
     4  [1]     PUSHINT         12
     5  [1]     SETTABLE        2         ; 2 indices

I'll just mention two other typical differences. For one, BASIC doesn't have 
nil, so:

   if 0 then

works out differently. And some structures (like Try/Catch) require additional 
bytecodes.

But for the most part, Lua's bytecodes serve as an excellent model, and 
require little tweaking to adapt.

-- David Cuny