8 Language specification 8.1 General organization
8.24 Eradicating void calls
Informative text
In the object-oriented style of programming the basic unit of computation is a qualified feature call x
.
f (args)which applies the feature f, with the given arguments args, to the object attached to x. But x can be a reference, and that reference can be void. Then there is no object attached to x. An attempt to execute the call would fail, triggering an exception.
If permitted to occur, void calls are a source of instability and crashes in object-oriented programs.
For other potential run-time accidents such as type mismatches, the compilation process spots the errors and refuses to generate executable code until they’ve all been corrected. Can we do the same for void calls?
Eiffel indeed provides a coordinated set of techniques that guarantee the absence of void calls at execution time. The actual rules are specific conditions of more general validity constraints — in particular on attachment and qualified calls — appearing elsewhere; in the following discussion we look at them together from the viewpoint of ensuring their common goal: precluding void calls.
The basic idea is simple. Its the combination of three rules:
• A qualified call x
.
f (args) is target-valid — a required part of being plain valid — if the type of x is attached, “Attached” is here a static property, deduced from the declaration of x (or, if it is a complex expression, of its constituents).• A reference type with a name in the usual form, T, is attached. To obtain a detachable type — meaning that Void is a valid value — use ?T.
• The validity rules ensure that attached types — those without a ? — deserve their name: an entity declared as x: T can never take on a void value at execution time. In particular, you may not assign to x a detachable value, or if x is a formal argument to a routine you may not call it with a detachable actual. (With a detachable target, the other way around, you are free to use an attached or detachable source.)
End 8.24.1 Syntax: Object test
Object_test
=
Δ "{" Identifier ":" Type "}" ExpressionInformative text
An Object_test of the form {x: T} exp, where exp is an expression, T is a type and x is a name different from those of all entities of the enclosing context, is a boolean-valued expression; its value is true if and only exp is attached to an instance of T (hence, non-void). In addition, evaluating the expression has the effect of letting x denote that value of exp over the execution of a neighboring part of the text known as the scope of the Object_test. For example, in if {x: T} exp then c1 else c2 end the scope of the Object_test is the compound in the then part, c1. Within c1, you may use x as a Read_only entity, knowing that it has the value exp had on evaluation of the Object_test, that this value is of type T, and that it cannot be changed during the execution of c1.
The following rules define these notions precisely.
End 8.24.2 Definition: Object-Test Local
The Object-Test Local of an Object_test is its Identifier component.
8.24.3 Validity: Object Test rule Validity code: VUOT
An Object_test ot of the form {x: T} exp is valid if and only if it satisfies the following conditions:
1 x does not have the same lower name as any feature of the enclosing class, or any formal argument or local variable of any enclosing feature or Inline_agent, or, if ot appears in the scope of any other Object_test, its Object-Test Local.
2 T is an attached type.
Informative text
Condition 2 reflects the intent of an Object_test: to test whether an expression is attached to an instance of a given type. It would make no sense then to use a detachable type.
End
8.24.4 Definition: Conjunctive, disjunctive, implicative;
Term, semistrict term
Consider an Operator_expression e of boolean type, which after resolution of any ambiguities through precedence rules can be expressed as a1 § a2 §… § an for n ≥ 1, where § represents boolean operators and every ai, called a term, is itself a valid Boolean_expression. Then e is:
• Conjunctive if every § is either and or and then.
• Disjunctive if every § is either or or or else.
• Implicative if n = 2 and § is implies.
A term ai is semistrict if in the corresponding form it is followed by a semistrict operator.
8.24.5 Definition: Scope of an Object-Test Local
The scope of the Object-Test Local of an Object_test ot includes any applicable program element from the following:
1 If ot is a semistrict term of a conjunctive expression: any subsequent terms.
2 If ot is a term of an implicative expression: the next term.
3 If not ot is a semistrict term of a disjunctive expression e: any subsequent terms.
4 If ot is a term of a conjunctive expression serving as the Boolean_expression in the Then_part in a Conditional: the corresponding Compound.
5 If not ot is a term of a disjunctive expression serving as the Boolean_expression in the Then_part in a Conditional: any subsequent Then_part and Else_clause.
6 If not ot is a term of a disjunctive expression serving as the Exit_condition in a Loop: the Loop_body.
7 If ot is a term of a conjunctive expression used as Unlabeled_assertion_clause in a Precondition: the subsequent components of the Attribute_or_routine.
8 If ot is a term of a conjunctive expression used as Unlabeled_assertion_clause in a Check: the subsequent components of its enclosing Compound.
Informative text
The definition ensures that, for an Object_test {x: T} exp, we can rest assured that, throughout its scope, x will never at run time have a void value, and hence can be used as the target of a call.
End 8.24.6 Semantics: Object Test semantics
The value of an Object_test {x: T} exp is true if the value of exp is attached to an instance of T, false otherwise.
Informative text
In particular, if x is void (which is possible only if T is a detachable type), the result will be false.
End 8.24.7 Semantics: Object-Test Local semantics
For an Object_test {x: T} exp, the value of x, defined only over its scope, is the value of exp at the time of the Object_test’s evaluation.
8.24.8 Definition: Read-only void test
A read-only void test is a Boolean_expression of one of the forms e = Void and e /= Void, where e is a read-only entity.
8.24.9 Definition: Scope of a read-only void test
The scope of a read-only void test appearing in a class text, for e of type T, is the scope that the Object-Test Local ot would have if the void test were replaced by:
1 For e = Void: not ({ot: T} e).
2 For e /= Void: {ot: T} e.
Informative text
This is useful if T is a detachable type, providing a simple way to generalize the notion of scope to common schemes such as if e /= Void then …, where we know that e cannot be void in the Then_part. Note that it is essential to limit ourselves to read-only entities; for a variable, or an expression involving a variable, anything could happen to the value during the execution of the scope even if e is initially not void.
Of course one could always write an Object_test instead, but the void test is a common and convenient form, if only because it doesn’t require repeating the type T of e, so it will be important to handle it as part of the Certified Attachment Patterns discussed next.
End 8.24.10 Definition: Certified Attachment Pattern
A Certified Attachment Pattern (or CAP) for an expression exp whose type is detachable is an occurrence of exp in one of the following contexts:
1 exp is an Object-Test Local and the occurrence is in its scope.
2 exp is a read-only entity and the occurrence is in the scope of a void test involving exp.
Informative text
A CAP is a scheme that has been proved, or certified by sufficiently many competent people (or computerized proof tools), to ensure that exp will never have a void run-time value in the covered scope.
• The CAPs listed here are the most frequently useful and seem beyond doubt. Here too compilers could be “smart” and find other cases making exp
.
f safe. The language specification explicitly refrains, however, from accepting such supposed compiler improvements: other than the risk of mistake in the absence of a public discussion, this would result in some Eiffel texts being accepted by certain compilers and rejected by others. Instead, a compiler that accepts a call to a detachable target that is not part of one of the official CAPs listed above is non-conformant.• The list of CAPs may grow in the future, as more analysis is applied to actual systems, leading to the identification, and certification by human or automatic means, of safe patterns for using targets of detachable types.
End 8.24.11 Definition: Attached expression
An expression exp of type T is attached if it satisfies any of the following conditions:
1 T is attached.
2 T is expanded.
3 exp appears in a Certified Attachment Pattern for exp.
Informative text
This is the principal result of this discussion: the condition under which an expression is target-valid, that is to say, can be used as target of a call because its value is guaranteed never to be void at any time of evaluation. It is in an expanded type’s nature to abhor a void; attached types are devised to avoid void too; and Certified Attachment Patterns catch a detachable variable when it is provably not detached.
End