Identifiers =========== Identifiers consist of one or more subidentifiers. The simplest case is where there's only one subidentifier, like this: thing An identifier may also consists of several subidentifiers, where first subidentifier specifies the namespace, and the following specify nested namespaces. The last subidentifier is the actual type, function or data definition being referenced. For example: somenamespace:subnamespace:thing Identifiers are case sensitive and may use the English letters A-Z (both upper and lower case), the digits 0-9 and the _ and - symbols. However, an identifier may not start with a digit. A future version of LRL might also allow UTF-8 characters, but currently there's no standard way of encoding these so it will cause errors in the backend. Identifier lookup ----------------- Identifiers are first searched for in the current scope, and then in the scope which that scope is contained in, and so on. For example: int x = 1; int y = 2; int f() { int y = 3; { int y = 4; return x + y; // returns 1+4 = 5 } } An identifier may reference a particular namespace. In this case, the first subidentifier of the namespace will be looked up according to the rules above. Then subidentifiers after it will be searched for in the referenced namespaces. For example: int a = 1; namespace b { int d = 2; namespace e { int f = 3; int x = d; // 2 } } namespace c { int x = a; // 1 int y = b:d; // 2 int z = b:e:f; // 3 } Identifier definitions ---------------------- Usually a definition of an identifier consists of just a single subidentifier. But it is also possible to define an identifier inside a namespace, or define the current namespace's identifier. The following example illustrates this with three type definitions: typedef thing = int; // Usual identifier definition. typedef somenamespace:thing = int; // Define in "somenamespace". typedef here = int; // Define this namespace's identifier // to be a type of int. Note that the namespace "somenamespace" in the second line must be defined somewhere also. **TODO:** Actually require the namespace to be created explicitly, e.g. with "namespace numbers {}" The last "here" definition is useful when defining a type and functions to use it at the same time. For example: namespace Point { typedef here = (int x, int y); Point make_point(int x, int y); int distance(Point a, Point b); } This defines a type called "Point" with two functions in it's namespace. It's allowed for an identifier to be both a namespace and **either** a type, a function or a data definition, like in the example. However, an identifier can only have one definition which is not a namespace.