TOC PREV NEXT INDEX DOC LIST MASTER INDEX



Package Expressions

Package Expressions provides access to expressions and their components, function calls, and use clauses. These items are defined by the following Ada constructs:

For more information, click on a topic:


Resources in Package Expressions

The subprograms in package Expressions fall into several functional groups, as shown below.

To see detailed referenced information, click on the name of a subprogram:
Determining expression kinds, types, and names:
Expression_Type Kind Name
Declarations and definitions of entities:
Name_Declaration Name_Definition

Identifying references to entities:
Is_Referenced References

Processing the components of names:
Attribute_Designator_Argument Attribute_Designator_Kind Attribute_Designator_Name Index_Expressions Prefix Selected_Component Selected_Designated_Subtype Selected_Task_Entry Selection_Kind Selector Slice_Range

Processing function calls:

Called_Function Function_Call_Parameters Is_Normalized Is_Parameter_Association Prefix
Processing literals:
Is_Literal Is_Static Position_Number_Image Representation_Value_Image Static_Value
Processing aggregates:

Component_Choices Component_Expression Components

Processing parenthetical expressions:
Expression_Parenthesized

Processing operators and implicit subprograms:
Expression_Associated_Type Is_Derived Is_Implicit Is_Predefined Is_Prefix_Call Operator_Kind Subprogram_Derivation

Processing special operations:
In_Range_Operation_Right_Hand_Side In_Type_Operation_Right_Hand_Side Short_Circuit_Operation_Right_Hand_Side Special_Operation_Kind Special_Operation_Left_Hand_Side
Processing type conversions:

Converted_Or_Qualified_Expression Type_Mark
Processing qualified expressions:
Converted_Or_Qualified_Expression Type_Mark
Processing allocators:

Allocation_Type Qualified_Object_Expression
Processing static and universal expressions:
Is_Static Is_Universal Static_Value

Processing use clauses:

Named_Packages


Key Concepts for Package Expressions

Package Expressions provides access to expressions and their components, function calls, and use clauses. The processing is divided into the following categories. To see more information, click on a topic:

Expression Kinds, Types, and Object Names

An expression is a formula that defines the computation of a value (Ada83 LRM 4.4, Ada95 LRM 4.4). Expressions are recursive structures of operands (or primaries) and operators, and they are represented by elements. Primaries include such things as literals, names, and function calls. Operators include such things as relational operators, binary and unary adding operators, and membership tests. Each element of an expression has an Element_Kinds of An_Expression.

The Expression_Kinds type describes all the components, both primaries and operators, that can make up an expression. Given an element with an Element_Kinds of An_Expression, you can determine the Expression_Kinds with the Kind function. The Expression_Kinds determines how additional analysis of the expression should be performed.

Most expressions also have a type, which is defined by an associated type definition. Further, since expressions are defined recursively, each element composing an expression can have a type. You can obtain the type definition for an expression by calling the Expression_Type function. This function returns a type definition that is a base type, universal type, subtype, or derived type. The functions in package Declarations can be used to analyze the returned type definition.

There is one class of expression that does not have a type and another class that might not have a type:

If an expression does not have a type, Asis.Nil_Element is returned by the Expression_Type function.

Primaries that represent terminal elements —— for example, a simple variable name or a character literal —— have an associated text image. Function calls, which include the predefined operators, also have an associated text image. You can obtain the text image of the name with the Name function.

To be supplied: Include some Element trees here which include the Expression_Kinds, Expression_Type, and Name for each node. If implicit conversions or other nasty stuff take place describe that.

Declarations and Definitions of Entities

An Ada entity definition can be either:

Various ASIS functions allow you to move between the halves of specific kinds of two-part definitions. For example, Declarations.Corresponding_Specification returns the specification that corresponds to a given body and Declarations.Corresponding_Constant_Declaration returns the full constant declaration for a specified deferred constant.

Given an entity representing an implementation or use, the Name_Definition function can provide the entity's definition. For example, if a specified element represents A_Simple_Name of a variable's use, An_Entity_Name_Definition from the variable's declaration is returned.

If provided with the second part of a two-part entity definition, Name_Definition returns the first part. If provided with the first part of a one- or two-part definition, it acts as an identity function and returns the argument.

Name_Definition returns a non-nil result except when provided with an attribute reference that is not an attribute function. Such attributes have no defining instance. The Element_Kinds of a non-nil result is always An_Entity_Name_Definition.

A non-nil Name_Definition always has an enclosing element with an Element_Kinds of A_Declaration or A_Statement.

The Name_Declaration function returns the declaration for an entity reference. Calling this function is equivalent to calling Name_Definition and then (for non-nil results) calling Elements.Enclosing_Element.

References to Entities

ASIS provides functions that determine whether and where an entity has been referenced.

You can call the Is_Referenced function, which returns a Boolean value, to determine whether an entity has been referenced within a particular context. You can call the References function, which returns a list of elements, to determine where an entity has been referenced.

The search can be performed with an entity name or an expression. If an entity name is specified, the search is for the corresponding simple name or operator symbol. If an expression is specified, the search is performed with the associated Name_Definition function. See "Declarations and Definitions of Entities" for more information on the Name_Definition function.

Both functions require a Context parameter. This parameter specifies the range of elements over which the search will take place. The context can reference anything from a single element through the declaration for an entire library or secondary unit.

Processing the Components of Names

Names are defined by the following syntax:

Ada83 LRM 4.1, Ada95 LRM 4.1

 name ::= simple_name
  | character_literal
  | operator_symbol
  | indexed_component
  | slice
  | selected_component
  | attribute

 simple_name ::= identifier

 prefix ::= name | function_call

Each of the above syntax components is described in its own section, as indicated in the following table:
Syntax Component
Described in Section
simple_name
identifier

"Expression Kinds, Types, and Object Names"
character_literal
"Processing Literals"
indexed_component
"Processing Indexed Components"
slice
"Processing Slices"
selected_component
"Processing Selected Components"
attribute
"Processing Attributes"
prefix
"Processing Prefixes"
function_call
"Processing Function Calls"

Processing Prefixes

Prefixes are defined by the following syntax:

Ada83 LRM 4.1, Ada95 LRM 4.1 

prefix ::= name | function_call

Function calls are defined by the following syntax:

Ada83 LRM 6.4, Ada95 LRM 6.4

 function_call ::=
  function_name [actual_parameter_part]

The function_name syntax component is a reference to the syntax-component name. That is:

 function_name ::= name

Thus, a prefix is a name, either directly or through the definition of a function call.

A review of the syntax diagram for name shows that it is composed of terminal and composite components. A review of the syntax diagrams for each of the composite components shows that they include a prefix.

This circular definition —— from prefix, to name, to composite, and back to prefix —— defines the multiple levels of dereferencing that are possible in an Ada program. This allows you, for example, to call a function that returns an array of records (a function call), select an element of the array (an indexed component), and then a component of the record (a selected component).

You can obtain the prefix with the Prefix function. The returned expression represents the construct to the left of the rightmost unnested left parenthesis in function calls, indexed components, or slices; the construct to the left of the rightmost dot in selected components; or the construct to the left of the rightmost apostrophe for attributes.

Processing Indexed Components

Indexed components are defined by the following syntax:

Ada83 LRM 4.1.1, Ada95 LRM 4.1.1

 indexed_component ::=
  prefix(expression {, expression})

The element representing an indexed component has an Expression_Kinds of An_Indexed_Component.

The components can be obtained by calling the subprograms in the following table:
Information Desired
Call to Use
prefix
Prefix
expression list
Index_Expressions

Processing Slices

Slices are defined by the following syntax:

Ada83 LRM 4.1.2, Ada95 LRM 4.1.2 

slice ::= prefix(discrete_range)

The element representing a slice has an Expression_Kinds of A_Slice.

The components can be obtained by calling the subprograms in the following table:
Information Desired
Call to Use
prefix
Prefix
discrete_range
Slice_Range

Processing Selected Components

Selected components are defined by the following syntax:

Ada83 LRM 4.1.3, Ada95 LRM 4.1.3 

selected_component ::= prefix.selector

 selector ::= simple_name
  | character_literal
  | operator_symbol
  | all

The element representing a selected component has an Expres-sion_Kinds of A_Selected_Component.

The components and related information can be obtained by calling the subprograms in the following table:
Information Desired
Call to Use
prefix
Prefix
selector
Selector
The kind of selector
Selection_Kind
The declaration of a discriminant or record-component selector
Selected_Component
The entry declaration of a task- entry selector
Selected_Task_Entry
The designated subtype or type of an access-object selector
Selected_Designated_Subtype

Processing Attributes

Attributes are defined by the following syntax:

Ada83 LRM 4.1.4, Ada95 LRM 4.1.4 

attribute ::= prefix'attribute_designator

 attribute_designator ::=
  simple_name [(universal_static_expression)]

The element representing an attribute has an Expression_Kinds of An_Attribute.

The components and related information can be obtained by calling the subprograms in the following table:
Information Desired
Call to Use
prefix
Prefix
simple_name
Attribute_Designator_Name
universal_static-_expression
Attribute_Designator_Argument
The kind of the attribute-_designator
Attribute_Designator_Kind

Processing Function Calls

Function calls are partially defined by the following syntax:

Ada83 LRM 6.4, Ada95 LRM 6.4

 function_call ::=
  function_name [actual_parameter_part]

 parameter_association ::=
  [formal_parameter =>] actual_parameter

The element representing a function call has an Expression-_Kinds of A_Function_Call.

Operators are also defined as functions. In this case, the function name is the name of an operator. ASIS functions are available to identify function calls that are predefined operators, whether the subprograms are implicitly defined and possibly derived, what the associated type definition was if implicitly defined, and whether the call has been made in prefix notation. See "Processing Operators" and "Processing Implicit Subprograms" for more information.

The components and related information can be obtained by calling the subprograms in the following table:
Information Desired
Call to Use
function_name
Prefix
parameter_association list
Function_Call_Parameters
The declaration of the called function
Called_Function
Whether an element represents a parameter-
_association

Is_Parameter_Association

Association Lists

Associations represent the pairing of a name and a value. The name represents the formal parameter and the value the actual parameter.

A number of functions return lists containing associations:
Function Name
Association Element_Kinds
Components
A_Component_Association
Type_Definitions.-
Discriminant_Associations

A_Discriminant_Association
Function_Call_Parameters
Declarations.Generic-
_Parameters
Statements.Call_Parameters

A_Parameter_Association

Each of the above functions contains a Normalized parameter. This parameter determines whether the returned list contains normalized or unnormalized associations. Not all ASIS implementations are able to return unnormalized lists. In this case, the Normalized parameter is ignored and all returned lists contain normalized associations. See package Environment, "Normalization of Parameter Lists" for more information.

You can call the Is_Normalized function to determine whether an element from an association was obtained from a normalized or unnormalized list.

Processing Literals

A literal is a numeric literal, an enumeration literal, the literal null, a string literal, or a character literal (Ada83 LRM 4.2, Ada95 LRM 4.2). Numeric literals can be either integer or real.

Elements with the following Expression_Kinds represent literals:

You can determine whether an expression represents a literal by calling the Is_Literal function.

Literals are also static (see "Processing Static and Universal Expressions" for more information). You can obtain the text image of a literal with the Static_Value function.

Two additional functions that return text images are available for enumeration literals:

Processing Aggregates

Aggregates are defined by the following syntax:

Ada83 LRM 4.3, Ada95 LRM 4.3

 aggregate ::=
  (component_association
   {, component_association})

 component_association ::=
  [choice {| choice} => ] expression

The element representing an aggregate has an Expression-_Kinds of An_Aggregate.

The components can be obtained by calling the subprograms in the following table:
Information Desired
Call to Use
component_association list
Components
choice list
Component_Choices
expression
Component_Expression

Processing Expressions

The Ada syntax for expressions contains a large number of components. These components are shown in "Expressions and Relations" and "Primaries." Unlike most other syntax-driven ASIS analysis, however, there are no functions that return elements that correspond exactly to most of these syntactic components. There are no functions that return these syntactic components: expression, relation, simple_expression, term, or factor. Similarly, there are no functions that return the individual operator classes.

To ASIS, an expression is essentially a number of primaries, or parenthesized primaries, joined together by function calls or special operations. Remember that function calls can be either predefined operators or user-defined functions (see "Processing Function Calls" for more information).

For example, consider the expression A + B. This expression has been written in infix notation. If the expression is written in prefix notation, the way in which function calls join the primaries can be seen more clearly. The expression in prefix notation is + (A, B). The predefined addition operator (+) is nothing more than a function with two parameters, and it is represented in this way by ASIS.

You can determine the kind of an operator, and, if necessary, the operator kind can be used to determine the syntactic components being joined. However, there is typically no need to identify an element as representing, for example, a simple expression versus a factor.

Expressions and Relations

This section describes expressions, relations, and their
components.

Expressions are defined by the following syntax:

Ada83 LRM 4.4, Ada95 LRM 4.4

 expression ::=
   relation {and relation}
  | relation {and then relation}
  | relation {or relation}
  | relation {[or else relation}
  | relation {xor relation}

The reserved words and, or, and xor represent logical operators. See "Processing Operators" for more information. The reserved words and then and or else represent short-circuit control forms. See "Processing Special Operations" and "Processing Short-Circuit Control Forms" for more information.

Relations are defined by the following syntax:

Ada83 LRM 4.4, Ada95 LRM 4.4 

relation ::=
   simple_expression
    [relational_operator simple_expression]
  | simple_expression [not] in range
  | simple_expression [not] in type_mark

See "Processing Operators" for a description of relational operator. The reserved words not in represent a membership test. See "Processing Special Operations" and "Processing Membership Tests" for more information.

Simple expressions, terms, and factors are defined by the following syntax:

Ada83 LRM 4.4, Ada95 LRM 4.4 

simple_expression ::= [unary_adding_operator]
  term {binary_adding_operator term}

 term ::= factor {multiplying_operator factor}

 factor ::= primary [** primary]
  | abs primary | not primary

The syntactic components unary_adding_operator, binary_ad-ding_operator, and multiplying operator, the reserved words abs and not, and the exponentiate operator (**) all represent operators. See "Processing Operators" for more information.

Primaries are described in "Primaries."

Primaries

Primaries are defined by the following syntax:

Ada83 LRM 4.4, Ada95 LRM 4.4

 primary ::=
   numeric_literal | null | aggregate
  | string_literal | name | allocator
  | function_call | type_conversation
  | qualified_expression | (expression)

Primaries include terminal symbols and composite symbols. Terminal symbols, such as a numeric literal, cannot be further analyzed. Composite symbols, such as a function call, can be further analyzed with the appropriate functions. Names can be either terminal or composite. If a name represents a simple name, character literal, or operator symbol, it is terminal; otherwise, it is composite.

Each of the syntactic components of a primary is described in its own section, as indicated in the following table:
Syntax Component
Described in Section
numeric_literal
"Processing Literals"
null
"Processing Literals"
aggregate
"Processing Aggregates"
string_literal
"Processing Literals"
name
"Expression Kinds, Types, and Object Names"
allocator
"Processing Allocators"
function_call
"Processing Function Calls"
type_conversion
"Processing Type Conversions"
qualified-
_expression

"Processing Qualified Expressions"
(expression)
"Parenthetical Expressions"

Parenthetical Expressions

A primary can be an expression enclosed in parentheses. An element that represents a parenthesized expression has an Element_Kinds of A_Parenthesized_Expression. You can obtain the enclosed expression, which itself can be parenthesized, with the Expression_Parenthesized function.

Processing Operators

Operators are defined by the following syntax:

Ada83 LRM 4.5, Ada95 LRM 4.5

 logical_operator ::= and | or | xor

 relational_operator ::= =
   | /= | < | <= | > | >=

 binary_adding_operator ::= + | - | &

 unary_adding_operator ::= + | -

 multiplying_operator ::= * | / | mod | rem

 highest_precedence_operator ::= ** | abs | not

Operators are defined in terms of function calls having one or two parameters. An element representing a function call has an Expression_Kinds of A_Function_Call. The prefix of a function call corresponds to the name of the function. The name of an operator has an Expression_Kinds of An_Operator_Symbol. You can obtain the prefix with the Prefix function.

To determine which operator is represented by the element returned from the Prefix function, you can pass it to the Opera-tor_Kind function. This function returns an Operator_Kinds value indicating which operator has been specified or Not_An_Oper-ator if the function call is not to an operator.

Functions representing operators can be implicitly created, explicitly created, or derived. The Operator_Kind function makes no distinction based on the origin of the declaration of the function call. Implicitly created and derived functions are described in "Processing Implicit Subprograms."

Operators can be specified in infix notation or prefix notation. You can call the Is_Prefix_Call function to determine which method was used. However, not all ASIS implementations are able to detect the use of prefix notation. See Environment.Is-_Prefix_Call_Supported for more information.

Processing Implicit Subprograms

For each form of type declaration, certain of the operators described in "Processing Operators" are predefined —— that is, they are implicitly declared by the type declaration (Ada83 LRM 4.5, Ada95 LRM 4.5). For discrete type declarations, certain attribute functions are also implicitly declared and considered to be predefined (Ada83 LRM , Ada95 LRM 3.5.5).

Certain subprograms are said to be derivable. Derivable subprograms are those that have a parameter or result of a particular subtype. When a type is derived from the subtype, these derivable subprograms are implicitly declared.

You can determine whether a function call represents a call to a predefined operator or attribute function by calling the Is_Predefined function.

You can determine whether a function call represents a call to an implicitly defined subprogram by calling the Is_Implicit function. All elements that make up an implicitly defined subprogram declaration test as Declarations.Is_Part_Of_Implicit.

You can determine whether a function call is to a derived subprogram by calling the Is_Derived function. All function calls to derived subprograms also test as Is_Implicit. All elements that make up a derived subprogram declaration test as Declarations.Is_Part_Of_Derived.

For calls to derived subprograms:

For more information on implicit and derived operations, refer to package Declarations, "Processing Implicit and Derived Operations."

Processing Special Operations

Ada defines two additional classes of operators beyond those described in Ada83 LRM 4.5, Ada95 LRM 4.5:

ASIS refers to these operators as special operations.

Special operations are represented by an element having an Expression_Kinds of A_Special_Operation.

You can call the Special_Operation_Kind function to determine which special operation is represented. Detailed descriptions of the applicable functions and processing for special operations are located in "Processing Short-Circuit Control Forms" and "Processing Membership Tests."

Special operations cannot be overloaded and are not defined in terms of a function declaration. The Function_Call_Parameters function cannot be used with special operators. Instead, functions are available to return the left and right parameter values individually.

Processing Short-Circuit Control Forms

Expressions are defined by the following syntax:

Ada83 LRM 4.4, Ada95 LRM 4.4

 expression ::=
   relation {and relation}
  | relation {and then relation}
  | relation {or relation}
  | relation {[or else relation}
  | relation {xor relation}

The reserved words and then and or else represent the short-circuit control forms.

The components of the short-circuit control forms can be obtained by calling the subprograms in the following table:
Information Desired
Call to Use
relation (left side)
Special_Operation_Left_Hand-_Side
relation (right side)
Short_Circuit_Operation_Right-_Hand_Side

Processing Membership Tests

Relations are defined by the following syntax:

Ada83 LRM 4.4, Ada95 LRM 4.4

 relation ::=
   simple_expression
    [relational_operator simple_expression]
  | simple_expression [not] in range
  | simple_expression [not] in type_mark

The reserved words in and not in represent membership tests.

The components of membership tests can be obtained by calling the subprograms in the following table:
Information Desired
Call to Use
simple_expression
Special_Operation_Left-_Hand_Side
range
In_Range_Operation_Right-_Hand_Side
type_mark
In_Type_Operation_Right-_Hand_Side

Processing Type Conversions

Type conversions are defined by the following syntax:

Ada83 LRM 4.6, Ada95 LRM 4.6

 type_conversion ::= type_mark(expression)

The element representing a type conversion has an Expression_Kinds of A_Type_Conversion.

The components can be obtained by calling the subprograms in the following table:
Information Desired
Call to Use
type_mark
Type_Mark
expression
Converted_Or_Qualified-_Expression

Processing Qualified Expressions

Qualified expressions are defined by the following syntax:

Ada83 LRM 4.7, Ada95 LRM 4.7 

qualified_expression ::=
  type_mark'(expression) | type_mark'aggregate

The element representing a qualified expression has an Expression_Kinds of A_Qualified_Expression.

The components can be obtained by calling the subprograms in the following table:
Information Desired
Call to Use
type_mark
Type_Mark
expression
Converted_Or_Qualified-_Expression
aggregate
Converted_Or_Qualified-_Expression

Processing Allocators

Allocators are defined by the following syntax:

Ada83 LRM 4.8, Ada95 LRM 4.8 

allocator ::=
  new subtype_indication
   | new qualified_expression

The element representing an allocator has an Expression_Kinds of An_Allocation_From_Subtype or An_Allocation_From_Quali-fied_Expression.

The components and related information can be obtained by calling the subprograms in the following table:
Information Desired
Call to Use
subtype_indication
Allocation_Type
qualified_expression
Qualified_Object_Expression

Processing Static and Universal Expressions

Certain expressions of a scalar type are said to be static. Similarly, certain discrete ranges are said to be static, and the type marks of certain scalar subtypes are said to denote static subtypes (Ada83 LRM 4.9, Ada95 LRM 4.9).

You can determine whether an expression is static by calling the Is_Static function. If an expression is static, you can obtain the value of the expression by calling the Static_Value function.

A universal expression is either an expression that delivers a result of type universal integer or one that delivers a result of type universal real (Ada83 LRM 4.10, Ada95 LRM 4.9.1).

You can call the Is_Universal function to determine whether an expression represents a universal expression.

A universal expression can be static. You can call the Is_Static and Static_Value functions with universal expressions.

Processing Use Clauses

Use clauses are defined by the following syntax:

Ada83 LRM 8.4, Ada95 LRM 8.4

 use_clause ::=
  use package_name {, package_name};

You can obtain the list of packages named in a use clause with the Named_Packages function.


Rational Software Corporation  http://www.rational.com
support@rational.com
techpubs@rational.com
Copyright © 1993-2001, Rational Software Corporation. All rights reserved.
TOC PREV NEXT INDEX DOC LIST MASTER INDEX TECHNOTES APEX TIPS