Expression Pattern Language (eXPL)

Scopes

A scope in eXPL is a context that encapsulates a namespace, a locale and a properties environment. There is a global scope created at the start of a program and it is this scope which has been employed exclusively up till nou. The global scope has the following characteristics:

  • Name - All scopes have a unique name which as a rule must used when refering to an artifact from outside the scope in which it resides. The global scope is an exception to that rule. It's name is "global", and when scope is omitted from an artifact's name, it is assumed to be this name. .
  • Locale -The locale for any scope, including the global scope, defaults to the system default. However, the locale can be configured to any of ones supported by the Java runtime and this will be applied when working with number and currency formats.
  • Properties - A scope can be assigned any number of key-value pairs, plus 2 properties are reserved to set the locale - "language" and "region". If you run the ShowLocale application of tutorial12, you will see what these properties are set to in the global scope of your system. In Australia, you will see: locale_query(language=en, region=AU).

To prove the global scope exists, change the ShowLocale query from:

query<term> locale_query(locale);

to

query<term> locale_query(global.locale);

and run the application. The query should run to completion as normal. Change "global" to something else, and you will get a "scope not found" error.

Scope Format

A scope declaration has a name, statements enclosed in braces {} and optional properties:

scope name [ ( properties ) ]
{
  eXPL-statements
}

The properties are specified as a comma-delimited list of name-value pairs eg. (language="de", region="DE") specifies the Germany locale. A "variant" or "script" property can be added if required. The properties are accessed using a built-in axiom term list named "scope".

A scope may not have any enclosed statements, in which case, it just declares a context for artifacts in the global scope to use. Note that, apart from the global scope, a scope may not be nested inside another scope.

Applying Scope to Global Artifacts

A scope is assigned to a global artifact by referring to it using a 2-part name, the first part being the name of the desired scope. A scope can also be applied to a query at the time it is executed, which has the effect of applying that scope to all global artifacts.

The global scope is not normally declared, but this can be done to override the preset properties or add new ones.

Application CalculateSquareMiles3 of tutorial12 demonstrates declaring the global scope to change the "location" property to an actual name of a country. There is a second scope named "australia" which also sets the "location" property. The application displays the surface areas of both Australia and the USA and the units used, square kilometers or square miles depends on the location property. Note how the calculator named "country_area" is referred to as "australia.country_area" in the Australian query.

Context Term Lists

A context term list is a member of a collection of lists with the same name but residing in different scopes. A reference to a context list is interpreted as an access to the list belonging to the current scope. To reference a context list, use an identifier in the artifact format with the address part the reserved word "scope", eg. for a list named "lexicon", use identifier "lexicon@scope". The only list type supported is the axiom list. If the list contains only one item, then it's content can be accessed using an axiom term list. As you will see in the examples, this is the most likely usage of context lists - the selection of terms which are specific to a particular context.

For a context list declaration to be valid, there must exist in at least one scope, an axiom collection to which it refers. It is good practice to declare an axiom collection in the global scope, as this will be used as the default at the start of the program. Without such a default, then the context list is initialized only upon the first change to a scope with a referenced axiom collection.

Word Translation Example

Application ForeignScope of tutorial12 has a German scope configured with a query to print out a Euro amount + 10% tax along with the word "Total" in German. The translation of the word "Total" is done using a context list named "lexican@scope". This list contains a single axiom with a term to translate "Total" to "Gesamtkosten":

axiom german.lexicon
( Total)
{"Gesamtkosten"};

Note how this list is declared in the global scope with a 2-part name. The global scope is the custodian of all context lists.

This is the calculator which formats the text to output:

calc format_total
+ list<term> lexicon@scope;
(
string total_text =
lexicon->Total +
" + gst: " +
total.amount.format
);

The context list is attached to the calculator as an axiom term list, allowing direct access to the Total term.

The solution to the query is:

total_text = Gesamtkosten + gst: 13.580,24 EUR

To show that the context list is working as expected, a second French scope has been included. This time, the scope is empty and 2-part names are used in the "french_item_query" declared in the global scope. Run application ForeignScope2 and you should see the context list should now select "le total" for "Total". Also note the subtle difference between the German and French Euro thousands separator ("." vs. " ").

Axiom Choice

To allow selection based on context-sensitive values, axiom choice can have a context list attached. Application ForeignColors of tutorial12 provides a demonstration using an axiom choice to select a color by both it's German and French names:

choice swatch
+ list<term> lexicon@scope;
( name, red, green, blue)
{lexicon->aqua, 0, 255, 255}
{lexicon->black, 0, 0, 0}
{lexicon->blue, 0 , 0, 255}
{lexicon->white, 255, 255, 255};