Expression Pattern Language (eXPL)

Names and Namespaces

When developing a program, having to come up with a unique name every time one is required becomes impractical. Hence namespaces are provided as a necessary convenience. Namespaces also help to introduce categories so there is a simple way to refer to related things in the design domain, for example "personal.contacts" and "business.contacts" for two distinct types of contacts.

eXPL has a simple 2-level namespace scheme which as a consequence means names have never more than 3 parts, each part being an identifier.

Identifers

Identifiers in eXPL follow the Java naming syntax: identifiers begin with an alpha character which is followed by any number of alpha or numeric characters or "_" underscore. You see in all the eXPL examples a naming convention different from Java's camelCase. The convention is intended to make eXPL look different from Java and uses all lower-case names, with underscore character used to separate words eg. surface_area_increase.

Identifiers are assembled to form names that include the namespace coordinates of artifacts. A ". dot character is used to separate these identifiers. In most cases, just two identifiers are combined to form what is referred to as a "2-part name" eg. europe.megacities. For some artifacts, the namespace scheme requires a 3-part name to fully qualify an artifact's location.

Namespace Scheme

The eXPL namespace can be segmented into scopes, with every template in a scope creating it's own namespace. So for example, two templates can have the same name as long as they are in different scopes and two variables can have the same name as long as they are in different templates. There is also a global namespace in which artifacts can be placed that are intended to be visible from all other namespaces.

Scope

The highest level in the namespace scheme is called a "scope". A scope is named using an identifier and this forms the first part of an name when addressing an external scope. For example, a template named "megacities" in a scope named "europe" is referenced in a query belonging to a different scope as "europe.megacities".

There is a global scope created at the start of a program and all artifacts not included in a declared scope are automatically located in the global scope. You will find that the global scope is used almost exclusively in this reference. The section on Scopes is obviously an exception. Application EuropeanScopeMegaCities of tutorial2 gives a quick look at creating a scope named "europe" to illustrate using 2-part name europe.megacities in a global scope query. Here is how the europe scope is declared along with the query that references it:

scope europe
{
template megacities (Megacity, Country, Continent { "Europe" } );
}
query<axiom> euro_megacities (mega_city : europe.megacities);

Note that the program declares a second scope named "asia" which has a "megacities" template identical in name to the european template.

Template

Each template forms a separate namespace within it's enclosing scope. The namespace takes it's name from the template name which must be an identifer. A template is referenced using a 2-part name, the first part being the scope eg. europe.megacities. If the scope is the global scope, then the first part can be left out. Hence in most tutorials You will see templates referenced using only a single identifier.

Templates are referenced only in queries, but template terms are often referenced by other templates. Such terms are fully located using a 3-part name consisting of identifiers in a scope.template.term sequence. Again, the scope part can be dropped when the template is in the global scope. The only place where you will see 3-part names is in the section on scopes. Note that external template term values are taken from the query solution and despite appearances, terms that reference other namespaces are still just local terms. In other words, you cannot change the value of a term in one template by referring to it from another.

Location Defaults

Identifiers normally have location defaults applied to avoid the inconvenience of having to use fully qualified names everywhere. For example, if a template term has a variable named "x", then the program infers scope and template parts of x's full name from the context. The convention of dropping global scope from a name to reference an artifact does introduce ambiguity to single and 2-part names. The compiler deals with this ambiguity by assuming the local defaults apply, but if the referred artifact is not found, then it searches the global scope. Using artifact names provides a way of naming things unambiguously without resorting to 3-part names.

Artifact Names

Artifact names take the form of an internet address, using "@" as a separator to locate the scope part and placing the name in front of the scope. Artifact names are provided to allow references that are potentially shorter and more readable than their multi-part alternatives. They also prevent the ambiguities that single and 2-part names introduce. Note that global scope is implied if scope is omitted. Here are some examples:

  • megacities@europe for europe.megacities
  • dogs.dogs_only@ for global.dogs_only.dogs
  • matrix@ for artifact named "matrix" in global scope

Queries

A query is the launching point for eXPL execution and defines a goal to be achieved. A query has an identifier name, and if declared in a scope, must be referenced using a 2-part name. Queries is the next topic to be covered in detail.