Actions

Talk

Namespaces

From Gambit wiki

This page should greatly help anyone trying to understand the Gambit source code, because it lets people know what the # signs mean and gives them enough information to experiment (and to not get stuck).

But it doesn't give enough information (for me, anyway) to build a mental model of how the namespace feature works and how it might be implemented. I want to really understand the source code and possibly write tools to analyze it, or test and possibly improve the reader, printer, and REPL. For those things a good understanding of the namespace feature is essential.

I've been experimenting and talking with the page's author, User:Pflanze, and I understand some of the details better now. New comments in italics and indented.

A better page might be organized along these lines. Unfortunately I still have mostly questions and not many answers. Please comment, then I can continue the organization and writing.

  • Storage and access.
  • The Scheme standards define the ideas of environments, the actual environment(s) that exist(s) before programs run, and the ideas of binding and scoping. So you get a mental model of names and values being stored as programs run, and access rules controlling which names and values programs can see and change.
  • It sounds like Gambit's extensions to this model are very simple. Each name is divided into two parts (namespace and local name) which are both fixed when the name is created. There is a current namespace that sets the namespace part attached to unqualified tokens.
Maybe it's better to say that explicit qualification, and the variants of namespace, work together to create a mapping from each unqualified token to its qualified form, at each point in the source code.
Also, the standard evaluation rules define when each token is used to create a new name/value versus looking up an old one, and the namespace extension doesn't change those rules.
Also, as Pflanze pointed out in IRC, evaluating 'a to a doesn't involve qualification.
  • This part should come first because the extensions are so simple and static, and because I hope all names really are stored fully qualified. That would make the other points easier to think about.
  • Are there any restrictions on what can go into a namespace or local-name part in this low-level view of the world -- characters that are rejected if they are found?
  • It's important to get this part right before writing the others.
  • Reading.
  • This is where things get complicated. The namespace form looks like it affects tokens as they are read, but it also follows scoping rules. So it's not only part of the lexical-analysis phase. How early in the parsing process does it execute? Can you think about any part of the parsing process as working with fully-qualified names, and forget about unqualified names at that point?
  • Obviously some forms like define are designed to work with unevaluated names, which delays the process of evaluating and then qualifying them.
  • What strings can make up namespace and local-name parts at this level? That is, what read syntax is allowed in tokens?
  • What strings can be passed to the namespace form?
  • How do you convert those strings to the namespace parts that are actually stored?
  • The current namespace may affect the creation of new names differently than the lookup of old names. Is it useful to describe those algorithms separately?
I've changed my mind about this. I was looking at how the compiler uses namespace, and I couldn't see all of the uses in effect at certain points, so I thought there might be exceptions to the rules. Actually the rules apply to tokens at reading, and have nothing to do with evaluation (which is what creates or looks up names).
  • The page should emphasize the exceptions to the rules, especially the fact that there's no way to refer to identifiers in the empty-string namespace unless that's the current one. Saying "Just use ##namespace instead of namespace" glosses over the fact that they are diferent identifiers, not two ways of writing the same identifier.
My edits have tried to make these points clearer.
  • Printing.
  • How does the printer convert namespace and local-name parts back to a human-readable form?
It prints the namespace part when it's not empty. The current-namespace settings are not used.
  • What the namespace form does.
  • (The page already explains this pretty well.) I don't get the impression that it imports or exports names at all (copying them from namespace to namespace at runtime). Rather, it simply controls how unqualified identifiers are qualified.

This organization may be too heavy on the theory, but it hopefully defines concepts before they're used in later parts.

Gambit also transforms names as it generates C code, and the Gambit sources use other naming conventions like initial underscores in file names. Those don't belong on this page but should be described on a related page.