Finished section on namespace processing.
1 parent 5e8043d commit c6e9b9bf04f79e31b79986cfe9fb46b88490c753
@tundra tundra authored on 13 Apr 2004
Showing 1 changed file
View
255
tconfpy.3
.IP \(bu 4
Variable names may not contain whitespace.
 
.IP \(bu 4
Variable names may not begin with \'$\'. The one exception
Variable names may not begin with the \'$\' character. The one exception
to this is when you are referencing the value of an environment
variable.
variable. References to environment variables begin with \'$\':
 
.nf
# A reference to an environment variable is legal
x = [$TERM]
 
# Attempting to create a new variable starting with \'$\' is illegal
$MYVAR = something
.fi
 
.IP \(bu 4
Variable names cannot have the \'#\' character anywhere in them
because \*(TC sees that character as the beginning a comment.
From that point forward until the namespace is changed again, every
variable assignment
.B and
reference is "relative" to the namespace. What this really means is
that \*(TC sticks the namspace plus a period in front of every
that \*(TC sticks the namspace plus a \'.\' in front of every
variable assigned or referenced. It does this automatically and
invisibly, so \'Brand\' is turned into \'MyCar.Brand\' and so on. You
can actually check this by loading the example above into a test
configuration file and running the \'test-tc\' program on it. You will
create the actual variable name that will be returned in the symbol
table.
 
You're likely scratching your head wondering why on earth this
feature present in \*(TC. There are, in fact, several reasons for it:
 
.IP \(bu 4
 
feature present in \*(TC. There are several good reasons for it:
 
.IP \(bu 4
It reduces typing repetetive information throughout the configuration
file. In turn, this reduces the likelyhood of a typographical or
spelling error.
 
.IP \(bu 4
 
It helps visibly organize the configuration file. A namespace makes
it clear which variables are related to each other somehow. This is no
big deal in small configurations, but \*(TC was written with the idea
of supporting configuration files that might contain thousands or
even tens of thousands of entries.
 
.IP \(bu 4
 
It simplifies the application programmer's job. Say I want to write a
program that extracts all the information about your car from the
configuration file, but I don't know ahead of time how many things you
will describe. All I really have to know is that you are using
and so on, you can do so later
.B and the program does not have to be rewritten.
 
.IP \(bu 4
 
It helps enforce correct configuration files. By default, you can
introduce new namespaces into the configuration file any time you
like. However, as described in the previous section on the
\*(TC API, the application programmer can limit you to a pre-defined
incorrect configuration file entries by limiting just which
namespaces you can enter to reference or create variables.
 
 
.SS Lexical Namespace Specifics
.SS Rules For Using Lexical Namespace
 
Creating and using lexical namespaces is fairly straightforward,
but there are a few restrictions and rules:
 
.IP \(bu 4
 
The default initial namespace is the empty string, "". In this one case,
\*(TC does nothing to variables assigned or referenced. That's
why our early examples of how to assign a value to a variable and
then reference those value in the previous section worked.
When the namespace is "", nothing is done to the variable names.
The namespace, "", is also called the "root namespace."
The default initial namespace is the empty string, "". In this one
case, \*(TC does nothing to variables assigned or referenced. That's
why our early examples in the previous section worked. When we
assigned a value to a variable and then referenced that variable
value, we did so while in the so-called "root" namespace, "". When
the namespace is "", nothing is done to the variable names
 
Bear in mind that the programmer can change this default namespace to
something other than "" before the configuration file is parsed. If
they do this, they would be well advised to let their users know this
fact.
something other than "" before the configuration file is ever
processed. If they do this, they would be well advised to let their
users know this fact.
 
.IP \(bu 4
There two ways to change to a new namespace:
 
.nf
[NewNameSpace] # Must appear on a line by itself or with a comment only
OR
NAMESPACE = NewNamespace
.fi
 
If, at any point, you want to return to the root namespace, you can use
one of these two methods:
 
.nf
[]
OR
NAMESPACE =
.fi
 
So, why are there two ways to do the same thing?
 
 
 
 
 
In other words, \*(TC always prepends the current namespace (plus a
separating period) to any variable assignment or reference it finds in
a configuration. The one exception is when the namespace is "", in
which case \*(TC does not add anything to the variable names.
 
By default, the initial namespace is always "", but you can change this
as desired. Note, however, that the programmer can change this default
initial namespace if they wish. Also there is a programming option
(\'AllowNewNamespaces\', described in the previous section) which can limit
you to using only the namespaces the programmer has pre-defined. i.e., You
will not be able to create
.B new
namespaces of your own invention.
 
You can change to a new namespace anytime within the configuration file
a number of ways:
 
 
So how do you access variables in a namespace different than the one
you are in currently?
 
 
What's the point of all this namespace business anyway?
So, why are there two ways to do the same thing? The first way is the more
common, and the more readable way to do it. It appears on a line by itself and
makes it clear that the namespace is being changed. However, because variable
references cannot be "nested", you can only use strings of text here.
 
Suppose you want to change the namespace in a way that depends on the
value of another variable. For instance:
 
.nf
LOCATION = Timbuktu
NAMESPACE = [LOCATION]-East
.fi
 
In other words, the second form of a namespace change allows you to
employ the \*(TC string substitution and variable referencing
features. Bear in mind that \*(TC is case-sensitive so this
will not work as you expect:
 
.nf
Namespace = something
.fi
 
This just set the value of the variable \'Namespace\' to
\'something\' and has nothing whatsoever to do with lexical
namespaces.
 
This all works, by the way, because \'NAMESPACE\' is
nothing more than (yet) another variable in the symbol table. \*(TC
just understands that variable to be special - it treats it as the
repository of the current lexical namespace.
 
 
.IP \(bu 4
 
Whichever method you use to change it,
.B the new namespace cannot begin with \'$\'.
Both of the following will cause an error:
 
.nf
[$FOO]
OR
x = $FOO
NAMESPACE = [x]
.fi
 
 
.IP \(bu 4
By default, all variable assignments and references are
.B relative to the currently active namespace:
 
.nf
[MyNameSpace]
 
foo = 123 # Creates a variable called \'MyNameSpace.foo\'
x = bar # Means: \'MyNameSpace.x = MyNameSpace.bar\'
.fi
 
.IP \(bu 4
If you want to set or reference a variable in a namespace different
than the current namespace, you must use a so-called "absolute"
variable name. You do this by "escaping" the variable name. To escape the
name, begin it with a \'.\' and then use the
.B full name (including namespace)
of that variable. (This is called the "fully qualified variable
name".) For example:
 
.nf
[NS1] # Switch to the namespace \'NS1\'
foo = 14 # Creates \'NS1.foo\'
 
[NS2] # Switch to the \'NS2\' namespace
foo = [.NS1.foo] # Sets \'NS2.foo = 14\'
.fi
 
There is another clever way to do this without using the escape
character. \*(TC has no understanding whatsoever of what a
lexical namespace actually is. It does nothing more than
"glue" the current namespace to any variable names and references
in your configuration file. Internally, all variables are
named
.B relative to the root namespace.
This means that you can use the fully qualified variable name
without any escape character any time you are in the root
namespace:
 
.nf
[NS1] # Switch to the namespace \'NS1\'
foo = 14 # Creates \'NS1.foo\'
 
[] # Switch to the root namespace
foo = [NS1.foo] # Sets \'foo = 14\' - no escape needed
.fi
 
.IP \(bu 4
\*(TC keeps track of every new namespace you create and returns that
list to the calling program to use as it wishes. (See the section
above entitled,
.B The Initial Symbol Table And Lexical Namespaces
for details.)
 
 
.SS Pre-Defined Variables