Please note, this is a work in progress... The documents is being revised from an earlier version of GELLO.
A GELLO program is actually an expression (value) which is evaluated by the GELLO compiler.
The complete program must comply with a set of rules called a grammar, and must also also comply with another set of rules called the semantics. The combination of the grammar and the semantics defines the GELLO language. The grammar is defined formally by what is called a BNF grammar which is provided in the Appendices to this document. Many of the semantics are defined by the data type definitions (eg ISO 21090 data types) and the Virtual Medical Record (vMR) definition. The data types and vMR are defined by the GELLO class definition which has been successfully balloted by HL7 as a Draft Standard for trial use (DSTU) in September 2011.
GELLO programs are comprised of one or more lines of text which are further broken down into tokens and comments. The tokens are the items which have meaning to the compiler, while the comments are readable annotations for documenting the program and are ignored by the compiler.
Medical-Objects GELLO complies with the R2 release of the HL7/Ansi GELLO standard.
While GELLO has its roots in OCL 2.0, there are important distinctions between GELLO and OCL. You can read more about this here
Tokens are the individual words which make up a GELLO program. Tokens can be identifiers, numbers, strings and symbols.
Identifiers are used in GELLO to represent variable names, type names, property names and method names.
Identifiers can be 1 or more characters in length, and must start with "A-Z", "a-z" or "_". Subsequent characters must be "A-Z", "a-z", "0-9", or "_".
In GELLO R2, identifiers are case sensitive, which means that identifiers with the same alphabetic letters but with a different case will be treated by the compiler as different names. There is no limit to the number of characters in an identifier.
Here are some examples of identifiers.
The BNF syntax for a GELLO variable is
Numbers are used in GELLO to represent Integer or Real values.
All numbers must start with a digit ("0-9") followed by digits ("0-9"), optionally a period ("."), more digits ("0-9") and an optional exponent.
An exponent is represented by the letter "E" or "e" followed by a signed integer. It means that the first part (the mantissa) is multiplied by 10 to the power of the exponent. i.e. 1.1e3 means 1.1 times 10 to the power 3 which is 1100
Integer numbers do not have a period or exponent (i.e. it is a string of digits only). In practice there is an upper and lower limit of what can be represented in computable form.
Here are some examples of Integer numbers.
|0||the value Zero|
|1||the value one|
|15||the value fifteen|
|2345||the value two thousand, three hundred and forty five|
|812838482||and so forth....|
Real numbers are distinguished from Integer numbers by having a "." and an exponent. In practice there are limits to the size of the exponent and also the number of digits in the mantissa which can be represented in computable form.
Here are some examples of Real numbers.
|0.0||the value zero as a real number|
|1.0||the value one as a real number|
|1.0e0||the same value as above|
|0.15||the value 15 divided by one hundred (or three twentieths)|
|20.201||twenty plus two hundred and one thousands|
|3.141596254||an approximation of Pi|
|1.0E2||the value one hundred (one times ten to the power of two)|
|4.2E-30||4.2 divided by ten to the power of thirty|
|4.20.0e-32||the same value as above|
The BNF syntax for integer and Real numbers is as follows
Strings are used to represent textual values in GELLO expressions.
They are started with a quotation character (either " or ') and are terminated by the same character. Strings are not allowed to continue over omre than a line, and you can place any character in a string except for the surrounding quotation character.
If you wish to add control character to a string, they can be embedded with the standard XML quoting practice using the form "&ssss;". The following escape symbols are recognised.
|"&nl;"||Add a new line (carriage return + line feed)|
|"""||Add a double quote to the string ( " )|
|"'"||Add a single quote to the sting ( ' )|
Here are some examples of strings.
The syntax of strings is defined as follows.
Symbols are characters or combinations of characters which had special meaning in GELLO. Here is a list of them.
Reserved words are identifiers which are special in GELLO. They cannot be used as identifiers since they have special meaning within the grammar of GELLO. In GELLO R2, reserved words are case-sensitive, however some reserved words may have a capitalized variant.
Here is a list of them.
Comments can be either single-line comments or multi-line comments. Comments are used to annotate the GELLO program without affecting how the program functions.
A single line comment starts with the "--" characters and can appear anywhere on a line, even on lines with GELLO source. All characters from the "--" up until the end of the line are treated as comments.
Some examples of single line comments are...
A multi-line comment starts with the character sequence "/*" and finishes with the character sequence "*/". They can span more than one line or simple be embedded within an existing line.
Here are some examples of multi-line comments.
Values and Types
All expressions in GELLO have a Value and a Type. The Value is the actual representation of the Type. Types can be either Simple Types, Collection Types, Tuple Types or Model Types
Simple types represent the most fundamental pieces of data that a GELLO program can work with.
GELLO has several simple data types available. Integer, Real, String and Boolean
The Integer type represents values which are whole numbers. They can be positive or negative numbers and also include the value zero. MO-GELLO-R2 Integer values are stored as Extended precision real numbers (80 bits) with an exponent of Zero. This means they have at most 64 bits of precision (from -9,223,372,036,854,775,807 up to +9,223,372,036,854,775,807)
The Real type represents values which are numbers which are not necessarily integers. Integers are a subset of Real numbers. MO-GELLO Real values are stored as Double precision real numbers (64 bits).
The String type represents values which are sequences of characters. Strings in MO-GELLO can have any length within the constraints of the available memory in the executing environment, and the characters are taken from the extended ASCII character set.
The Boolean type is used to represent GELLO truth values. Values of this type can only be true, false or unknown.
Enumeration types are a specialization of the String type, however they are only permitted to have values that match the enumeration type. Any string value is permitted as an enumeration value.
For example a variable with enumeration type Colour could be defined as follows.
At the moment, the GELLO specification is incomplete with regard to using enumeration types, however if the underlying data model uses enumeration types, these may be imported by the GELLO program.
A collection is a list of data values, each with the same data type. The data values can be either of a simple type like integer or string, or can be complex data types like collections, tuples or classes. The components or items of a collection are formerly known as collection elements.
There are three kinds of collections, Sets, Bags and Sequences.
A Set is a list of items which are all distinct (i.e. there can be no identical items). They may be in any order, however the ordering is unimportant when comparing two sets.
A Bag is similar to a Set with the exception that more than one item of the same value is allowed, and ordering is unimportant when comparing two bags.
A Sequence is much the same as a bag, except that the order of the items is important.
Here are examples of Sets.
Here are examples of Bags.
Here are examples of Sequences.
Tuple types are similar to Collections in that they represent a group of related data items. However, unlike collections where the collection elements must be all of the same type, in tuples they may be of different types. Each element of a tuple is accessed by its name, and has its own distinct element type.
Here is an example of a let statement with a tuple representing the contact details and of a patient. The tuple definition starts with "tuple(" and ends with ")". Tuple types may be nested within other complex types, and other types can be nested within a tuple type.
The syntax of tuple type definitions is
Class types are similar to tuple types in that that have named elements which are called Attributes. Classes also have Operations which can be performed on the class. In general, the data model supplied to the GELLO program will have a number of classes which represent components of the data model.
Enter topic text here.
Enter topic text here.
Expressions form the foundation of GELLO programs and are made up of operands and operators. Generally an expression is written as a list of operands separated by operators. Operators have precedence, which means the order in which the operators will be applied when evaluating an expression with more than one operator. The precedence of operators may be overridden by the use of "(" and ")" to group sub-expressions.
conceptually in grammatical form
operands can be either literals, variable values, or the results of attributes, operations or queries.
Literal operands are operands which have fixed literal values, such as numbers, strings, or even complex literals like collection or tuple literals.
Integer literals are values which are integer tokens. see Numbers
Real literals are values which are real tokens. see Numbers
String literals are values which are string tokens. see Strings
Boolean literals are values which are boolean tokens. see Boolean Type
the syntax of Collection Literals is as follows
the syntax of Tuple Literals is as follows
A variable operand is represented by a variable name, and can be modified by any number of attributes or operations.
for example, in the program
there are variables a and b.
Whenever a variable is referred to, it is replaced in the expression by its value (in this example a has the value 1 and b has the value 26.
In this example,
there are several variable values.
observations code sodiums
Class Attribute Values
A class attribute value is specified by following an expression operand by a "." and an identifier representing the attribute name. The resulting operand can be used as operand. An attribute means the same as the property of a class in other object oriented languages.
for example, if a variable named obs of type Observation has the attributes name and age, these attributes can be written as
The operator "." may be repeatedly applied to the operand.
for example, one can write
to represent the surname attribute of the name attribute of the Observation obs
The syntax of a Class Attribute is
Class Operation Values
Class Operation values are similar to attributes, but instead return the result of an operation applied to a variable operand. An operation means the same as a method of a class in other object oriented languages.
for example, if there is a variable patient of class Patient, and it has an operation
to count the number of prescriptions in the last N years, one could get the number of prescriptions in the last year by writing...
the syntax of a Class Operation is
Expression Operators represent an operation which can be performed on one or two values or Operands of an expression. An operation on a single operand is called a Unary Operator and an operation on two operands is called a Binary Operator. Generally the form is either
The following operators work on Reals and Integer types.
The following operators work on Integer types only
The following operators work on Boolean types. In GELLO, the Boolean operators also work for unknown values.
Here is a table outlining the results of each Boolean operator
|A||B||A and B||A or B||A xor B||Not A|
There are several class operators available.
value.isUndefined() returns true if the value is null or undefined.
value.isDefined() returns true if the value is not null or undefined.
value.isTypeof(name) returns true if the class of value is name.
A collection operator is an operator that operates on collection classes only. To understand how collection operators are used, see Using Collections.
It takes the form <collection> "->" <collection operator> "(" <parameters> ")"
Here is an example using a collection operator.
let sodiums = observations -> select(code.name = "Sodium")
This means select from the collection observations only observations which have the attribute code with a name of "Sodium".
Some collection operators may take one or more conditions as parameters, while others may take a number, and some no parameters at all.
There are many predefined collection operators in GELLO. Here is a list of them with some examples of usage.
A Conditional Expression is an expression which is determined by a boolean value. If the expression between If and Then evaluates to true, the resulting expression is that between the Then and Else symbols, otherwise it is the expression between the Else and Endif symbols.. An important aspect of Conditional Expressions is that the two expressions alternatives are actually Expression Blocks which means one can have additional Let statements inside the Conditional Expression. It is important to remember that any variables defined in an expression block are only local to that block.
The syntax is as follows.
A GELLO program typically consists of a number of statements one after the other. Usually a GELLO program contains a number of Let statements followed by a final Expression. It is completely valid to have a final Expression without any Let statements. The combination of statements and final expression is called an Expression Block. Expression Blocks can also appear inside Conditional Expressions.
There are several kinds of statements, Let Statements, Context Statements and Final Expression.
Statements are joined together into statement lists. Since GELLO is a declarative language, the order of statements should not affect the end result, however variables must be defined before they are used so any let statements defining them will need to be placed earlier in the statement lists before those variable are used.
The syntax of the statement section of a GELLO program is as follows
The Let Statement allows a GELLO expression to be assigned to a variable name. It is a very useful concept in that it allows GELLO expressions to be broken down into meaningful pieces, and also allows frequently used values to be reused within the GELLO program. A Let Statement can also be referred to as a Variable Declaration.
GELLO variables differ to those in typical computer languages in that they may only be assigned a value once which means that GELLO variables are effectively constant for their lifetime. The reason for this is that GELLO is derived from OCL which belongs to the family of functional languages.
If you are a programmer of commonly used programming languages like C or Pascal, it requires some rethinking to grasp the ways in which GELLO expressions are written. However, with a little practice complex GELLO programs can be effectively structured through the use of GELLO variables.
Some examples of Let Statements are...
In GELLO-R2, the reserved word "Let" is case-sensitive. Also, in MO-GELLO, the type of the variable is optional and may be omitted. The type of the variable can be inferred from the expression which is used to create it. If the type is specified, the assigned expression must be compatible with that type.
The syntax of Let statements is as follows.
The Final Expression must be the last statement in a GELLO program. It is the result of executing the GELLO program. In MO-GELLO, this is currently optional, and when omitted, the GELLO program returns the null (or undefined) expression value.
In the following GELLO program
the final expression is the last line
a + b
In typical use, most GELLO programs will contain a Final Expression.
The syntax is
The Context Statement is mainly used when GELLO is run as an query language within an existing class context. The <ClassName> parameter identifies the class context of the instance data for which GELLO query is being applied in an embedded GELLO environment. You can optionally assign a identifier to the class instance. If one is not given, the default name "self" is assigned.
For example, a messaging infrastructure might wish to execute a GELLO query on a message representing an instance from the data model. The instance root class should be the one specified in the Context statement (e.g. the SinglePatient class from the VMR model). Any Let statements or Final Expressions following the Context Statement can reference all the published attributes and operations of the underlying context class directly.
The syntax of a Context Statement is as follows.
The Data Model
All GELLO program will have a predefined environment which is available to it. This environment will contain a list of predefined classes which can be used. When using the GELLO Interactive Debugging Environment (IDE) you can use the Class Explorer tab to explore the classes available with their properties and methods (attributes and operations).
Here is a list of some of the classes available....
NOTE - this only refers to the MO VMR model in MO-GELLO (GELLO R1)
There are also a number of predefined variables defined. (Only available in older MO-GELLO R1)
One of the most powerful features of GELLO is its ability to work with collections. Typically a data model has many different collections which can be queried with the collection operators.
It is important to remember that when a collection operator is used, the attributes of the element type of the collection become available automatically as variables inside the query. This can be seen with one of our demonstration examples.
The collection observations from the supplied model has as its elements, values of class Observation. One of the attributes of an observation is code which of class CodedValue. Inside the select query, this attribute is made available in the same way as a variable and can be referred to directly. In this example, we compare the value of each element's attribute code and if its name matches the string "Sodium", that element is selected and placed into the new collection. The same principle applies to several collection operators.
Some of the frequently used ones are...
You can create a subset of a collection by using the select operator
collection -> select(boolean-expression)
This will create a new collection of the same type as collection, but only containing elements of the original collection which match the boolean expression or condition. In our example, the following is the collection operation select.
You can create a new collection based on elements of the collection by using the collect operator.
collection -> collect(sub-expression)
This will create a new collection based on the original collection, but each new element will only be the value as determined by sub-expression. A short hand for a collect operation when sub-expression is a single attribute of the element type of the expression is
In our example, the following expressions are identical
Using Physical Quantities
GELLO systems will use Health data types (Such as ISO21090 data types) in the Virtual Medical Record and generally the data types will include a special type of value called Physical Quantity (sometimes using the short name PQ). These are similar to the numeric Real type in that one can perform arithmetic on them (+, -, *, / and so forth), however they have the added property that each Physical Quantity has a units attached to it. This units property is fully managed by the GELLO framework when performing arithmetic on Physical Quantities. Many predefined units are included as standard, including most SI units. In the vEMR data model supplied by the Medical-Objects framework, Physical Quantities are used wherever possible in observations, medications and so forth.
It is important to remember the following rules when calculating with physical quantities. Units are compatible if their unit exponents are the same. For example, units of length (metres, feet, inches etc) are all compatible. As long as there is a conversion from one unit to another, units are also compatible. All units are formed from base SI units (e.g. metres, seconds, kilograms, etc)
If A and B are physical quantities:
Addition and Subtraction
Units of A and B must be compatible. If the units of A and B not identical, a units conversion operation will be made before the calculation. If they are not compatible, a GELLO exception (run time error) will be produced.
The unit indices of B are added to those of A. For example if A is in metres (m) and B is in square metres (m^2) then the result will be in cubic metres(m^3). If there are any conversion factors from the base units they will be multiplied together. The units do not need to be compatible - however this means that the result of the multiplication will need to be meaningful to what you are planning to do. If the units of A and B are not compatible, a derived unit will be formed with the combination of both units.
The unit indices of B are subtracted from those of A. For example if A is in cubic metres (m^3) and B is in metres (m) then the result will be in square metres(m^2). If there are any conversion factors from the base units they will be conversion(A) / conversion(B).
Example of PQ use
An example of using physical quantities would be Body Mass Index. BMI = W / H^2
The results are...
GELLO R2 EBNF
The following notational conventions are used throughout GELLO BNF syntax:
The root symbol of the syntax is GELLOExpression
Non-terminal symbols are denoted by plain identifiers, e.g. expression
Left-hand side terms in production rules are nonterminal
Tokens are represented with text strings enclosed in angle brackets, e.g. <atom>.
Reserved words are represented by text strings enclosed in double quotes.
The grammar below uses the following conventions:
(x)? denotes zero or one occurrences of x.
(x)* denotes zero or more occurrences of x.
(x)+ denotes one or more occurrences of x.
x | y means one of either x or y.
- No labels