Expression Pattern Language (eXPL)

Function/Query Calls

Calculator lists function calls as a procedural feature. There are two function call forms, one which looks like a traditional function call, and the other an adaption of the query format. This duality is captured in the title. The first form will be refered to as a "function call" and the second as a "query call". Here are examples of both forms:

Function Call:system.random(4)
Query Call:<- school.subjects(english, maths, history) -> (marks_list)

However, the main distinction to be made is not the form of a call, but it's target, which can be an external library, a calculator or a query. A library is identified by name and contains a collection of Java methods. Each method implements a call evaluation interface, which takes terms as parameters and returns an axiom. There are no standard libraries available for eXPL, so a custom one will need to be programmed, if a library is required. A library can be employed in either a function call or query call. On the other hand, a calculator or query cannot be used in a function call.

Function Call

A function call is an expression in the eXPL syntax, so it can used on it's own or placed in another expression in any position. When used on it's own, any value returned by the call is discarded. Placed in an expression, the value of the first term of the axiom returned by the call is inserted in the expression. If a type mismatch occurs and type conversion is not possible, then the program will exit with a type conversion error.

A function call has format:

library.function ( [ arguments ] );

The library function is identified by a 2-part name, the first part consisting of the library and the second part the name of a member call evaluator. The optional arguments are comma-delimited and consist of literals or variables. The variables can be typed and assigned to expressions.

Query Call

A query call is an artifact which can be placed in a term position of a calculator. Unlike a function call, a query call cannot be placed in a template. The target of a query call can be either a query or a calculator. A query call has a distinctive format:

<- [scope.]target ( [ arguments ] ) [ -> (terms) ]

The call target can be the name of a query or calculator and if the target is in a different scope, then the scope must be included using a 2-part name. The optional arguments are the same as for a function call. The optional structure that can be appended on the right side of the target using the -> operator is a template to receive the axiom returned by the target. Any terms placed in this template need to correspond by name and type to those in this axiom, as the aim is to populate the template by unification. Note that the template can place terms in a different order to those of the returned axiom and omit terms that are not relevant. The template can also use expressions to change the values provided by returned terms.

Accessing Call Solution

The template placed on the right hand side of the query call is not assigned a name by the user because it's terms are directly accessible to the calling template. Post unification and evaluation, the solution generated by this template is inserted in a built-in axiom term list. This built-in is named by convention and availble for use by the program. The built-in is given a 2-part name where the first part is the name of the calculator making the call and the remaining part is the target name.

Although it's use is optional, the built-in may have some benefits when used in list declarations. It is permitted to attach a list to the calculator which is assigned to the built-in. This signals intention to access the query solution as a list using a meaningful variable name. As a bonus, the built-in of a query which returns only a list of any type adopts the same type. This will be demonstrated in the examples opposite.

Call Examples

The applications of tutorial 14 demonstrate all of the possible combinations of call form and target performing a query to generate the a report for 3 students, George, Sarah and Amy for subjects English, Maths and History. One additional application shows attachment of lists to access the query call solution.

Query Call to Calculator

StudentScores is the prototype application for all the call examples belonging to tutorial14. This has a target calculator name "subjects" in scope "school":

scope school {
calc subjects
+ list<axiom> marks_list {};
(
integer english,
integer maths,
integer history,
marks_list = axiom
{ subject="English", mark=mark[english] }
{ subject="Maths", mark=mark[maths] }
{ subject="History", mark=mark[history] }
);
}

The scope plays the role of a library in grouping like functions, but is optional. The subjects calculator has just 4 terms, the first three terms are parameters and the last is a dynamic axiom list populated with items that provide the desired solution. A target calculator always places the parameter terms, if any, at the start as they can be paired with the supplied values by name or position.

The query call passes the values for the 3 subjects and collects the list returned by the query:

<- school.subjects(english, maths, history) -> (marks_list)

Although not declared by the caller, the "marks_list" variable can be dereferenced according to its type eg. for the name of the first subject marks_list[0].subject and the grade for this subject marks_list[0].mark.

Function Call to Library

StudentMarks introduces a "school" library which contains a function equivalent in operation to the previous "subjects" calculator. The function call is used in an assignment on the right hand side with the same arguments as were passed in the query call example:

. marks_list = school.subjects(english, maths, history)

Again without being declared as any particular type, the "marks_list" variable can be dereferenced successfully as an axiom list. Note that a dot is placed in front of the variable to prevent it being exported, which is not appropriate in this case.