[[Property:title|ET: Instructions (beta)]] [[Property:link_title|ET: Instructions]] [[Property:weight|-6]] [[Property:uuid|628bf3db-728f-0b3c-bdbb-fe52deaae5b7]] ==Instructions== Eiffel has a remarkably small set of instructions. The basic computational instructions have been seen: creation, assignment, assignment attempt, procedure call, retry. They are complemented by control structures: conditional, multi-branch, loop, as well as debug and check. ===Conditional=== A conditional instruction has the form if ... then ... elseif ... then ... else ... end The elseif ... then ... part (of which there may be more than one) and the else ... part are optional. After if and elseif comes a boolean expression; after then and else come zero or more instructions. ===Multi-branch=== A multi-branch instruction has the form inspect exp when v1 then inst when v2 then inst2 ... else inst0 end where the else inst0 part is optional, exp is a character or integer expression, v1, v1, ... are constant values of the same type as exp, all different, and inst0, inst1, inst2, ... are sequences of zero or more instructions. The effect of such a multi-branch instruction, if the value of exp is one of the vi, is to execute the corresponding insti. If none of the vi matches, the instruction executes inst0, unless there is no else part, in which case it triggers an exception. {{note|Raising an exception is the proper behavior, since the absence of an else indicates that the author asserts that one of the values will match. If you want an instruction that does nothing in this case, rather than cause an exception, use an else part with an empty inst0. In contrast, if c then inst end with no else part does nothing in the absence of an else part, since in this case there is no implied claim that c must hold. }} ===Loop=== The loop construct provides a flexible framework for doing iterative computation. Its flexibility lies in how the complete form can be tailored and simplified for certain purposes by omitting optional parts. We will explore the entire mechanism, but let's approach things a little at a time. First let's look at the loop in what is probably its most commonly usage. This is a case in which some parts of the loop construct have been omitted because they are not necessary. So, just remember that you are not seeing everything that loops can be in this example. from Initialization until Exit_condition loop Loop_body end Initialization and Loop_body are sequences of zero or more instructions; Exit_condition is a boolean expression. The effect is to execute Initialization, then, zero or more times until Exit_condition is satisfied, to execute Loop_body. (If after Initialization the value of Exit_condition is already true, Loop_body will not be executed at all.) This form of the loop is used commonly to traverse data structures. For example, suppose that we wished to print every element in a linked list of strings. We can do so with this usage of the loop construct, as shown below. my_list: LINKED_LIST [STRING] ... from my_list.start until my_list.off loop print (my_list.item) my_list.forth end The Initialization part will attempt to set the cursor at the first item of the list. The loop will exit when there is no active list item. Then, in the Loop_body, the current list item will be printed, and the cursor advanced. ===Debug=== An occasionally useful instruction is debug (''Debug_key'', ... ) ''instructions'' end where ''instructions'' is a sequence of zero or more instructions and the part in parentheses is optional, containing if present one or more strings, called debug keys. The EiffelStudio compiler lets you specify the corresponding debug compilation option: yes, no, or an explicit debug key. The ''instructions'' will be executed if and only if the corresponding option is on. The obvious use is for instructions that should be part of the system but executed only in some circumstances, for example to provide extra debugging information. ===Check=== The final instruction is connected with Design by Contract™. The instruction check Assertion end where Assertion is a sequence of zero or more assertions, will have no effect unless assertion monitoring is turned on at the Check level or higher. If so it will evaluate all the assertions listed, having no further effect if they are all satisfied; if any one of them does not hold, the instruction will trigger an exception. This instruction serves to state properties that are expected to be satisfied at some stages of the computation -- other than the specific stages, such as routine entry and exit, already covered by the other assertion mechanisms such as preconditions, postconditions and invariants. A recommended use of check involves calling a routine with a precondition, where the call, for good reason, does not explicitly test for the precondition. Consider a routine of the form r (ref: SOME_REFERENCE_TYPE) require not_void: ref /= Void do ref.some_feature ... end Because of the call to some_feature, the routine will only work if its precondition is satisfied on entry. To guarantee this precondition, the caller may protect it by the corresponding test, as in if x /= Void then a.r (x) end but this is not the only possible scheme; for example if an create x appears shortly before the call we know x is not void and do not need the protection. It is a good idea in such cases to use a check instruction to document this property, if only to make sure that a reader of the code will realize that the omission of an explicit test (justified or not) was not a mistake. This is particularly appropriate if the justification for not testing the precondition is less obvious. For example x could have been obtained, somewhere else in the algorithm, as clone (y) for some y that you know is not void. You should document this knowledge by writing the call as check x_not_void: x /= Void -- Because x was obtained as a clone of y, -- and y is not void because [etc.] end a.r (x) {{recommended|An extra indentation of the check part to separate it from the algorithm proper; and inclusion of a comment listing the rationale behind the developer's decision not to check explicitly for the precondition. }} In production mode with assertion monitoring turned off, this instruction will have no effect. But it will be precious for a maintainer of the software who is trying to figure out what it does, and in the process to reconstruct the original developer's reasoning. (The maintainer might of course be the same person as the developer, six months later.) And if the rationale is wrong somewhere, turning assertion checking on will immediately uncover the bug.