Can someone please tell me what causes a stack overflow? The thing that confuses me, is it doesn’t happen all the time. I can run my script several times without a prob’, then suddenlt, out of the blue I get a Stack Overflow eror. Is it a memory issue? I’ve tried cleaning-up the script as much as possible, and even tried script debugger, but I don’t think I know how to use SD well enough. Maybe if I know the cause of a Stack Overflow, I’ll be able to fix the problem.
MUCH Thanks in advance,
-G
I guess it’d be easier to help me if you could run the script, but like I said it may take a few runs through before an error occurs.
property mistakeliststring : ""
property practiceletterstring : ""
property practiceLetter : ""
property practiceList : ""
property wordCheck : " "
property mistakeList : " "
property ALetter : " "
property startTime : ""
property timeDifference : ""
property endTime : ""
property theTypedWord : ""
property wpm : 0
property chosenWord : ""
property number_correct : 0
property wpmstring : ""
property avNumWords : 0
--*************************
reset()
--*************************
to reset()
set startTime to 0
set endTime to 0
set timeDifference to 0
set number_correct to 0
set wpm to 0
set wpmstring to ""
set practiceList to ""
set practiceLetter to ""
set mistakeList to ""
set mistakeliststring to ""
set practiceletterstring to ""
set wordCheck to ""
set ALetter to ""
set startTime to ""
set theTypedWord to ""
set chosenWord to ""
set wpmstring to ""
set avNumWords to 0
-----------------------------------------------
display dialog "GassyTypingPractice 1.0" & return & return & "Type the letters above the text area," & return & "as in the example below." & return & return & "example" default answer "example" buttons {"Cancel", "START"} default button "START" with icon 1
PreSet()
end reset
--*************************
to PreSet()
if timeDifference > 4 then
showscoreEnd()
end if
try
set practiceLetter to some item in practiceList
end try
getlevel()
end PreSet
--*************************
to getlevel()
if wpm is less than 6 then
set the_list to {"asdf", "afds", "sfad", "dsfa", "jkls", "ljka", "jaks", "lfks", "sjal", "fjsl", "lkds", "kjfd", "alsk", "ajdl", "jlfs"}
else if wpm is less than 11 then
set the_list to {"ahsdf", "qazw", "azqx", "wsxe", "sxwc", "edcr", "dcev", "rfve", "fvrc", "tgvf", "yhbn", "ujni", "jnum", "ujmi", "jmun", "ikjo", "lkjm", "afhds", "sfagd", "hdsfa", "jklgs", "lhjka", "jhaks", "lfksg", "sjhal", "gfjsl", "lkdsh", "kjfgd", "ahlsk", "ajdgl", "jhlfs", "ghfjd", "flash", "glads", "ksgha", "lhgsj"}
else if wpm is less than 16 then
set the_list to {"stew", "huge", "polite", "ploy", "swat", "rough", "read", "quiet", "pride", "dead", "deal", "kill", "hurt", "shirt", "justify", "height", "flush", "they", "used", "pout", "proud", "trout", "great", "gift", "queer", "iraq", "wade", "quote", "thought", "kite", "pike", "lake", "fake", "freak", "treat", "trees", "rush", "trash", "dry", "droop", "pair", "fright", "fryer", "flight", "spite", "trout", "read", "seed", "dear", "poke", "speed", "seed", "ripe", "quilt", "dark", "dusk", "yard", "party", "dirty", "flirt", "flower", "flour", "squirt", "square", "jail", "jerk", "jimmy", "jewish"}
else if wpm is less than 21 then
set the_list to {"hello", "Gary", "button", "laxative", "next", "xerox", "extreme", "excited", "house", "tonight", "cigarette", "kitchen", "Milwaukee", "Wisconsin", "Franklin", "penny", "nickle", "dime", "quarter", "dollar", "king", "queen", "jack", "ten", "nine", "eight", "seven", "six", "five", "four", "three", "two", "one", "zero", "after", "army", "apple", "ace", "blue", "brown", "red", "yellow", "rhyme", "green", "black", "white", "iraq", "iran", "bingo", "beatles", "ghost", "sign", "president", "exit", "enter", "door", "window", "zipper", "jazz", "buzzard", "blizzard", "century", "circus", "days", "enough", "elephant", "echo", "flight", "french", "hat", "hour", "ink", "itch", "jinx", "jerk", "lamp", "listen", "mouth", "mice", "market", "never", "knife", "north", "opera", "ounce", "park", "punt", "resist", "run", "rope", "sit", "shelf", "start", "store", "square", "time", "that", "them", "try", "under", "above", "uncle", "usher", "vice", "vote", "work", "when", "winter", "wonderful", "year", "typist", "television", "lazy", "guitar", "water", "sugar", "orange", "rake", "injury", "tissue", "empty", "automobile", "crazy", "happiness", "munch", "crunch", "examine", "burn", "verse", "over", "squint", "squeeze"}
else
set the_list to {"Hello, how are you today?", "Gary is a very cool dude.", "Button your flannel shirt.", "The fireplace burned brightly.", "Tonight is all we have.", "Smoke gets in your eyes.", "Let's paint the kitchen purple!", "Milwaukee is the beer capitol.", "Wisconsin is the dairy state.", "Franklin is very near to Milwaukee.", "A penny earned isn't much.", "A nickle equals five cents.", "Two nickles equal one dime.", "I'll have a quarter pounder.", "Can I have a dollar?", "king Henry had headless wives!", "A queen bee is huge!", "Jack sprat ate no fat.", "Ten people ran that way.", "Nine comes right after eight.", "Eight tacos with hot sauce.", "Six feet deep sounds good.", "Five threes is a Yahtzee!", "The dog wants to go for a walk.", "Three little pigs arrested me.", "Two more for the road!", "One is the loneliest number.", "Here's your prize.", "The aspirin is in the medicine cabinet.", "Our army is much bigger.", "Don't eat the poison apple.", "The ace is the highest.", "The grey sky turned blue.", "I want to drive the van next.", "Do my eyes look red?", "Your yellow shirt is dirty.", "Axe doesn't rhyme with bird.", "Is the lawn green yet?", "Black widow spiders scare me.", "Reggie White sacked the quarterback!", "Iraq is nice to visit.", "Iran harbors terrorists no more.", "Bob Dylan wrote excellent lyrics.", "Casper is a friendly ghost.", "The sign is located above the door.", "Please vote for president Bush.", "The exit is that way.", "Don't enter while I'm showering.", "We need new carpeting in here.", "Wash the window with ammonia.", "My zipper is stuck again!", "Jazz music can relax me.", "The buzzard circled our camp.", "This blizzard better stop soon!", "That happened nearly a century ago.", "Circus clowns drive little cars.", "Forty days and forty nights.", "That's enough spaghetti for me.", "Elephants can remember very well.", "Do you hear an echo?", "Flight was a great invention.", "French people hate french fries.", "This knife isn't sharp anymore.", "A compass always points north.", "Good Opera hurts my ears.", "How many ounces was that?", "Don't park in my spot!", "Please don't punt the ball.", "How can you resist me?", "Walk, don't run in here.", "Is that rope tied securely?", "Just sit down and watch.", "The shelf can't hold that.", "Let's start all over again.", "Squirrels store all their nuts.", "Squares can't fit into circles!", "Time is on my side.", "It takes a lot to laugh, but it takes a train to cry.", "Some are smears, and some are spots.", "Al Gore invented the internet.", "Still crazy after all these years.", "Megan wishes she could be cool like Gary.", "Go fly a kite.", "Do chickens have lips?"}
end if
repeat 10 times
set chosenWord to some item of the_list
set chosenWordi to items in chosenWord
if practiceList is "" then exit repeat
if practiceLetter is in chosenWordi then
set practiceletterstring to "It's time to practice the letter " & practiceLetter & "."
exit repeat
else
set practiceletterstring to ""
end if
end repeat
giveWord()
end getlevel
--*************************
to giveWord()
set numLetters to count of chosenWord
set avNumWords to numLetters / 5
set startTime to current date
set {theTypedWord, button_pressed} to {text returned, button returned} of (display dialog "GassyTypingPractice 1.0" & return & return & wpmstring & " words per minute." & return & ¬
practiceletterstring & return & return & chosenWord default answer "" buttons {"Cancel", "PAUSE", "NEXT"} default button "NEXT" with icon 1)
if button_pressed is "PAUSE" then
showscore()
else if theTypedWord ? chosenWord then
getbadletter()
end if
goodAnswer()
end giveWord
--*************************
to goodAnswer()
set endTime to current date
set timeDifference to timeDifference + (endTime - startTime) / 60
set number_correct to number_correct + avNumWords as string
try
set wpm to (number_correct / timeDifference)
set wpm2 to (number_correct / timeDifference) as string
end try
if (count of wpm2) > 3 then
set wpmstring to items 1 thru 4 of wpm2 as string
else if (count of wpm2) < 4 then
set wpmstring to wpm2 as string
end if
PreSet()
end goodAnswer
--*************************
to getbadletter()
beep 1
set oops to theTypedWord as text
set typedletters to items in oops
repeat with ALetter in chosenWord
if typedletters does not contain ALetter and ¬
ALetter is not in mistakeList and ¬
ALetter is not in {" ", ",", ".", "'", "?", "!", ""} then
set mistakeList to mistakeList & " " & ALetter
set practiceList to practiceList & ALetter
end if
end repeat
badDialog()
end getbadletter
--*************************
to badDialog()
if theTypedWord is "" then
set theTypedWord to "No Text Was Entered!"
end if
set {theTypedWord, button_pressed} to {text returned, button returned} of (display dialog "GassyTypingPractice 1.0" & return & return & wpmstring & return & "OOPS!---> " & theTypedWord & return & return & chosenWord default answer "" buttons {"Cancel", "PAUSE", "NEXT"} default button "NEXT" with icon 2)
if button_pressed is "PAUSE" then
showscore()
else if theTypedWord ? chosenWord then
getbadletter()
end if
goodAnswer()
end badDialog
--*************************
to showscore()
if mistakeList ? "" then
set mistakeliststring to "Some letters you need to practice:
" & mistakeList
end if
beep 3
if wpm = 0 then
set wpmstring to "You didn't type anything!"
end if
set the_result to button returned of (display dialog "GassyTypingPractice 1.0" & return & return & ¬
"You're typing " & wpmstring & " words per minute." & return & ¬
mistakeliststring & return buttons {"Cancel", "Start Over", "Continue"} default button 3 with icon 1)
if the_result is "Continue" then
PreSet()
else
reset()
end if
end showscore
--*************************
to showscoreEnd()
beep 3
display dialog "GassyTypingPractice 1.0" & return & return & ¬
"You typed " & wpmstring & " words per minute." & return & ¬
mistakeliststring & return buttons {"Cancel", "Let's do that again!"} default button 2 with icon 0
reset()
end showscoreEnd
I just noticed that my last post doesn’t compile because there are 3 or 4 places where a “Does Not Equal” sign as replaced with a question mark after it was submitted. It should work fine if you put it in manually durring compile.
OK, this one is going to be tricky - but I guess you knew that already, didn’t you?
A stack overflow is a basic memory error - you’ve asked the script to do more than it can keep track of. They typically happen in repeat loops where inside the loop you ask it to do something that calls itself.
It took me a couple of times to reproduce the problem - for some reason I couldn’t get past the “Please vote for president ” word
The problem in this case is the basic script flow. If you walk through the script (and assume you type the word correctly) you’ll find it goes something like this:
run → reset → PreSet → getlevel → giveWord → goodAnswer → PreSet
However, at this point the script has to keep track of your path back to the beginning. The ‘PreSet’ handler your’re in now is not the same PreSet handler at step 2. What’s worse is that, assuming you keep typing correctly, each PreSet will append:
PreSet → getlevel → giveWord → goodAnswer → PreSet
to the stack trace, ad infinitum.
In other words, none of your handlers ever end, they just keep calling other handlers.
To fix it you need to restructure your script such that the handlers return to a master handler, like:
on run
reset()
set done to false
PreSet()
set nextWord to getlevel() -- have 'getlevel' return the next word rather than calling giveWord itself
repeat until done is true
set userResponse to giveWord (nextWord) -- pass the variable into giveWord so it knows what word to use, and pass pack the result
if userResponse = "QUIT" then
set done to true
else if userResponse = "PAUSE" then
showscore()
else if userResponse = "" then
badDialog()
else if userResponse is not equal to nextWord then
getbadletter()
else
goodAnswer() -- do the calcs
PreSet() -- preset
set nextWord to getlevel() -- choose the next word
end if
end repeat
showscoreEnd()
end run
Note that the above code will not directly translate into your current code - you’ll need to move some of the functionality around, but the basic idea is to have a single handler that repeatedly calls the others rather than having each handler call the next one without truly ending itself.
Hope this helps.
Thank you, Thank you, thank you! My original code, while sloppy as he**, was one long Repeat routine, and I didn’t have any problems. but somewhere along the line I decided a bunch of sub-routines would clean- up the script. I never connected the problem with the way I structured my script. From what I gather in your post, I should go back to the one - single repeat routine, while keeping the latest (ie: neater) syntax in place. I’ll give it a try and see what happens. I’m soooo greatful for your help. I feel guilty everytime I post that g-forsaken script on this site.
Thanks Again,
-G
B.T.W… Why do some cripts show-up on this site looking like I’m viewing it through the script editor on my 'puter, while mine show-up looking like I pasted it from a bad text editor? Do I have to chage the font size & color for each individaual Variable, comment, etc,?
They probably used John’s “Convert Script to Markup Code”: