[TADS 3] Debugging / Tracing Verbs

19 views
Skip to first unread message

Jeff Nyman

unread,
Aug 13, 2006, 1:59:26 PM8/13/06
to
This may sound like an odd question but I am curious if anyone has an idea
of how to implement a "debug" type of command in TADS 3 such that when you
typed a command, a sort of "tracing output" could be given that would show
you how often verify(), check() and action() were called and on what objects
they were called on. (This is sort of akin to the idea of ACTIONS ON and
RULES ON in Inform 7.)

I am guessing some of this I could glean via the debugger but the problem is
that I am finding it is hard to parse through all the files that you get
taken through. I am never sure where I am safe to "step over" something and
where I am not.

Alternatively, are there any pointers on good places in the ADV3 library to
put a breakpoint in the debugger if what you want to do is trace the
execution of a command after it is entered?

- Jeff


Eric Eve

unread,
Aug 13, 2006, 5:02:49 PM8/13/06
to
"Jeff Nyman" <jeffnyman_nospam@nospam_gmail.com> wrote in message
news:V9-dnbXGLYvg9ULZ...@comcast.com...

> This may sound like an odd question but I am curious if anyone has
> an idea of how to implement a "debug" type of command in TADS 3
> such that when you typed a command, a sort of "tracing output"
> could be given that would show you how often verify(), check() and
> action() were called and on what objects they were called on.
> (This is sort of akin to the idea of ACTIONS ON and RULES ON in
> Inform 7.)

As you're probably aware there is a DEBUG command in TADS 3, which
simply breaks into the debugger. I'm not immediately sure how you'd
go about implementing the kind of TRACE command you have in mind
(off the top of my head it doesn't feel straightforward), but from
my own experience of using the debugger I think what you'd find is
that a command cycle would involve multiple calls to the verify()
part of all potential direct and indirect objects involved in the
command, and a single call to the check() and action methods of the
objects actually involved.


> I am guessing some of this I could glean via the debugger but the
> problem is that I am finding it is hard to parse through all the
> files that you get taken through. I am never sure where I am safe
> to "step over" something and where I am not.
>
> Alternatively, are there any pointers on good places in the ADV3
> library to put a breakpoint in the debugger if what you want to do
> is trace the execution of a command after it is entered?

It's difficult to generalize without knowing what it is you want to
see. You could, for example, put a breakpoint on the first
executable line of executeCommand() in exec.t and then step through
the entire command process, but as perhaps you've already discovered
that can be a bit overwhelming. If you're interested in tracing
where particular verify(), check() and action() methods get called,
you might do better to put your breakpoints in the particular
verify(), check() and action() methods you're interested in. For
something in between you could try setting breakpoints in, say, the
execAction() method of TAction and stepping into the methods called
from there.

Without knowing what you're looking for, it's hard to give more
specific advice, though I appreciate it may be hard to know what
you're looking for until you know where to find it! If you're not
sure, perhaps you could try starting with the last of my suggestions
and see where it leads you.

-- Eric


Jeff Nyman

unread,
Aug 14, 2006, 7:42:20 AM8/14/06
to
Eric Eve wrote:

> It's difficult to generalize without knowing what it is you want to
> see.

> Without knowing what you're looking for, it's hard to give more


> specific advice, though I appreciate it may be hard to know what
> you're looking for until you know where to find it!

Understood. As an example of what I am doing, I have a new verb called
Test. I know that I need to put an illogical() method in my verify()
routine. However, when I do not have that in place, I get this if I
type >TEST (without a direct object) at the command prompt:

<game output>
There's no reason to test the {the dobj/him}.There's no reason to test
the {the dobj/him}.There's no reason to test the {the dobj/him}.There's
no reason to test the {the dobj/him}.There's no reason to test the {the
dobj/him}.There's no reason to test the {the dobj/him}.There's no
reason to test the {the dobj/him}.There's no reason to test the {the
dobj/him}.There's no reason to test the {the dobj/him}.There's no
reason to test the {the dobj/him}.There's no reason to test the {the
dobj/him}.There's no reason to test the {the dobj/him}.There's no
reason to test the {the dobj/him}.What do you want to test?
</game output>

But if I type >TEST OBJECT, where "OBJECT" is a defined object in the
game (derived from Thing), I get this:

<game output>
There's no reason to test the {the dobj/him}.There's no reason to test
the {the dobj/him}.

There's no reason to test the the dummy object.
</game output>

Purely as a means of understanding what objects are being acted upon, I
wanted to see if I could trace what method was called in which object.
I figured this would help me more clearly understand how verbs work and
how and when various routines are called.

It is not so much a "debug" that I would want as it is a "simple"
trace. That said, I did try some different breakpoints in the debugger
but it is massive overkill when you just want to see what is going on
in a narrow focus. Or, at least, for me it seems to be overkill. (Plus,
after awhile, you get taken through so many files in the ADV3 library
that it is hard to keep track of what is going on anyway.)

I will try some of your suggestions and play around. If I find anything
moderately interesting, I will be sure to post back here.

- Jeff

Eric Eve

unread,
Aug 14, 2006, 9:10:37 AM8/14/06
to
"Jeff Nyman" <jeff...@gmail.com> wrote in message
news:1155555740.7...@74g2000cwt.googlegroups.com...

> Understood. As an example of what I am doing, I have a new verb
> called
> Test. I know that I need to put an illogical() method in my
> verify()
> routine. However, when I do not have that in place, I get this if
> I
> type >TEST (without a direct object) at the command prompt:
>
> <game output>
> There's no reason to test the {the dobj/him}.There's no reason to
> test
> the {the dobj/him}.There's no reason to test the {the
> dobj/him}.There's
> no reason to test the {the dobj/him}.There's no reason to test the
> {the
> dobj/him}.There's no reason to test the {the dobj/him}.There's no
> reason to test the {the dobj/him}.There's no reason to test the
> {the
> dobj/him}.There's no reason to test the {the dobj/him}.There's no
> reason to test the {the dobj/him}.There's no reason to test the
> {the
> dobj/him}.There's no reason to test the {the dobj/him}.There's no
> reason to test the {the dobj/him}.What do you want to test?
> </game output>

This looks to me like the parser is running through all the objects
in scope, trying to see if there is one single object that stands
out as the most logical target of a TEST command so that it can be
used as a default here. This, indeed, is one of the main things
verify() is for, namely to identify which objects the player most
likely meant to refer to. Roughly what's happening here, I think, is
that the action-processing routine is going through the verify
routine of every object in scope, building a list of the objects and
their logical ranks for the action to see if there is a most logical
candidate. In this case no candidate emerges as being uniquely the
most logical, so you're prompted for a direct object.

One way to trace this might be to do something like the following:

dobjFor(Test)
{
verify()
{
if(libGlobal.tracing)
"Trying verifyDobjTest() in <<theName>>.\n";
illogical('There\'s no need to test {the dobj/him}. ');
}
}

And then add another TRACE ON|OFF command that toggles
libGlobal.tracing between true and nil.

> But if I type >TEST OBJECT, where "OBJECT" is a defined object in
> the
> game (derived from Thing), I get this:
>
> <game output>
> There's no reason to test the {the dobj/him}.There's no reason to
> test
> the {the dobj/him}.
>
> There's no reason to test the the dummy object.
> </game output>

In this instance "OBJECT" probably uniquely identifies the object in
question, so the parser only needs to look at the verify() method
for this one object. It still does so several times for reasons I
don't fully claim to understand, but part of it has to do with an
early pass whittling down the list of objects you might plausibly be
referring to (and I think the same logic applies even if there's
only one object in the initial list) in the course of resolving your
command to a particular object, while the final pass (after object
resolution) prints out the "illogical" message to explain the
refusal to act if it is determined, as here, that the action is
ruled out on the object in question.

-- Eric


Jeff Nyman

unread,
Aug 15, 2006, 6:42:59 PM8/15/06
to
"Eric Eve" <eric...@NOSPAMhmc.ox.ac.uk> wrote in message
news:ebpsoj$lij$1...@frank-exchange-of-views.oucs.ox.ac.uk...

> "Jeff Nyman" <jeff...@gmail.com> wrote in message
> news:1155555740.7...@74g2000cwt.googlegroups.com...
>
> One way to trace this might be to do something like the following:
>
> dobjFor(Test)
> {
> verify()
> {
> if(libGlobal.tracing)
> "Trying verifyDobjTest() in <<theName>>.\n";
> illogical('There\'s no need to test {the dobj/him}. ');
> }
> }

I apologize for the late response to this. I did try this out, Eric, and it
actually works quite well. At the very least it can show me what TADS 3 is
trying at various points with what objects.

I am not always sure exactly *why* TADS 3 is trying certain things, but
knowing a little is better than knowing nothing. :)

- Jeff


Reply all
Reply to author
Forward
0 new messages