Rob Mayoff gives an excellent description of what is going on.
The script you posted contains a child script, named Empty, and a handler, the “implicit run handler”. The implicit run handler contains one statement:
run Empty
A child script inherits the handlers of its parent. So your Empty inherits the implicit run handler of its parent. And that inherited implicit run handler calls the run handler of Empty, so it calls itself recursively.
It gives an AppleScript error as long as Script object and parenting chains exists in AppleScript. It’s quite normal because root/top level (main) script objects do need an run handler. So if not one exists it will add one and wrap plain code into an handler. So basically the following scripts are identical because plain code is wrapped into a run handler by yourself.
beep 1
is the same as
on run
beep 1
end run
this means that your script is also the same as:
script Empty
end script
on run
run Empty
end run
Now script Empty doesn’t need a run handler because it’s an child object of the main script. To prove this we can block the parenting chain by setting the parent of script Empty to itself. This way we block that child script objects will call an handler from it’s parent:
script Empty
property parent : me
end script
run Empty -- ERROR: Something about missing handler or message (I don't have an English machine)
As you will see an error occurred telling you that the run handler doesn’t exists in script Empty. For child objects there are no implicit run handlers created. That means in the original script that the run is called in script Empty and will be missing. Then something happens that AppleScript suppose to do, it will follow the parenting chain when a handler is missing to look if the missing handler exists in it’s parent script object before throwing an error. Because script Empty’s parent “ the main script “ does contain a run handler (that automatically is created; implicit run handler) it will be called and run the run Empty line again, and again, and again… until it reach it’s maximum depth of recursive calls.
So your initial script will actually be the same as this one liner:
run me
The best way for this situation to avoid inheritance is overwriting the class/instance method. Which is in this case the run handler. This way you avoid that the script will follow the parenting chain but contains the handler you want to call with the run command.
script Empty
on run
end run
end script
on run
run Empty
end run