Re: 2 Pass Binder
- Posted by Roderick Jackson <rjackson at CSIWEB.COM> Aug 18, 1999
- 431 views
JJProg at CYBERBURY.NET wrote: >EU>Now I doubt *I'd* write a program like this, but if it's >EU>syntactically and logically valid, why would it be wrong for someone >EU>else to do so? That's when the problems begin. The only way to get >EU>around this seems to be somehow limiting the programmer's ability to >EU>write such code--probably by eliminating the ability to pass variables >EU>to routine_id. > >Not nessicarily. If the binder couldn't be sure that a particular >routine wasn't used, it would just have to include it anyway. It would >still be able to get rid of routines that it was sure wasn't used. Also, >a really smart interpreter could see where the variable is modified that >stores the names of the routines, and try to figure out what is used >from there. But that's my point... you might be able to do that for simple code, but sooner or later it breaks down. You wouldn't even be able to tell which routines were definitely not used. Why? Because, in order to arrive at a literal for every instance of routine_id that is given a variable, you almost have to execute the program while still binding--and you'd have to try to do it backwards!... Whenever a binder following this method would encounter the code "routine_id (var)", it would have no immediate knowledge of what "var" was. Sure, the line prior to it might read "var = 'MyFunc'", a case you could hardwire to be handled easily. But what if "var" was passed in as a parameter to the enclosing routine? (or had some other messy source, but let's stick with this one for now.) Not likely, but possible. So now the binder has to go back and find every call to that routine, and determine all possible values of that parameter. If you or Rob would be up to taking the challenge of writing a binder that could do all that, hey, more power to you, but if I was writing that kind of a binder, and it saw that several of those calls had variables passed as parameters instead of literals, I think I'd just have the thing give up and retain every routine. Or if it found only one call, but the call was something like: Found = 0 for i = 1 to length(s) do if (s[i] = k) then Found = 1 routine_name = construct_routine_name (i) exit end if end for if (Found) then exec_routine (routine_name) -- EEK! end if I think I'd have the binder just keep everything in this case, too. Having it nested in an "if" is one thing; but when the parameter itself is the result of a function call, well, it's probably better to stop right there rather than keep running the program in reverse... <snip> >Actually, I have used dynamic construction of routine names to spcify >the types of arguments. I did this to construct an Euphoria interpreter >for my compiled Euphoria bytecodes (I've been working on a Euphoria >assembly language and a compiler and interpreter for it). Ah yes, you were working on the Euphoria OS, right? Sorry about switching subjects mid-stream, but how is that going? It sounds like a pretty neat idea. <snip> >I agree with you, though, that if the routine name was totally >unpredictable (like using gets(0) to get a routine name), the binder >would not be able to scrap _any_ routines _in the current scope_. For >example: > >include somefile.e >procedure a() > ... >end procedure >procedure b() > ... >end procedure >sequence name >name = gets(0) > >The binder couldn't get rid of a, b, or any global routines defined in >somefile.e. It could get rid of any non-global routines in somefile.e >that aren't referenced by any of the global routines. Hmmm, almost. If the local routine is called by a local routine that's called by a global routine, it still needs to be included. The only way any routine could be left out would be if: 1) it were local 2) no local routines (within the same scope, including itself) used routine_id with a variable passed to it, and 3) there was no direct or indirect calling of the routine from a global routine in the same scope. I wouldn't think a typical, large program that used routine_id would have a lot of routines that would fit those criteria. Any such routines it did have would have to be either a logic error on the part of the programmer, or deliberate (to test workings of the interpreter, etc.) Hmm... perhaps that's what this all boils down to. Should logic errors ever be optimized away? For example, I've often put code like this in a program: for i = 1 to 1000000 do end for even though it doesn't appear to do anything. I've even employed empty procedures and functions a time or two. Is it wise to assume the programmer made a mistake in these cases? If so, wouldn't it be better to alert him to it rather than "throwing it away"? Does such a feature have worth even as a bind option? If the code doesn't belong there, shouldn't the programmer be told about it so that he can remove it (or rewrite it like he originally intended), rather than let the error go unnoticed, for months or even years? Please note, I'm not saying the feature doesn't have worth, etc.; I'm just playing "devil's advocate" here. Rod