Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "EDT:Language Overview02"

(Killed spam)
 
(38 intermediate revisions by 4 users not shown)
Line 15: Line 15:
  
 
A '''field declaration''' is a coded statement that declares a value in a memory area. If the value is based on a reference type, the memory area typically holds an address that points to the value. If the value is based on a value type, the memory area contains the value itself.  
 
A '''field declaration''' is a coded statement that declares a value in a memory area. If the value is based on a reference type, the memory area typically holds an address that points to the value. If the value is based on a value type, the memory area contains the value itself.  
 +
 +
The difference between reference and value types has practical effect when you are assigning a value from one memory area to another. [ details to follow ]
 +
 +
== Variables and constants  ==
  
 
A named field declaration includes an identifier that names the memory area for subsequent use. If the embedding code is allowed to update the area, the identifier is a '''variable'''. If the update is disallowed, the identifier is a '''constant'''.   
 
A named field declaration includes an identifier that names the memory area for subsequent use. If the embedding code is allowed to update the area, the identifier is a '''variable'''. If the update is disallowed, the identifier is a '''constant'''.   
Line 34: Line 38:
 
The type in this case is INT List or INT[], which is a reference type. The first statement declares a '''reference variable''', which means that you can assign a different list to <code>NumberOfVehicles</code> later. Incidentally, you can also change the values inside the list and can change the number of elements.  
 
The type in this case is INT List or INT[], which is a reference type. The first statement declares a '''reference variable''', which means that you can assign a different list to <code>NumberOfVehicles</code> later. Incidentally, you can also change the values inside the list and can change the number of elements.  
  
The second statement declares a '''reference constant''', which means that you cannot assign a different list to <code>MINIMUMNUMBERS</code>. However, even in this case, you can alter the values inside the list and can change the number of elements.  
+
The second statement declares a '''reference constant''', which means that you cannot assign a different value to <code>MINIMUMNUMBERS</code>. However, even in this case, you can alter the values inside the list and can change the number of elements.  
  
The behavior is consistent because each declaration in the second example identifies a memory area that contains an address of a second memory area. The constant is only constant in the sense that the area identified as <code>MINIMUMNUMBERS</code> must always contain the same address, which refers to the same list. The following, subsequent assignment is not valid even though the values are the same:<br>
+
The behavior is consistent because each declaration is referring to a list, not to an element in a list. The constant is only constant in the sense that the area identified as <code>MINIMUMNUMBERS</code> must always contain the same address, which refers to the same list. The following, subsequent assignment is not valid even though the values are the same:<br>
 
<pre>  // An invalid assignment
 
<pre>  // An invalid assignment
 
   MINIMUMNUMBERS = [1,2,3,4,5]; </pre>
 
   MINIMUMNUMBERS = [1,2,3,4,5]; </pre>
Line 43: Line 47:
 
In some cases, a reference type is&nbsp;'''nullable''', which means that a&nbsp;variable of that type might refer to an object or might not.&nbsp;  
 
In some cases, a reference type is&nbsp;'''nullable''', which means that a&nbsp;variable of that type might refer to an object or might not.&nbsp;  
  
A variable that is declared to be of a&nbsp;nullable type is called a '''nullable variable'''.&nbsp;If such a variable&nbsp;does not refer to an object, the following statements apply:
+
A variable that is declared to be of a&nbsp;nullable type is called a '''nullable variable'''.&nbsp;If such a variable&nbsp;does not refer to an object, the&nbsp;variable is said to be null, with no value at all.  
 
+
*The variable is said to be null, with no value at all.
+
*The memory area&nbsp;named by the variable is holding a&nbsp;value that is characteristic of a null; typically, binary zeros.
+
  
 
To indicate that a&nbsp;type is nullable, add a question mark to the end of the type name.&nbsp;For example, here is another List declaration:  
 
To indicate that a&nbsp;type is nullable, add a question mark to the end of the type name.&nbsp;For example, here is another List declaration:  
Line 53: Line 54:
 
<pre>  myList = [1,2,3,4,5];  
 
<pre>  myList = [1,2,3,4,5];  
 
   myList = null;</pre>
 
   myList = null;</pre>
In EGL, you can make any variable nullable. For example, Int is a value type, but after&nbsp;the following code runs, <code>myInt</code> is null:&nbsp;  
+
In EGL, you can make any variable nullable, even a value variable. For example, Int is a value type, but after&nbsp;the following code runs, <code>myInt</code> is null:&nbsp;  
 
<pre>myInt Int?;&nbsp;&nbsp;</pre>
 
<pre>myInt Int?;&nbsp;&nbsp;</pre>
If you append a question mark to the name of a value type, you are identifying a reference type. The Int and Int? types are different; and after the following code runs, <code>myInt</code> refers to an object that contains an integer:
+
The variable continues to&nbsp;behave as a value variable&nbsp;when used in a statement&nbsp;that assigns a value.&nbsp;  
<pre>myInt = 4;</pre>
+
<br>
+
  
 
== Instantiability  ==
 
== Instantiability  ==
Line 81: Line 80:
 
<pre>myDictionary Dictionary? = new Dictionary
 
<pre>myDictionary Dictionary? = new Dictionary
 
                               { lastName = "Twain",
 
                               { lastName = "Twain",
                                 firstName = "Mark" };
+
                                 firstName = "Mark" };</pre>
 +
You can instantiate any EGL value type, although doing so&nbsp;merely places the default value for the type into the memory area.&nbsp; For example, the following code assigns 0 to <code>myInt</code>: <br>
 +
<pre>&nbsp;myInt Int = new Int{};</pre>
 +
The value variable continues to be a value variable.
  
 +
Last, several EGL reference types are not instantiable:&nbsp;
  
</pre>
+
*In some cases, a&nbsp;variable of a non-instantiable&nbsp;type&nbsp;receives an object from the EGL runtime code, but only when the variable is used in a particular way.&nbsp;Such cases apply in SQL processing and in service access; and in those cases, the variable&nbsp;must be nullable.&nbsp;&nbsp;
Last, several EGL reference types are not instantiable:&nbsp;  
+
*A singular case is the&nbsp;Any type. At run time, the related variable&nbsp;can take on the characteristics&nbsp;of one type or, later, another type.&nbsp;That&nbsp;variable&nbsp;must be nullable unless the declaration statement includes an initial value. <br><br>Here is an example where the variable is not nullable:
  
*In some cases, the variable related to the type receives an object only when the variable is used in a particular kind of statement.&nbsp;Such cases apply in SQL processing and in service access; and in those cases, the variable&nbsp;must be nullable.&nbsp;&nbsp;
+
:<pre>myAny Any = new Dictionary;</pre>
*A singular case is the&nbsp;Any type. The related variable&nbsp;is of one type or another at run time, but not of the Any type. In this case, the variable must be nullable unless you instantiate the value of another type in the&nbsp;declaration statement.
+
  
 
== EGL native types  ==
 
== EGL native types  ==
Line 132: Line 134:
 
| &nbsp;&nbsp;&nbsp;&nbsp;'''&nbsp;&nbsp; Name&nbsp;&nbsp;&nbsp;&nbsp;'''  
 
| &nbsp;&nbsp;&nbsp;&nbsp;'''&nbsp;&nbsp; Name&nbsp;&nbsp;&nbsp;&nbsp;'''  
 
| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '''Purpose&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'''
 
| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; '''Purpose&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'''
|-
 
| Class
 
|
 
 
|-
 
|-
 
| DataItem  
 
| DataItem  
Line 184: Line 183:
 
=== Annotation types<br> ===
 
=== Annotation types<br> ===
  
An annotation represents an area of memory and is based on an EGL type. To understand these points, consider the following declaration:<br>
+
An annotation is a value that is based on an EGL Record type. To understand this, consider the following declaration:<br>
<pre>myCarCount NumberOfCars { InputRequired = yes }; </pre>
+
<pre>myCarCount Int{ @InputRequired{yes} }; </pre>
 
That code has effects at two different stages:  
 
That code has effects at two different stages:  
  
*It declares the <code>myCarCount</code> variable. The appropriate declaration statement is generated into the output code, and the related instance is available at run time. The type of the variable is <code>NumberOfCars</code>, which is an alias of type INT. Here is the alias, or data item:
+
*It declares the <code>myCarCount</code> variable. The appropriate declaration statement is generated into the output code, and the related instance is available at run time. <br>
<pre>DataItem
+
 
  NumberOfCars INT
+
End</pre>
+
 
*The example also identifies an instance that is available at transformation time. The type of that instance is '''InputRequired'''.<br><br>Here is the EGL Record type:
 
*The example also identifies an instance that is available at transformation time. The type of that instance is '''InputRequired'''.<br><br>Here is the EGL Record type:
 
<pre>Record InputRequired type Annotation
 
<pre>Record InputRequired type Annotation
 
   value Boolean;
 
   value Boolean;
 
End</pre>
 
End</pre>
All annotations are based on one or another EGL Record type.
+
=== Annotation syntax<br> ===
 
+
=== Annotation syntax ===
+
 
+
The '''InputRequired''' declaration in the earlier source code did not set the value field explicitly. The <code>InputRequired = Yes</code> assignment is a shorthand form of the following code:
+
 
<pre>@InputRequired { value = yes }</pre>
 
<pre>@InputRequired { value = yes }</pre>
The at sign (@) indicates that you are declaring an annotation, and the characters&nbsp;"InputRequired" indicate that the annotation is based on the InputRequired Record type. The next characters then assign content to the fields in the annotation.<br><br>A shorthand form such as <code>InputRequired = Yes</code> is available whenever the Record&nbsp;type for the annotation has a single field, regardless of the name of that field. If an annotation has multiple fields, only the long form of the declaration is valid, as in the following example:  
+
The at sign (@) indicates that you are declaring an annotation, and the characters&nbsp;"InputRequired" indicate that the annotation is based on the InputRequired Record type. The next characters then assign content to the fields in the annotation.<br><br>The following example shows an annotation being declared with multiple fields:  
 
<pre>@AnotherAnnotation { field01 = "test", field02 = 5 }</pre>
 
<pre>@AnotherAnnotation { field01 = "test", field02 = 5 }</pre>
 
An annotation can be based on a Record&nbsp;type that only has fields with default values.&nbsp;Here is an example:  
 
An annotation can be based on a Record&nbsp;type that only has fields with default values.&nbsp;Here is an example:  
Line 210: Line 203:
 
In that&nbsp;case, the mere presence of the annotation is meaningful to the EGL system code, and only the at sign (@) is required. Here is an example declaration:<br>
 
In that&nbsp;case, the mere presence of the annotation is meaningful to the EGL system code, and only the at sign (@) is required. Here is an example declaration:<br>
 
<pre>@ThirdAnnotation&nbsp;</pre>
 
<pre>@ThirdAnnotation&nbsp;</pre>
In many cases, you can declare multiple annotations, one separated from the next by a comma. For example, the following code declares the '''InputRequired''' and '''DisplayName''' annotations:&nbsp;  
+
If an annotation contains only one field, the name of the field does not have to be specified when declaraing the annotation.&nbsp; Here is an example:<br>
 +
<pre>@InputRequired { yes }
 +
</pre>
 +
In many cases, you can declare multiple annotations, one separated from the next by a comma. For example, the following code declares the '''InputRequired''' and '''IsDecimalDigit '''annotations:&nbsp;  
 
<pre>myCarCount NumberOfCars {
 
<pre>myCarCount NumberOfCars {
   InputRequired = yes,
+
   @InputRequired{yes},  
  DisplayName  = "Number of cars: " };</pre>
+
   @IsDecimalDigit };</pre>
=== Annotation overrides  ===
+
 
+
You can declare an annotation when you define a type, and then override the annotation when you declare a variable that is based on the type.
+
 
+
Here is a data item with two annotations:<br>
+
<pre>DataItem
+
   NumberOfCars {
+
      InputRequired = no,
+
      DisplayName = "Number of cars: "}
+
End</pre>
+
The following variable declaration overrides the previous value of the&nbsp;'''InputRequired''' annotation:<br>
+
<pre>myCarCount NumberOfCars { InputRequired = yes }; </pre>
+
If a data item or part includes several annotations and a few are overridden in a variable declaration, the annotations that were not overridden are still in effect. In the previous example, the <code>myCarCount</code> variable is associated with both the '''InputRequired''' and '''DisplayName''' annotations.
+
 
+
The ability to set multiple annotations is particularly important for data items. For example, a data item might be defined with annotations that are meaningful for user interface and for accessing a relational database. The benefit of being able to specify multiple annotations is that you can retain data items in a library and use those data items for many purposes. When you use a data item to declare a variable for one purpose such as database&nbsp;access, the annotations relevant to other purposes such as user interface have no effect.
+
 
+
 
Most annotations have a relatively small effect. For example, the '''InputRequired''' annotation specifies whether a field in a user-interface form is generated in one way or another. But a stereotype is an annotation that affects a series of decisions; the effect is greater.<br>
 
Most annotations have a relatively small effect. For example, the '''InputRequired''' annotation specifies whether a field in a user-interface form is generated in one way or another. But a stereotype is an annotation that affects a series of decisions; the effect is greater.<br>
  
 
== Stereotypes  ==
 
== Stereotypes  ==
  
A stereotype is an annotation that you set to communicate a major decision to the EGL compiler. In response to the annotation, the compiler responds in accordance with a pattern that differs from one stereotype to another.  
+
A '''stereotype''' is an annotation that you set to communicate a major decision to the EGL compiler. In response to the stereotype, the compiler processes&nbsp;your code in a way that differs depending on which stereotype is specified.<br><br>For example, you can declare a Handler type that does not include a stereotype. In this case, the Handler type is the basis of a basic handler, which is a variable that contains fields, functions, or both.  
  
For example, you might want to display a web page that&nbsp;responds as follows to a button click: by changing&nbsp;the button text from "Toggle on" to "Toggle off" or from "Toggle off" to "Toggle on".&nbsp;&nbsp;The logic is in the following handler, which includes a declaration for the '''RUIHandler''' stereotype:
+
<br>In contrast, if you declare a Handler type that includes the '''RUIHandler''' stereotype, the handler provides&nbsp;a way to interact with&nbsp;a web browser for the purpose of maintaining a web page at run time.  
 +
 
 +
Consider the following Handler type:&nbsp;  
 
<pre>Handler MyHandler type RUIhandler{
 
<pre>Handler MyHandler type RUIhandler{
 
   initialUI =[myButton],
 
   initialUI =[myButton],
Line 256: Line 238:
 
   end
 
   end
 
end </pre>
 
end </pre>
You might want to provide the same capability on a mobile device that runs on the Android operating system. In this case, an extender might&nbsp;provide a pair of constructs...&nbsp;&nbsp;??
+
The '''type''' clause refers to the '''RUIHandler''' stereotype, which causes the Handler type to be&nbsp;deployable, unlike a Handler type that has no stereotype. The example code displays a web page that responds as follows to a button click: changes the button text from "Toggle on" to "Toggle off" or from "Toggle off" to "Toggle on".&nbsp;  
<pre>Handler MyHandler type WindowHandler
+
  { createLayout = true, contentView = }
+
  
  &nbsp;????
+
The presence or absence of a stereotype also changes the capabilities provided by a Library type. For example, when you declare a Library type without a stereotype, the type contains fields and functions that might be available to multiple handlers. However, when you declare a Library type with the '''RUIPropertiesLibrary''' stereotype, you define a library containing fields that that holds values provided from&nbsp;a properties file at run time.<br><br>To see that a stereotype is a kind of annotation, compare the following, equivalent&nbsp;outlines for the '''MyHandler''' handler:  
 
+
  myButton DojoButton{
+
      text = "Toggle on",  
+
      onClick&nbsp;::= myButton_onClick };
+
 
+
  function myButton_onClick(event Event in)
+
      if (myButton.text == "Toggle on")
+
        myButton.text = "Toggle off";
+
      else
+
        myButton.text = "Toggle on";
+
      end
+
  end
+
end</pre>
+
[ Explain ]<br><br>To see that a stereotype is a kind of annotation, compare the following, equivalent&nbsp;outlines for the '''MyHandler''' handler:  
+
 
<pre>Handler MyHandler type RUIHandler
 
<pre>Handler MyHandler type RUIHandler
 
                   {  
 
                   {  
Line 296: Line 262:
 
end</pre>
 
end</pre>
 
Although the second, longer form is rarely used, the at sign (@) again declares a value used by an EGL compiler.&nbsp;In this case, the declaration is based on the Record type named '''RUIHandler''', which includes several fields:  
 
Although the second, longer form is rarely used, the at sign (@) again declares a value used by an EGL compiler.&nbsp;In this case, the declaration is based on the Record type named '''RUIHandler''', which includes several fields:  
<pre>Record RUIHandler type Annotation
+
<pre>Record RUIHandler type Stereotype
 
   {
 
   {
 
       targets = [ElementKind.handlerPart],
 
       targets = [ElementKind.handlerPart],
       @Stereotype {defaultSuperType=View},
+
       defaultSuperType=View,
 
       validationProxy =  
 
       validationProxy =  
  
Line 312: Line 278:
 
   theme String;  
 
   theme String;  
 
end</pre>
 
end</pre>
The '''RUIHandler''' Record type declares three&nbsp;annotations:  
+
The '''RUIHandler''' Record initializes 3 fields in the '''Stereotype '''type:  
  
 
*'''targets''' indicates the custom types for which the stereotype applies.&nbsp;The term "part" is sometimes used in place of the term "custom type," and the '''ElementKind.handlerPart '''value indicates that&nbsp;a&nbsp;Handler type can be annotated with&nbsp;a&nbsp;value of type '''RUIHandler'''.&nbsp;The absence of any other '''ElementKind''' value indicates that no other kind of custom type can be annotated in the same way.  
 
*'''targets''' indicates the custom types for which the stereotype applies.&nbsp;The term "part" is sometimes used in place of the term "custom type," and the '''ElementKind.handlerPart '''value indicates that&nbsp;a&nbsp;Handler type can be annotated with&nbsp;a&nbsp;value of type '''RUIHandler'''.&nbsp;The absence of any other '''ElementKind''' value indicates that no other kind of custom type can be annotated in the same way.  
*'''@Stereotype''' indicates that the Record type is defining a stereotype.&nbsp;Fields in the '''View''' supertype are available to the Handler type being stereotyped.&nbsp;In particular, the&nbsp;custom Handler&nbsp;type has access to the&nbsp;'''initialUI'''&nbsp;field, which&nbsp;lists the widgets&nbsp;for initial&nbsp;display on the web page.  
+
*'''defaultSuperType '''indicates that the Handler type being stereotyped will be compatible with the '''View '''type, and all fields and functions&nbsp;in the '''View''' supertype are available to it.&nbsp;In particular, the&nbsp;custom Handler&nbsp;type has access to the&nbsp;'''initialUI'''&nbsp;field, which&nbsp;lists the widgets&nbsp;for initial&nbsp;display on the web page.  
 
*'''validationProxy''' identifies a&nbsp;Java class that validates the stereotype value with which the custom Handler type is annotated.
 
*'''validationProxy''' identifies a&nbsp;Java class that validates the stereotype value with which the custom Handler type is annotated.
  
Line 321: Line 287:
  
 
If you annotate a custom type with a stereotype, and if the custom type can include fields of its own, the stereotype can declare an annotation of type '''MemberAnnotations'''.&nbsp;The purpose is to&nbsp;list the annotations that can be appled to each&nbsp;field of the custom type.&nbsp;Here is an example of such an annotation:  
 
If you annotate a custom type with a stereotype, and if the custom type can include fields of its own, the stereotype can declare an annotation of type '''MemberAnnotations'''.&nbsp;The purpose is to&nbsp;list the annotations that can be appled to each&nbsp;field of the custom type.&nbsp;Here is an example of such an annotation:  
<pre>Record ExampleStereotype type Annotation
+
<pre>Record ExampleStereotype type Stereotype
 
{
 
{
 
   targets = [ElementKind.recordPart],
 
   targets = [ElementKind.recordPart],
 
   memberAnnotations = [Annotation01, Annotation02]
 
   memberAnnotations = [Annotation01, Annotation02]
  @Stereotype {}
 
 
}
 
}
  

Latest revision as of 12:38, 17 June 2013

EGL types and values

The next sections move from general comments to a review of EGL native types, custom types, classifiers, annotations, and stereotypes.

General comments on types and values

In general usage, a type such as integer or string defines a set of values and a set of operations that can be applied to those values. For example, integers are whole numbers that can be added, subtracted, and so forth; and the number 5 is a value of that type.

The meaning is much the same in EGL, where every value is “of a type.” The type defines the structure of the value and the set of operations that can be applied to the value.

Types can be categorized in different ways, and we initially distinguish between reference and value types:  

  • A reference type defines an object, which is a value in a memory area that was separately allocated to hold the value. The object is referenced from some logic and is an instance of the type. In this case, the words "value," "object," and "instance" are interchangeable.
  • A value type defines a value that is embedded in an object.

field declaration is a coded statement that declares a value in a memory area. If the value is based on a reference type, the memory area typically holds an address that points to the value. If the value is based on a value type, the memory area contains the value itself.

The difference between reference and value types has practical effect when you are assigning a value from one memory area to another. [ details to follow ]

Variables and constants

A named field declaration includes an identifier that names the memory area for subsequent use. If the embedding code is allowed to update the area, the identifier is a variable. If the update is disallowed, the identifier is a constant

Consider the following field declarations:

   // variable declaration
   NumberOfCars INT;    
   
   // constant declaration
   const MINIMUMNUMBER INT = 2; 

The type is each case is INT, which is a value type for four-byte integers. The first statement declares a value variable, the second declares a value constant.

For a second example, you might declare a list of integers by coding a statement like one of these:

   // variable declaration
   NumberOfVehicles INT[];

   // constant declaration
   const MINIMUMNUMBERS INT[] = [1,2,3,4,5];

The type in this case is INT List or INT[], which is a reference type. The first statement declares a reference variable, which means that you can assign a different list to NumberOfVehicles later. Incidentally, you can also change the values inside the list and can change the number of elements.

The second statement declares a reference constant, which means that you cannot assign a different value to MINIMUMNUMBERS. However, even in this case, you can alter the values inside the list and can change the number of elements.

The behavior is consistent because each declaration is referring to a list, not to an element in a list. The constant is only constant in the sense that the area identified as MINIMUMNUMBERS must always contain the same address, which refers to the same list. The following, subsequent assignment is not valid even though the values are the same:

   // An invalid assignment
   MINIMUMNUMBERS = [1,2,3,4,5]; 

Nullability

In some cases, a reference type is nullable, which means that a variable of that type might refer to an object or might not. 

A variable that is declared to be of a nullable type is called a nullable variable. If such a variable does not refer to an object, the variable is said to be null, with no value at all.

To indicate that a type is nullable, add a question mark to the end of the type name. For example, here is another List declaration:

   myList Int[]?;

After that declaration runs, myList is null.  You might assign a value to myList and then reset the variable to null, as shown next: 

   myList = [1,2,3,4,5]; 
   myList = null;

In EGL, you can make any variable nullable, even a value variable. For example, Int is a value type, but after the following code runs, myInt is null: 

myInt Int?;  

The variable continues to behave as a value variable when used in a statement that assigns a value. 

Instantiability

A type is instantiable if you can create a instance of that type by using the new operator. For example, an EGL dictionary is a reference variable that is composed of a set of entries, each of which is a key and a related value. Here is how you might instantiate a dictionary:

myDictionary Dictionary = new Dictionary
                              { lastName  = "Twain",
                                firstName = "Mark"  };

EGL offers the following convenience:  you can declare an instance of an instantiable type without using the new operator. Here is an example, which is neither more nor less efficient than the previous one: 

myDictionary Dictionary 
             { lastName  = "Twain",
               firstName = "Mark"  };

Alternatively, the instance can be created without content, as here:

myDictionary Dictionary;

When an instantiable type is nullable, you must instantiate the type explicitly. For example, the following code declares a nullable variable and sets it to null, without creating an instance:

myDictionary Dictionary?;

For a second but invalid example, consider code that tries to assign field values to a null variable: 

// error at compile time
myDictionary Dictionary? 
             { lastName = "Twain",
               firstName = "Mark" }; 

One way to correct that error is to instantiate the dictionary in the same statement:

myDictionary Dictionary? = new Dictionary
                               { lastName = "Twain",
                                 firstName = "Mark" };

You can instantiate any EGL value type, although doing so merely places the default value for the type into the memory area.  For example, the following code assigns 0 to myInt:

 myInt Int = new Int{};

The value variable continues to be a value variable.

Last, several EGL reference types are not instantiable: 

  • In some cases, a variable of a non-instantiable type receives an object from the EGL runtime code, but only when the variable is used in a particular way. Such cases apply in SQL processing and in service access; and in those cases, the variable must be nullable.  
  • A singular case is the Any type. At run time, the related variable can take on the characteristics of one type or, later, another type. That variable must be nullable unless the declaration statement includes an initial value.

    Here is an example where the variable is not nullable:
myAny Any = new Dictionary;

EGL native types

EGL Core defines a set of native types, which are implemented only by extensions such as Eclipse IDE for EGL Developers. The most elemental are the simple types. They have no sub-fields and can be categorized as follows:

  • Boolean, which is the basis of a field that contains the logical true or false.
  • Character types 
  • Timestamp types
  • Large object types
  • Numeric types

The following native types are also defined in EGL Core and implemented by Eclipse IDE for the EGL Developer: 

  • ANY, which is the basis of an instance that can reference a value of any type.
  • Dictionary type, which is the basis of a dictionary. A dictionary is composed of key-value
    pairs that can be increased or decreased in number and otherwise updated at run time.
  • List types, each of which is the basis of a list. A list is a dynamic array: an ordered sequence of elements that can be increased or decreased in number and otherwise updated at run time.

Custom types and EGL classifiers

EGL provides a variety of classifiers, each of which is a kind of type. The capabilities of a classifier are made available to your code in various situations; most often, when you define a custom type that is based on a classifier.

Characteristics of custom types

Depending on the classifier, a custom type can have some or all of the following characteristics:

  • A header, which is always required. The header includes the classifier name; the name of the custom type; and, in some cases, a stereotype.
  • The end keyword, which is the last detail in the type definition.
  • A set of members:
    • Fields, each of which is based on a native or custom type.
    • Functions, each of which is a logical unit that is equivalent to a function or method in another language. EGL functions do not embed other functions.
    • Constructors, each of which is a logical unit that creates an instance of a reference type.

The members in a custom type are typically accessible in the same type. However, if you declare a member to be private, the member is protected from external access; it can be accessed only within the same type. If you do not declare a member to be private, it is said to be public.

Kinds of classifiers

The next table lists the classifier provided in EGL Core. 

Kinds of classifiers
       Name                              Purpose                        
DataItem To alias a native or custom type.
Delegate To define a type that identifies a kind of function. The related variable is like a function pointer in C language.
Enumeration To define a type that holds a collection of named values. The value of the related variable is one of those values. 
ExternalType To define a type that identifies non-EGL code. The related variable provides access to the code.
Handler To define a type that includes all the possible kinds of members. The related variable either defines a general purpose object or allows for interaction with a user interface technology.
Interface

To define a type that represents a contract between a unit of logic such as a service and the logic requester. Uses are twofold:

  • To enable access of the unit of logic, EGL code declares a variable that is based on the Interface type. 
  • To ensure that design decisions are fulfilled, you can code the unit of logic to reference an Interface type.
Library To define a static type that contains fields and functions that are local to other EGL logic. The fields retain values across requesters.
Program To define a static type that has a single entry point.
Record To define a type that includes fields.
Service To define a static type that has multiple entry points and that might be accessed locally or remotely.  The type also can be the basis of a variable that provides access to the logic from other EGL code.

To extend a capability, an extender makes an additional stereotype available for use with an existing classifier. The list of classifiers is a fixed aspect of the language.

Annotations

When you write EGL source code, you set annotations. They are values used by some aspect of EGL technology; in most cases, by the EGL compiler. 

Annotations help ensure that your EGL-created output reflects your intent. You can set them when you define custom types; when you declare variables and constants; when you code a subset of EGL statements; and, in some cases, when you declare functions.

For example, when you declare a field in a user-interface form, you might set a YES value in the InputRequired annotation. That setting causes the EGL generator to store a detail in the generated output, and the detail ensures that the user can submit the form only if the specified field has content.

Annotation types

An annotation is a value that is based on an EGL Record type. To understand this, consider the following declaration:

myCarCount Int{ @InputRequired{yes} }; 

That code has effects at two different stages:

  • It declares the myCarCount variable. The appropriate declaration statement is generated into the output code, and the related instance is available at run time.
  • The example also identifies an instance that is available at transformation time. The type of that instance is InputRequired.

    Here is the EGL Record type:
Record InputRequired type Annotation
   value Boolean;
End

Annotation syntax

@InputRequired { value = yes }

The at sign (@) indicates that you are declaring an annotation, and the characters "InputRequired" indicate that the annotation is based on the InputRequired Record type. The next characters then assign content to the fields in the annotation.

The following example shows an annotation being declared with multiple fields:

@AnotherAnnotation { field01 = "test", field02 = 5 }

An annotation can be based on a Record type that only has fields with default values. Here is an example:

Record ThirdAnnotation type annotation
   value Boolean = true;
end

In that case, the mere presence of the annotation is meaningful to the EGL system code, and only the at sign (@) is required. Here is an example declaration:

@ThirdAnnotation 

If an annotation contains only one field, the name of the field does not have to be specified when declaraing the annotation.  Here is an example:

@InputRequired { yes }

In many cases, you can declare multiple annotations, one separated from the next by a comma. For example, the following code declares the InputRequired and IsDecimalDigit annotations: 

myCarCount NumberOfCars {
   @InputRequired{yes}, 
   @IsDecimalDigit };

Most annotations have a relatively small effect. For example, the InputRequired annotation specifies whether a field in a user-interface form is generated in one way or another. But a stereotype is an annotation that affects a series of decisions; the effect is greater.

Stereotypes

A stereotype is an annotation that you set to communicate a major decision to the EGL compiler. In response to the stereotype, the compiler processes your code in a way that differs depending on which stereotype is specified.

For example, you can declare a Handler type that does not include a stereotype. In this case, the Handler type is the basis of a basic handler, which is a variable that contains fields, functions, or both.


In contrast, if you declare a Handler type that includes the RUIHandler stereotype, the handler provides a way to interact with a web browser for the purpose of maintaining a web page at run time.

Consider the following Handler type: 

Handler MyHandler type RUIhandler{
   initialUI =[myButton],
   onConstructionFunction = start}
   
   myButton DojoButton{ 
      onClick ::= myButton_onClick }; 
   
   function start()
      myButton.text = "Toggle on";
   end

   function myButton_onClick(event Event in)
      if (myButton.text == "Toggle on")
         myButton.text = "Toggle off";
      else
         myButton.text = "Toggle on"; 
      end
   end
end 

The type clause refers to the RUIHandler stereotype, which causes the Handler type to be deployable, unlike a Handler type that has no stereotype. The example code displays a web page that responds as follows to a button click: changes the button text from "Toggle on" to "Toggle off" or from "Toggle off" to "Toggle on". 

The presence or absence of a stereotype also changes the capabilities provided by a Library type. For example, when you declare a Library type without a stereotype, the type contains fields and functions that might be available to multiple handlers. However, when you declare a Library type with the RUIPropertiesLibrary stereotype, you define a library containing fields that that holds values provided from a properties file at run time.

To see that a stereotype is a kind of annotation, compare the following, equivalent outlines for the MyHandler handler:

Handler MyHandler type RUIHandler
                  { 
                      initialUI =[myButton],
                      onConstructionFunction = start
                  }

   // handler members are here 

end

Handler MyHandler { @RUIHandler 
                    { 
                       initialUI = [myButton],
                       onConstructionFunction = start
                    } 
                  } 

   // handler members are here

end

Although the second, longer form is rarely used, the at sign (@) again declares a value used by an EGL compiler. In this case, the declaration is based on the Record type named RUIHandler, which includes several fields:

Record RUIHandler type Stereotype
   {
      targets = [ElementKind.handlerPart],
      defaultSuperType=View,
      validationProxy = 

         // split onto two lines for better display
         "org.eclipse.edt.compiler.binding.
         annotationType.RUIHandlerAnnotationTypeBinding"
   }
   onConstructionFunction FunctionMemberRef;
   includeFile String;
   cssFile String;
   title String;
   theme String; 
end

The RUIHandler Record initializes 3 fields in the Stereotype type:

  • targets indicates the custom types for which the stereotype applies. The term "part" is sometimes used in place of the term "custom type," and the ElementKind.handlerPart value indicates that a Handler type can be annotated with a value of type RUIHandler. The absence of any other ElementKind value indicates that no other kind of custom type can be annotated in the same way.
  • defaultSuperType indicates that the Handler type being stereotyped will be compatible with the View type, and all fields and functions in the View supertype are available to it. In particular, the custom Handler type has access to the initialUI field, which lists the widgets for initial display on the web page.
  • validationProxy identifies a Java class that validates the stereotype value with which the custom Handler type is annotated.

The RUIHandler Record type also declares a set of fields, which are available to any custom type that declares a RUIHandler stereotype. The earlier code identified only one of those fields: onConstructionFunction, which references a constructor that runs initially, before the user accesses the web page. These fields are properly called annotation fields or, more specifically, stereotype fields.   

If you annotate a custom type with a stereotype, and if the custom type can include fields of its own, the stereotype can declare an annotation of type MemberAnnotations. The purpose is to list the annotations that can be appled to each field of the custom type. Here is an example of such an annotation:

Record ExampleStereotype type Stereotype
{
   targets = [ElementKind.recordPart],
   memberAnnotations = [Annotation01, Annotation02]
}

// stereotype fields are here

end

The developer of the custom type can annotate each field with Annotation01 and Annotation02, which are also Record types of type Annotation.

Each classifier supports zero to many stereotypes. For example, a Handler type can include a declaration of RUIHandler or RUIWidget. A developer who codes a custom type selects from the stereotype list that is specific to a classifier.



Next:  Packages and type-name resolution

Previous:  Introduction

Back to the top