[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Lua Virtual Machine Spec?
- From: David <dcuny@...>
- Date: Sun, 4 May 2003 02:04:23 -0700
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