lua-users home
lua-l archive

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


>> So it cannot trigger the linehook at that point
>> because the VM instruction at that point might not be the start of a 
line;

> I thought line hooks are only triggered for valid Lua code. So, in
> my understanding (and through limited testing), if a line hook
> is triggered, the line number has to point to a valid line of
> Lua code.) Is that not right?

The code is written so that a line hook only happens at a line boundary.
However, the "line" is compiled into a number of VM instructions. Some
of those VM instructions do not start a line.

The count hook hooks on individual VM operations, but the line hook is
designed to correspond to the actual lines in the source code. So if
you had:
   a = a + 1; b = b - 1; c = math.floor((b - a) / 2)
in your program, that is only one line and the line hook would only
trigger once. That may not be what you want or expect, but that is the
way it works. :) In other words, the Lua Virtual Machine has no concept
of "statements" but it does have a many-to-one mapping from operations
to "line numbers"; the line hook triggers when it executes an operation
whose line number differs from the previously executed one (or when a
backwards branch is taken even in the same line, which means that the
statement:
  while a do a = f(a) end
will hook on each execution of the while loop. This was added in
Lua 5, I believe, and is quite useful.)

>> So if you think of a line hook happening *after* each line, instead of 
>> *before* each line

> To test that concept, I placed a 'print("end of script")' message
> as the very last line in a Lua script, and let it run with the
> line hook attached (the line hook currently prints debug info
> to the command line). If the line hooks are fired after each
> line, one would expect the line hook to fire after the last
> line of Lua code. But it is not, so I am certain that line
> hooks are fired before each line. 

Yes, you are right. "after" is not correct either. I suppose that
"between" would have been a better word. Hmmm. The reason it
didn't trigger after the last line in the script is that there
is an *implicit* return in the script and the implicit return
is implicitly on (rather than following) the last line.

I believe you could change that behaviour with a small patch
to lparser.c. Lines 375-376 currently read:

  check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> 
expected");
  close_func(&lexstate);

You could add one statement between them:

  check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> 
expected");
  lexstate.lastline = lexstate.linenumber;
  close_func(&lexstate);

And the implicit return would probably have its own linenumber (assuming 
the
file ends with a newline).

I do stand by my statement that you should probably use both
line hooks and call hooks.

> Right now, I am simply initializing the line hook after I attach
> it to the Lua state. I am calling luaG_inithooks() declared in
> ldebug.h, and so far I have not experienced any problems. It is
> also possible to include lstate.h and write
> lua_state_pointer->hookinit = 1, which seems to work the same way,
> although the assignment is only a part of what luaG_inithooks() does.
> My main concern is whether any of these two solutions may cause
> problems later, or if they are both completely safe.

I'm not actually sure what you mean by "attach it to the Lua state",
so it is hard to say. Any problems you ran into would have to do with
threads / coroutines, I think, so you are probably OK *BUT* it is 
never a good idea to use undocumented internal interfaces if there is
an alternative; I certainly cannot pretend to understand the code base
well enough to guarantee you that you will not run into problems there.
There are some particularly intricate interactions between hooks and
coroutines.

R.