Re: symbol resolution (was:EuCOM : Attn Matt : String Return Value)

new topic     » goto parent     » topic index » view thread      » older message » newer message

Pete Lomax wrote:
> 
> Matt Lewis wrote:
> > 
> Yes. An example:
main.e
   global Z
   include libA.e
     global Z
     include libAmisc.e
        if Z then

> Once you take the view that libA works standalone and including it as part of
> a larger app should not change that, then the unqualified reference to Z
> should
> automatically resolve to the one in libA and ignore the one in main.e
> 
> IMO such a rule would help far more often than hinder, and not as if it is
> going
> to break any existing code or anything.

I can see what you're saying, but there's still some ambiguity.  The minimum
that I think I'd go along with is to put in a warning.  Now, if libAmisc.e
put in an include statement for libA.e, then it would be explicit that it
wants to use the symbols from libA.e.  

What if main.e had also included libAmisc.e?


main.e
   global Z
   include libAmisc.e
     if Z then
   include libA.e
     global Z
     include libAmisc.e
        if Z then

Now how would the interpreter handle this?  It has to be an error (assuming
that libAmisc.e never included libA.e).  I think we have to assume that 
this situation will occur, because for main.e to see some of the symbols
of libAmisc.e, it might need to use a namespace identifier to avoid 
having libA.e symbols mask those from libAmisc.e.  So we've got another
case of a library breaking because of the way it was used (similar, but
slightly different from including two libraries with conflicting symbols).

Based on this line of thought, I believe that using a symbol not in one's
include tree should throw a warning, and that this situation (as it does
today) should be an error.

> > I'm not sure on that one.  Alternately, your statement seems to logically
> > follow the other facts, but there's something about it that isn't sitting
> > right.  I'll have to think about it some more, but I suspect that you're
> > correct.
>
> Perhaps the missing part is that "include third.e as third" also allows
> third:n_also_in_third
> to explicitly target the other one of the clashing globals.

I think you're right.
 
> > > Matt Lewis wrote:
> > > > Continuing my train of thought from the response to Pete, I guess a 
> > > > legitimate question to be asked would be whether we should let symbols
> > > > in
> > > > directly included files mask those from lower down in the tree? 
> > > > Assuming,
> > > > of course, that no namespace identifier is used, and there is only one 
> > > > possible symbol.
> > > 
> > > Are you saying that in eric you would check bob&diane (directly included
> > > by
> > > eric) as one level then alice&chris (included indirectly via bob&diane
> > > respectively) as the next, which seems messy? The parent masks grandparent
> > > seems
> > > more useful. One of my guiding principles is: If it works standalone, it
> > > should
> > > work the same when you include it in the middle of an application.
> > 
> > I'm not sure I follow the difference here.  Maybe I'm thinking too much
> > in terms of the way RTLookup is coded (and the symbol table is put 
> > together).  I don't think there's any guarantee that you'll encounter
> > symbols from one file before another, so you have to check all of them
> > before deciding who masks whom (though I might be wrong about this).
> 
> Given that some of the sub-includes may in fact be re-includes, then yes,
> following
> a hash chain may chance upon relevant entries in a completely
> higgledy-piggledy
> fashion. I concede that treating bob&diane as one level and alice&chris
> as one lower need not be any messier, still not seeing why you would actually
> want to do that though. Got a practical example?

I wonder if we're talking past each other?  I'll adopt your example from
above:

app.ex
  include main.e main.e
    global Z
    include libAmisc.e
      if Z then
    include libA.e
      global Z
      include libAmisc.e
         if Z then
  ? Z -- back in app.ex


I was talking about how to resolve Z.  I'd say that an unqualified Z in 
this instance should get you main:Z.  To get libA:Z

app.ex
  include main.e main.e
    global Z
    include libAmisc.e
      if Z then
    include libA.e
      global Z
      include libAmisc.e
         if Z then
  include libA.e as A
  ? A:Z -- back in app.ex


> > I think some of my concern with the masking is that it's a new behavior 
> > for euphoria, and isn't always obvious.  I think that if any globals from
> > other files mask other globals from other files due to a parent/grandparent
> > relationship, there should be at minimum a warning generated.  I think
> > it would be easy to get confused as to which symbol is resolved, and
> > going on our merry way to destruction.
> 
> The obvious thing is to develop a set of test files. You can find the ones I
> used at <a
> href="http://www.palacebuilders.pwp.blueyonder.co.uk/t05.zip">http://www.palacebuilders.pwp.blueyonder.co.uk/t05.zip</a>
> which you may or may not have already seen and may or may not find useful. The
> .exw files are
> the actual tests (14 of), some of which are mind numbingly trivial. 
> 
> Probably also a good ideal to develop a set of "fail" test files which should
> generate the desired errors and warnings.

I agree.  I checked out your test files.  Once I got rid of the 'positivisms'
in them, they all seemed to pass (on the version of euphoria built from
the svn head), except for incV.exw, and I'm not even going to try to 
figure out what you were doing there.  I got lots of illegal escape chars, 
and I suspect that it relies on the directory structure of your machine.

> > > > I'm also starting to think that any symbol resolution from beyond the 
> > > > include tree should generate a warning.
> > >
> > > Is this the same worry I had with "win32lib:length" above?
> > 
> > I don't think so.  Let's say you're developing myapp.exw, and it includes
> > win32lib.  It also includes myapp.ew, which does not include win32lib,
> > but calls win32lib routines.  As long as win32lib was included before
> > myapp.ew, then this will work, but since you're depending on symbols that
> > you've never explicitly included into myapp.ew, I  believe that a warning
> > should be generated.
> 
> I'm not convinced. If you can make myapp:closeWindow() work in this case
> without
> introducing other problems then fair do's, but I still think it should just
> be an error (which goes away if you put "include win32lib.ew" inside
> myapp.ew).

I'm not sure what myapp:closeWindow() refers to.  The behavior described
above will work with current euphoria:
myapp.exw
  include win32lib.ew
  include myapp.ew
    closeWindow(...)

But let's suppose that someone has made a custom structure library, and
it has a routine called allocate().
myapp.exw
  include win32lib.ew  -- somewhere, this includes machine.e 
  include struct.e
    global function allocate(...)
  include myapp.ew
     ptr = allocate(...)

This worked fine until we put struct.e in there.  If we were to warn (before
we add struct.e to the mix) about using allocate() in myapp.ew, when it
doesn't include (directly or indirectly) machine.e, then we can at least
sleep at night knowing that we flagged it, and he should have fixed it
before it became a problem.

This isn't the best example, because all of the stuff happens in the
app dev's code, and it isn't best practices, but I don't think we should
necessarily assume (as developers of the language) that the code written
in the language will follow best practices.  I'm just saying that since we 
*can* detect something that can easily lead to problems, we should give a 
warning about it.

I bet that I'll find a lot of this in various libraries of mine.

Matt

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu