Re: 2 Pass Binder
- Posted by Roderick Jackson <rjackson at CSIWEB.COM> Aug 18, 1999
- 405 views
JJProg at CYBERBURY.NET wrote: >EU> routine_name = commands[choice] > >EU> ? call_func (routine_id (routine_name), {operand}) > >EU>Now, how could I expect the binder to know to leave in the two >EU>functions above? It HAS to leave both in the code, even though it >EU>can't tell if either of them will ever be used. [...] >With this, though, a smart binder could do the following: >1. see that commands is a constant >2. see that the argument to routine_id is an element of commands >3. know to leave in any routines named in commands Well, that's theoretically true, and that sort of behavior would be desireable. But just as another example of how tricky this could get... before sending my email, I looked over the code and realized that, silly me, I had left "commands" as a local variable. Since in my example I knew it wasn't going to change, I made it a constant "for efficiency purposes." The problem is, leaving "commands" as a variable, even modifying it later on (to add other commands once the user clicks on a checkbox, etc.) is an completely valid approach. Now I doubt *I'd* write a program like this, but if it's syntactically and logically valid, why would it be wrong for someone else to do so? That's when the problems begin. The only way to get around this seems to be somehow limiting the programmer's ability to write such code--probably by eliminating the ability to pass variables to routine_id. Sure, you could try to make the binder smarter still, but even if *this* case can be caught, the variations are nearly infinite... you'll eventually reach a point at which the binder can't handle it. Suppose your referenced routines consist of: commandname_parametertype and the name of the function to call is constructed at runtime based on options the user selects? Or, what if you want to test individual routines by directly inputing their names and executing them? "No one does any of that!" PROBABLY true. But it's valid, isn't it? And if it's valid, then it's a situation that has to be handled. The point is, there's no way to correctly evaluate all possible contexes (?) when "routine_id (var)" is encountered. The binder would have to back up through every place where "var" is set, everywhere where a slice of "var" is set, every location where a variable that var is set to gets set. In this miniscule example alone, the binder would have to back up through: routine_id (routine_name) --> routine_name = commands[choice] --> constant commands = {...} --> BINDER: good, "commands" is a constant. Is "choice"? --> choice = get_number (0) --> (assume get_number is built-in, or things get worse...) BINDER: no, "choice" is always undetermined. We need to account for every element of "commands" --> BINDER: adds routine named commands[1] to the table ... BINDER: adds routine named commands[length(commands)] to the table I imagine that for larger programs, or use of expressions (&, etc.), the complexity could increase quite rapidly. Even then, you're still making some assumptions that may not be valid. And again, heaven forbid that after backing through all assignments you wind up not having enough data to construct all potential literals. It seems clear that you'd be better off just leaving all routines in rather than taking this approach. You'll either wind up limiting routine_id, or only being able to do this on programs that have no calls to routine_id, or leaving open the possibility of writing programs that occasionally give "invalid routine name" errors at runtime. Rod