Data References
In general,
Enki language expressions are stored either at a
dispel
or at a data item. From an expression, all the data published to the dispel or accessible from the data
item can be used.
Data external to the expression are accessed by writing the
name
of object in which the desired data item is located, followed by a dot separated
reference
to the data item. For example, if there is a table named
customers
in the document section
Data,
it is accessed from an
Enki expression as follows:
document.data.customers
Some object names are optional. Thus, for instance, instead of writing
this.x
,
it is sufficient to write just
x
.
Whether the object name is optional can be, for instance, decided in a
data
provider definition for the local variables object name.
A variable name defined with the keyword
var
can serve as an object name, too.
Sequence Element Identification
As has been described, a data reference consists of the names of structure components separated by dots.
If an array or sequence element is to be identified, an index instead of a name is used (the index of
the first element is 0). Equivalently, the index can be enclosed in square brackets, as is common in
many other programming languages.
For instance:
document.data.customers.0.name
refers to the same data item (the name component of the first row of the customers
table stored in the document section Data) as:
document.data.customers[0].name
The Concept of L-Value
A reference identifies a data item, the value of which can not only be used in a computation, but it
can be changed, as well. In this respect, references differ from constants and function results, which
are mere values. A reference, on contrary, identifies an object (a variable or a data item), to which
a value can be stored. A value that identifies an object (whose value can be changed) is called an l-value
(“l” for “left”, as such a value can be
placed at the left side of an assignment operator). A mere direct value is then called an r-value.
Every l-value can be used at the place of an r-value, as it can
be converted to an r-value by reading the current value stored in the referred object.
Dynamic Determination of Sequence Element
In the example above, a reference to a sequence element was created. However, it is often needed to refer
to a sequence element, the index of which is a result of a computation. Let us suppose, that i
is an integer variable. If the i-th sequence element is to be referred, the variable
(or even a whole expression) is written enclosed in the square brackets:
document.data.customers[i].name
However, an equivalent expression written using the dot-notation document.data.customers.i.name
would not work, because it would be interpreted as referencing a component with the name i
,
which is, however, not present in the table customers
.
In order to distinguish a direct name from a variable name or an expression, it is necessary to enclose
the computed index in parentheses:
document.data.customers.(i).name
Dynamic Determination of Arbitrary Part of Reference
The concept of dynamic index determination described above can be generalized to dynamic computation
of any part of reference. To help this task, two data type are defined:
Atom
A single name, from which a reference is built up. A value of this data type can be created by the
typecast
operator from a string. For instance:
[Atom]"name"
.
Dref
A value representing a part of or a whole reference; i.e. one or more atoms and/or indexes. A value of
this data type can be created by the
typecast
operator from a string. For instance:
[Dref]"customers.0.name"
.
Conversely, the values of the both types can be converted to String
.
With the dot operator, any value of the types Atom
or Dref
can be chained with another
reference. For instance:
var
Atom column = [Atom]"name";
document.data.customers.0.(column)
Again, it is necessary to enclose the computed part in parentheses to distinguish it from a direct component
name.
Similarly for Dref
:
var
Dref item = [Dref]"customers.0";
document.data.(item).name
L-Value and Reference Alteration
If a Dref
value contains a whole reference,
the corresponding l-value can be obtained with the asterisk (*
)
operator:
var
Dref item = [Dref]"document.data.customers.0.name";
*item = "Joseph Smith";
Conversely, the Dref
value corresponding
to an l-value can be obtained with the ampersand (&
)
operator:
var
Dref item_ref = &document.data.customers.0.name
This can be useful with a parameter passed by reference (see the
function
editor), where the acquired valued of the type
Dref
can be converted to a
String
and further
analyzed.
Data Declaration
In the most cases, it can be inferred from the function location, which external data are accessible
from the functions. However, in some cases (e.g. in a
tool
definition), this does not necessarily hold. Then, it may be needed to declare what data are expected
to be present during the run-time and what their type is. The
declare
statement serves this purpose:
declare Type name
If the exact type is not known, it suffices to declare it as a Union
,
which is a union of all types (i.e. any type).