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

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

Matt Lewis wrote:
> 
> CChris wrote:
> > 
> > Matt Lewis wrote:
> > > 
> > > 
> > > I agree that my solution doesn't really deal with the encapsulation issue.
> > > That's not the point, and I don't believe that your solution really solves
> > > the issues at hand.  The point is to fix the problem of using multiple
> > > libraries and having them conflict with each other.  If two libraries 
> > > export the same symbols, you still have the same problem.
> > > 
> > 
> > If your application includes two libs which export the same identifier, it
> > has
> > to explicitly choose one of them, using the current namespace system.  At
> > least,
> > internal (ie global, but not interface) symbols won't be seen, just
> > interface
> > symbols.
> 
> Yes, but what about those two libraries.  One will have been included in
> the main app after the other.  Did the author use namespaces for everything
> in his library?  The first included library has polluted the namespace.
> How does the second library manage to deconflict the symbols?
> 

There are two ways around it:
1) As explained in my paper, write a wrapper include around say the first
library, and filter the clashing symbol out from there:
-- app.exw
include wrap_lib1.e -- managed inclusion of lib1.e
include lib2.e
-- more code here

-- wrap_lib1.e
-- define a package around the rogue lib
package lib1_filtered = <comma separated list of allowed symbols from lib1>
-- enforce it
with package lib1_filtered
-- now in protected area
include lib1.e
-- very complicated three lines


So, if lib1.e defines symbols that would clash either with identifiers in
app.exw or in lib2.e('s subtree), they will be screened off and neither lib2.e
nor app.exw will see them.

wrap_lib1.e is to be written by the application coder, since the list of
clashing symbols depends on the other third party libs and the app.exw code.

2/ If only a couple symbols cause trouble, which is expected to be the most
frequent case, it is even simpler to do this:
-- app.exw
include lib1.e
restrict clashing_symbol_1 from lib1.e to lib1.e
--...
restrict clashing_symbol_N from lib1.e to lib1.e
include lib2.e
-- more code here

with exactly the same effect. If the symbols come from lib1.e's subtree, then
solution 1/ is in order.

> > > What happens when the library maintainer makes some changes, and the 
> > > packaging directives don't keep up?  
> > > 
> > 
> > The maintainer usually tests his lib, and specially the new functionalities,
> > and something won't work right, which he should fix before shipping.
> >
> > If the directives are in some custom wrapper you wrote, then it is your call
> > to keep the wrapper up to date, since you wrote it. Or to ship an update for
> > your application, so that an user can use the new version of the lib.
> > 
> > If the packaging uses a negative list, ie a list of internal symbols, then
> > adding
> > more exported symbols requires no update at all.
> 
> In a perfect world, this would be done.  And I agree that this isn't, in
> and of itself, a deal breaker.  I am saying that it's creating another
> way to create bugs.  How would the author know that he'd missed something?
> That his library causes problems with some other piece of code that hasn't
> even been written yet?  

He wouldn't. By properly marking internal symbols as such, he'd eliminate their
clashing with anything, so only interface symbols may still cause problems. If
someone uses another library with same interface, then see above.

> 
> The end result is that the users of the library are going to have to do 
> extra work (by effectively editing the code of the library) to use this 
> library, which is exactly what I'm trying to avoid.
> 

Definitely not true.
As the examples above show, the system is designed to _completely eliminate_ any
third party code editing. It also enables one to deal with legacy code (ie
without internal or exported), using export lists in wrapper includes.

> A negative list may reduce the chances of having to go in and edit, but
> it does not solve the problem.  It does, however drive up the complexity 
> of the code.
> 

Not really. SymTab has two more fields, one of them being the initial package
and the other the current package. If a symbol is *exported*, initial package is
-1; if *internal*, it is current_package; if *global*, the relevant package list
is looked up so as to determine whether this is internal or exported. Finally,
keyfind() checks from the current package field if som global is visible.

For example, contrary to your implementation, no change of file structure in the
front end is required in order to include it as a library. Just a wrapper as a
stopgap, or marking all current global symbols as internal if they are not to be
seen outside

> > 
> > > Also, your solution seems to me to be overly complex, and difficult to
> > > maintain.  When we get to encapsulation, I think I'd prefer something
> > > along the lines of an import vs include, where the globals "imported" 
> > > don't go beyond the file that imported them.  This way, if you need to
> > > keep stuff hidden, just import it.  If you want to expose things, either
> > > put it in the main include, or use the standard include directive.
> > > 
> > > It's possible that I just don't understand your proposal sufficiently.
> > > Please submit a modified set of files to demonstrate how you'd modify
> > > v3.1 to handle these files.  The benefit of my proposal is that there is
> > > absolutely no new syntax, and it does it in an intuitively straightforward
> > > manner.
> > > 
> > 
> > Huh? It does work for some obvious cases, but explicitly inluding a parent
> > file,
> > for example, is far from anything I'd call "intuitive or straightforward".
> 
> This really baffles me.  You have a file which uses symbols in another file.
> If that other file is not present, then it won't work.  You're saying that
> it's unintuitive to include that file with the symbols you depend upon?
>

Since the identifier defined in the parent is already in the known symbol space,
it is counter intuitive to add it again, yes. The only advantage I see in your
scheme is the dependency being made explicit. Otherwise, it's more typing for
less functionality, because then all symbols from parent will become viible from
the included file, won't they? If they don't, read "same functionality".
  
> > I'll have to post the files indeed. As I noted earlier, this may take some
> > time
> > because of RL fiercely catching up these days. But this is the way to go.
> > Also,
> > I didn't try adjusting the runtime lookup functions accordingly yet.
> > 
> > > I'm not really interested (in this discussion) to hear about how your 
> > > solution encapsulates symbols.  I'm interested in how we deal with
> > > multiple files that expose duplicate symbols, whether the original 
> > > author wants them to be exposed or just used internally.  Accept that
> > > the symbols are exposed to the program.
> > 
> > We obviously have different approaches.
> 
> Well, if you're honestly trying to solve the namespace/third party conflict
> problem then I'd agree with you, and I'd go farther to say that your
> approach is deeply flawed.
>  

I am trying to solve several related issues around name clashing and scope in
one sweep, rather than applying yet another Band-Aid. So This is why my solution
brings both encapsulation, overloading and name clash prevention in one
consistent "package".

The changes of syntax are:
* 2 new scope modifiers, *internal* and *exported*, which are mutually exclusive
with *global* and make the intent of the symbol known from just reading the code;
* 2 new with/without directive parameter:
+ *with package <pkg>*/*without package* pushes a package layer onto the package
stack;
+ *with previous_package* pops this stack.
* 2 new top level directives:
+ *package <pkg> [[!]=<symbol list>]* defines which globals are
exported/internal
+ *restrict <sym> from <id_def> to <new_scope>* changes the scope of an
identifier.

As explained, people who write multifile libs or apps that use several
(multifile) libs will need or use some of the new syntax. Hardly anyone else is
impacted.

> > > It seems that your method puts a larger burden onto the programmer to
> > > resolve conflicts.  My goal is to take what's already there (all 
> > > those include statements) and to make full use of the information that
> > > they impart.
> > 
> > The only burden is to disambiguate between interface and non interface
> > symbols.
> > It is not a new task for programmer, since the docs he wrote usually do this
> > already.
> 
> You still haven't answered the main issue here.  How does this solve two
> third party library conflicts?  I'll admit that I simply may not understand
> your solution well enough, and maybe your examples will clear this up,
> but you seem to be avoiding the question by saying, effectively, that
> your solution reduces the number of global symbols, so probabilistically,
> the chance of a conflict is reduced.
> 

Of course it does. As the code above shows, it also addressesthe clashes between
interface symbols.

> I agree with you on that point.  But your solution doesn't solve, AFAICT,
> the conflicts themselves.  So I'll use your terminology:
> 
> How would your approach resolve conflicts between two interface symbols
> conflicting in two third party libraries.  The conflict exists because
> the libraries (not just user code) use those interface symbols. 
> Therefore, simply having a program like:
> }}}
<eucode>
> -- myapp.ex
> include libMatt.e
> include libCChris.e
> </eucode>
{{{

> ...causes an error somewhere inside of libCChris.e, because one of its
> interface symbols conflicts with an interface symbol in libMatt.e.
> 
> What would we need to do to make sure that this situation doesn't occur.
> And what tools does the library programmer have to help him?
> 

If two interface symbols collide, I think the examples above show exactly what
to do from the _application writer's_ end.

If a non interface symbol clashes with anything, then:
1/ The application writer can screen it off using the same method;
2/ Later, the library writer may mark interface symbols as *internal*, or define
a package with either an export or exclude list, as s/he sees fit, and release a
better behaved library. The wrapper will still work, but won't be useful then.
This ensures immunity to change in library versions.

> Matt

Well, it looks like my paper is completely not understandable; however, I don't
know what to do about it, because I had tried to make it as precise and detailed
as I could figure out. Need some hints there.

CChris

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

Search



Quick Links

User menu

Not signed in.

Misc Menu