Hello Charles, I’m glad to hear you’ve found a way to get this working for you.
What follows is a more complete examination of some of the issues involved and an example script structure that may be helpful to others who would like to do something similar to implement a recovery and retry mechanism for their tests.
There are a couple of things to look at here: the do command, and the way you’re going about repeating the test.
About the Do Command
First, there is rarely a need to use the do command. The main reason one would use it is to execute some code that is constructed by the script at runtime. While do is potentially very powerful and can sometimes achieve things that couldn’t be done any other way, its power also comes at a cost. It calls the SenseTalk compiler at runtime, making it slightly slower to execute, and also (as I think you’ve found) incurring an extra level in the call stack as a result.
Usually, there are other ways to achieve the same result. I’m not sure if what you’ve shown is your actual code (I’m guessing not) but using the do statements you’ve shown as an example, you should be able to get the same results without “do” like this.
you could simply say
This will work if something is the actual name of the script you want to run. If (as I’m guessing is the case here) something is a variable name containing the name of the script, then you could use the run command, like this:
Your second use of do is more complex:
do ("run" && scriptName &"."& functionName && playerType & "," & loopLocation)
Here, you are actually constructing a command in text and executing it with do, which is exactly what do is good for. But it’s probably not necessary in this case either.
The run command, as shown in the previous example, will run a script whose name is stored in a variable (and does it without costing you anything extra in call depth). So the first part of the line above could become:
However, since you’re calling a specific handler in the script identified by scriptName, what you’ll really need is:
I’ve changed this to use the get command which treats functionName as a function call rather than a command message (the run command currently has some limitations that keep it from providing a similar solution). If the handler for that message is implemented as a “to” handler this will work fine, since a “to” handler will handle either command or function messages. If it was implemented as an “on” handler you’ll have to change it to either a “to” or “function” handler for this solution to work.
By putting functionName in parentheses here, it will be interpreted as an expression (a variable name in this case, although it could also be a more complex expression) that yields the name of the function to call. Without parentheses, it would try to call a function named “functionName” which isn’t what you want. The playerType and loopLocation values are passed as parameters to the function named by functionName.
By switching your code to use run and get instead of do, you can save one level on the call stack in each case.
One Approach to Recovering and Retrying a Failed Test
The second issue to look at is the way you are going about repeating a test after a failure. You can save some frames on your call stack here as well, by letting your LogError handler return and using another repeat loop to try the test again. Here’s what it might look like:
repeat with each item testname in testList
Log "Running Test " & testname
repeat 2 times -- maximum number of times to try
Log "Completed Test " & testname
exit repeat -- test ran successfully, don't repeat again
LogAnError testname, error
to LogAnError testname, error
LogError "Test " & testname & " got an error: " & error
-- other important stuff to prepare for running test again
Here, LogAnError reports the error and performs any necessary cleanup or recovery prior to attempting the test again, but doesn’t re-run the test itself. This way it can return (without adding to the call depth) and allow the calling script to repeat the test. The main test loop makes 2 attempts to run the test (this number could be increased if you like) and stops trying after the test completes successfully.
By making these changes, it should be possible to run any number of tests, repeating each test as many times as needed, without running into the call depth (recursion) limit.